From patchwork Wed Apr 22 16:18:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E5E3C55185 for ; Wed, 22 Apr 2020 16:21:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4C3C020776 for ; Wed, 22 Apr 2020 16:21:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="1y/PUmYN" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726877AbgDVQVy (ORCPT ); Wed, 22 Apr 2020 12:21:54 -0400 Received: from esa1.microchip.iphmx.com ([68.232.147.91]:23983 "EHLO esa1.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726498AbgDVQVv (ORCPT ); Wed, 22 Apr 2020 12:21:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587572510; x=1619108510; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=PD8IUS1EdZAMiLoRRlRU8vrEN2R88F6dLZkoxx8iJGI=; b=1y/PUmYNc8x2qNnPAuuCV34h3zrvMUILvtyaUFP5nS1Cgopf2R0U6N+T jlSRsA6RbShV4tVQCLxm6E6mbAovM9BA7qk68Z3IrVDBksBR5Q1E51g1H ppiwbyiZCMTc2WOTgfpQQiWnoS2VAiWzgxH5Bh6/GIJ20PC1lXTDKgd9y Vi76TpOmgzOXz4tPp7dBZqCX0nO3686ThIVedtjViV2UNg2JmD0qs9xhQ Rcp5RCZuY3sR5/LJIB3J2Zux76uEVbpV9zS3taTxjJGMGodOb2xHlOWXM 1XGiqSdlpSbboJT3TPSh3kvS6ctZO8AjJmadauaZJCEhoOiPrnwCvMiau Q==; IronPort-SDR: balzNi6XcS3EdcDjIm7WHQ3S4KTxbweFy2PPSew945s3xWqdhVaWzcFCCAxfeCiLmL90EfzuA1 59CVxW+EEitXgpsmZ6oE5Um3rFt6BqvaexKX0MEPGr1tzsSKnSHUzK7VX9yJrbue7ZO8nCifAO hGJQCRCV5tMIy4Iiy5crG2UL5qt4IFWHmR+2yRXPpejR11KOHn6OfrhqX19rOUQnqQqZLpioh8 8wmE1fnINZw+FS+i81KBYax8mF3mawta4BxJllE88tBbaWCe4iSzaODjKpG5SB3uvbvlb5zOzK YVQ= X-IronPort-AV: E=Sophos;i="5.73,304,1583218800"; d="scan'208";a="76894561" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa1.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 22 Apr 2020 09:21:50 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 22 Apr 2020 09:21:49 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Wed, 22 Apr 2020 09:21:49 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v3 03/11] bridge: mrp: Extend bridge interface Date: Wed, 22 Apr 2020 18:18:25 +0200 Message-ID: <20200422161833.1123-4-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200422161833.1123-1-horatiu.vultur@microchip.com> References: <20200422161833.1123-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org To integrate MRP into the bridge, first the bridge needs to be aware of ports that are part of an MRP ring and which rings are on the bridge. Therefore extend bridge interface with the following: - add new flag(BR_MPP_AWARE) to the net bridge ports, this bit will be set when the port is added to an MRP instance. In this way it knows if the frame was received on MRP ring port - add new flag(BR_MRP_LOST_CONT) to the net bridge ports, this bit will be set when the port lost the continuity of MRP Test frames. - add a list of MRP instances Signed-off-by: Horatiu Vultur --- include/linux/if_bridge.h | 2 ++ net/bridge/br_private.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 9e57c4411734..b3a8d3054af0 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -47,6 +47,8 @@ struct br_ip_list { #define BR_BCAST_FLOOD BIT(14) #define BR_NEIGH_SUPPRESS BIT(15) #define BR_ISOLATED BIT(16) +#define BR_MRP_AWARE BIT(17) +#define BR_MRP_LOST_CONT BIT(18) #define BR_DEFAULT_AGEING_TIME (300 * HZ) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1f97703a52ff..835a70f8d3ea 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -428,6 +428,10 @@ struct net_bridge { int offload_fwd_mark; #endif struct hlist_head fdb_list; + +#if IS_ENABLED(CONFIG_BRIDGE_MRP) + struct list_head __rcu mrp_list; +#endif }; struct br_input_skb_cb { From patchwork Wed Apr 22 16:18:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220741 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9DCBC5518B for ; Wed, 22 Apr 2020 16:22:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C99232076E for ; Wed, 22 Apr 2020 16:22:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="uCpnBChu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726930AbgDVQWF (ORCPT ); Wed, 22 Apr 2020 12:22:05 -0400 Received: from esa2.microchip.iphmx.com ([68.232.149.84]:21023 "EHLO esa2.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726584AbgDVQVx (ORCPT ); Wed, 22 Apr 2020 12:21:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587572513; x=1619108513; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=j9vuAzMiBC0XIenmNk+Q7ztffNdq+mbfWZ9t9r+B3uw=; b=uCpnBChuSrTlZinFsPBj9u5ma13AdxsiFjMJdQbQxIjY0KAqoKnhFdIL LG/TcNWqRv+yjS7tkMVxeflquMBC5mJv3VPY3fvcvu3+GZK89KfJabIGz 1ZqG9C4kx1bwwNCApo2ZfNgt8DhbEO2ZetOcmnW9/qbyAsaiKBQ8Ep4Fx 1pQhegpe6BgzIzLRRZqwfLPviGuM6idcDWzK4R1NT9dxB0K5RUIOWJfZ4 1gaoI+CNup6IOPbMZivxjf4Hu+nRI/3hNEQsbHHlH5Et7nraMMUudfk0R amPZhsGCduZMVqBAnmoMbXmUBsc+NGIs5pt8b5TckASIutY38w9VCG9nE Q==; IronPort-SDR: 05wpkENByLm+AofgDAwhbMxKzmDBej05vmCmALEw0EZDJKlY9LLCinmIt3ODGt2ynMjUPBYETP 55pZ/rLa8x+HrlNLHEpAdcnG8aHHV6Rhq4jmdjmzzXTX8cTGeECWRaTL481LUg8+eQdoixn47g y/JjRHyKLYQGeP3tKYHFy/W9tb6VLQLCIODBhoaS9+L4YT+sTzy+PPLHtKB3To96z2nJ1qITyV k4GuvK0dWMN6Jf+zEI82H1NUmNi1NuGk9k8+7uBwTXE0RepWzv0IeP7RAKDwpC51g6dV/9eEXj gGI= X-IronPort-AV: E=Sophos;i="5.73,304,1583218800"; d="scan'208";a="73007283" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 22 Apr 2020 09:21:52 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 22 Apr 2020 09:21:52 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Wed, 22 Apr 2020 09:21:52 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v3 04/11] net: bridge: Add port attribute IFLA_BRPORT_MRP_RING_OPEN Date: Wed, 22 Apr 2020 18:18:26 +0200 Message-ID: <20200422161833.1123-5-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200422161833.1123-1-horatiu.vultur@microchip.com> References: <20200422161833.1123-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds a new port attribute, IFLA_BRPORT_MRP_RING_OPEN, which allows to notify the userspace when the port lost the continuite of MRP frames. This attribute is set by kernel whenever the SW or HW detects that the ring is being open or closed. Signed-off-by: Horatiu Vultur --- include/uapi/linux/if_link.h | 1 + net/bridge/br_netlink.c | 3 +++ tools/include/uapi/linux/if_link.h | 1 + 3 files changed, 5 insertions(+) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 61e0801c82df..4a295deb933b 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -343,6 +343,7 @@ enum { IFLA_BRPORT_NEIGH_SUPPRESS, IFLA_BRPORT_ISOLATED, IFLA_BRPORT_BACKUP_PORT, + IFLA_BRPORT_MRP_RING_OPEN, __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 43dab4066f91..4084f1ef8641 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -151,6 +151,7 @@ static inline size_t br_port_info_size(void) + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MULTICAST_ROUTER */ #endif + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_GROUP_FWD_MASK */ + + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_RING_OPEN */ + 0; } @@ -213,6 +214,8 @@ static int br_port_fill_attrs(struct sk_buff *skb, nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) || nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS, !!(p->flags & BR_NEIGH_SUPPRESS)) || + nla_put_u8(skb, IFLA_BRPORT_MRP_RING_OPEN, !!(p->flags & + BR_MRP_LOST_CONT)) || nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED))) return -EMSGSIZE; diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h index 024af2d1d0af..70dae9ba16f4 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -343,6 +343,7 @@ enum { IFLA_BRPORT_NEIGH_SUPPRESS, IFLA_BRPORT_ISOLATED, IFLA_BRPORT_BACKUP_PORT, + IFLA_BRPORT_MRP_RING_OPEN, __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) From patchwork Wed Apr 22 16:18:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220739 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDACBC54FCB for ; Wed, 22 Apr 2020 16:22:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B955F2076E for ; Wed, 22 Apr 2020 16:22:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="jmQLE9wg" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727065AbgDVQWY (ORCPT ); Wed, 22 Apr 2020 12:22:24 -0400 Received: from esa1.microchip.iphmx.com ([68.232.147.91]:24020 "EHLO esa1.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726983AbgDVQWP (ORCPT ); Wed, 22 Apr 2020 12:22:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587572534; x=1619108534; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=Wk5W6JOrVyShu0Bu566DjA/nJMtV0L8hDnh56QYpSOM=; b=jmQLE9wgjbiL8EeJkGRIzLxAA4ApiptlkMb25lSkLEE4MyxdLRoJkXpz wuGjOC1RUbQiLUzxa02oAnGH2yEEsRFY6XekS5VdBO+D+fPLlgYtcV+B3 gsMlH0PkYNvQLJs5nrL7LeuT4lYcY4YXEgCWcEFk0/Fl8gywDA4/FMIzK oCbGAyz8Ui0lmihZDebpQuqU9JT0LKHOtKChidTrHN5rFGW1DhI7Libdo 0gPRQb5vmRK7UHVl5uJPff33BJfdonfdPZNFjn6h7DldR1uCi4OfWrmH3 1gvlNC+ETywsBvkPJl/nWCTmv2Y7O3xBflRAxUIdA9FAzb+7HaJfL+ZcR A==; IronPort-SDR: BkKNcp0cleGm0x3/bUdbWeDy4sliKg8MOaf2LvpHeGhHLpDZgBqlPXHH8v0H7xvHft7peBbiIN 7j7mBDMG0fstXPWi2KLBFbxKO1MV+THo+1tguC26Fyt3PxPjjIQY6IKkrOe4wvw2Fj/ZP1oXnn Nj+3dAgUQB4XyGVYHnP3rz0nsBMlkBtoWJb3PfZ2PNbIYgJioQg8mk3hcDYzeZVhrwkvAWlJZL BGYoP5DOQInCUGjB+D3RZkHYV9u5xskQS6kOBffNpP0CCwAr/mp6m8hjd637m8WWJiLwN5nMdg za8= X-IronPort-AV: E=Sophos;i="5.73,304,1583218800"; d="scan'208";a="76894600" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa1.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 22 Apr 2020 09:21:58 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 22 Apr 2020 09:21:58 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Wed, 22 Apr 2020 09:21:57 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v3 06/11] switchdev: mrp: Extend switchdev API to offload MRP Date: Wed, 22 Apr 2020 18:18:28 +0200 Message-ID: <20200422161833.1123-7-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200422161833.1123-1-horatiu.vultur@microchip.com> References: <20200422161833.1123-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Extend switchdev API to add support for MRP. The HW is notified in following cases: SWITCHDEV_OBJ_ID_MRP: This is used when a MRP instance is added/removed from the MRP ring. SWITCHDEV_OBJ_ID_RING_ROLE_MRP: This is used when the role of the node changes. The current supported roles are MRM and MRC. SWITCHDEV_OBJ_ID_RING_TEST_MRP: This is used when to start/stop sending MRP_Test frames on the mrp ring ports. This is called only on nodes that have the role MRM. In case this fails then the SW will generate the frames. SWITCHDEV_OBJ_ID_RING_STATE_STATE: This is used when the ring changes it states to open or closed. This is required to notify HW because the MRP_Test frame contains the field MRP_InState which contains this information. SWITCHDEV_ATTR_ID_MRP_PORT_STATE: This is used when the port's state is changed. It can be in blocking/forwarding mode. SWITCHDEV_ATTR_ID_MRP_PORT_ROLE: This is used when port's role changes. The roles of the port can be primary/secondary. This is required to notify HW because the MRP_Test frame contains the field MRP_PortRole that contains this information. Signed-off-by: Horatiu Vultur --- include/net/switchdev.h | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index aee86a189432..ae7aeb0d1f9c 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -40,6 +40,10 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED, SWITCHDEV_ATTR_ID_BRIDGE_MROUTER, +#if IS_ENABLED(CONFIG_BRIDGE_MRP) + SWITCHDEV_ATTR_ID_MRP_PORT_STATE, + SWITCHDEV_ATTR_ID_MRP_PORT_ROLE, +#endif }; struct switchdev_attr { @@ -55,6 +59,11 @@ struct switchdev_attr { clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ bool mc_disabled; /* MC_DISABLED */ +#if IS_ENABLED(CONFIG_BRIDGE_MRP) + u8 mrp_port_state; /* MRP_PORT_STATE */ + u8 mrp_port_role; /* MRP_PORT_ROLE */ + u8 mrp_ring_state; /* MRP_RING_STATE */ +#endif } u; }; @@ -63,6 +72,12 @@ enum switchdev_obj_id { SWITCHDEV_OBJ_ID_PORT_VLAN, SWITCHDEV_OBJ_ID_PORT_MDB, SWITCHDEV_OBJ_ID_HOST_MDB, +#if IS_ENABLED(CONFIG_BRIDGE_MRP) + SWITCHDEV_OBJ_ID_MRP, + SWITCHDEV_OBJ_ID_RING_TEST_MRP, + SWITCHDEV_OBJ_ID_RING_ROLE_MRP, + SWITCHDEV_OBJ_ID_RING_STATE_MRP, +#endif }; struct switchdev_obj { @@ -94,6 +109,53 @@ struct switchdev_obj_port_mdb { #define SWITCHDEV_OBJ_PORT_MDB(OBJ) \ container_of((OBJ), struct switchdev_obj_port_mdb, obj) + +#if IS_ENABLED(CONFIG_BRIDGE_MRP) +/* SWITCHDEV_OBJ_ID_MRP */ +struct switchdev_obj_mrp { + struct switchdev_obj obj; + struct net_device *p_port; + struct net_device *s_port; + u32 ring_id; +}; + +#define SWITCHDEV_OBJ_MRP(OBJ) \ + container_of((OBJ), struct switchdev_obj_mrp, obj) + +/* SWITCHDEV_OBJ_ID_RING_TEST_MRP */ +struct switchdev_obj_ring_test_mrp { + struct switchdev_obj obj; + /* The value is in us and a value of 0 represents to stop */ + u32 interval; + u8 max_miss; + u32 ring_id; + u32 period; +}; + +#define SWITCHDEV_OBJ_RING_TEST_MRP(OBJ) \ + container_of((OBJ), struct switchdev_obj_ring_test_mrp, obj) + +/* SWICHDEV_OBJ_ID_RING_ROLE_MRP */ +struct switchdev_obj_ring_role_mrp { + struct switchdev_obj obj; + u8 ring_role; + u32 ring_id; +}; + +#define SWITCHDEV_OBJ_RING_ROLE_MRP(OBJ) \ + container_of((OBJ), struct switchdev_obj_ring_role_mrp, obj) + +struct switchdev_obj_ring_state_mrp { + struct switchdev_obj obj; + u8 ring_state; + u32 ring_id; +}; + +#define SWITCHDEV_OBJ_RING_STATE_MRP(OBJ) \ + container_of((OBJ), struct switchdev_obj_ring_state_mrp, obj) + +#endif + typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); enum switchdev_notifier_type { From patchwork Wed Apr 22 16:18:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220740 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02DA2C54FCB for ; Wed, 22 Apr 2020 16:22:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CA01C2076E for ; Wed, 22 Apr 2020 16:22:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="bwyxzhzi" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727014AbgDVQWU (ORCPT ); Wed, 22 Apr 2020 12:22:20 -0400 Received: from esa1.microchip.iphmx.com ([68.232.147.91]:24020 "EHLO esa1.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726685AbgDVQWR (ORCPT ); Wed, 22 Apr 2020 12:22:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587572536; x=1619108536; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=OFYsE4ajPoCEgwn80uXjmikgNtEGyhguwpXN6OxgLuc=; b=bwyxzhzilWWIavPwk4DNEb3CPbTi+wvWDzbP5JCuiOh3Siyqv0I1Vb72 xqeqq6wBw19ZaQNQbBtotNVLJHU33U/MOYRwmgO9sC//7K1pHrqrHGQUD 94/nAuWLwEtUhkWTwfTDb3oFr15ynl+xjZabm3ld79NibvgvWHDV+Jtd6 g7phKx+7nXfHYcDj71pvTFX66Qo0z3zmFQiZmGXCwJx2AVfYmLgt/HVPq dK9oZDOsIHZjMVsKy7MbzAVPQvgAxOTVIp5Vyp3bPyLUP6yxHCMr01EV+ /HCaJyEkVivCQs8CJ8HkLzr5fDRHxN+IXgOOlOv4SF3y5hZRgPdbZ4RAH Q==; IronPort-SDR: LO9HbH4CBebomcp8CpQPOtrjPRWMZrU8jKniLHR6uQQu5AOxQfNqu4fpCSsBeT7xFVrrYw/tF+ FGgdxc61B+kpKrcedcgh/6g9LOViwNYgmwruKp7hFk2iiDzd0jwGoEju2mCHSZaFxHMzCMQeQF ffjkmhvlPSDLOpXzGFQ+ouibthSyfDUObyUYq2qjwVUSIbveT9OqvkEV2aUgAiZ8OEBZ+eNCwP 0dWDYI5PtrhBZqp/uezeEXsoKGhlPhpOh4ME2csEO0L1UX9lJ4jjXwH6xiJX8PNTVUj1kCDW5N X3Y= X-IronPort-AV: E=Sophos;i="5.73,304,1583218800"; d="scan'208";a="76894635" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa1.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 22 Apr 2020 09:22:03 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 22 Apr 2020 09:22:06 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Wed, 22 Apr 2020 09:22:03 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v3 08/11] bridge: mrp: Connect MRP API with the switchdev API Date: Wed, 22 Apr 2020 18:18:30 +0200 Message-ID: <20200422161833.1123-9-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200422161833.1123-1-horatiu.vultur@microchip.com> References: <20200422161833.1123-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implement the MRP API. In case the HW can't generate MRP Test frames then the SW will try to generate the frames. In case that also the SW will fail in generating the frames then a error is return to the userspace. The userspace is responsible to generate all the other MRP frames regardless if the test frames are generated by HW or SW. The forwarding/termination of MRP frames is happening in the kernel and is done by the MRP instance. The userspace application doesn't do the forwarding. Signed-off-by: Horatiu Vultur --- net/bridge/Makefile | 2 +- net/bridge/br_mrp.c | 556 ++++++++++++++++++++++++++++++++++++ net/bridge/br_mrp_netlink.c | 29 ++ 3 files changed, 586 insertions(+), 1 deletion(-) create mode 100644 net/bridge/br_mrp.c create mode 100644 net/bridge/br_mrp_netlink.c diff --git a/net/bridge/Makefile b/net/bridge/Makefile index 3cacf9dd78d5..ccb394236fbd 100644 --- a/net/bridge/Makefile +++ b/net/bridge/Makefile @@ -26,4 +26,4 @@ bridge-$(CONFIG_NET_SWITCHDEV) += br_switchdev.o obj-$(CONFIG_NETFILTER) += netfilter/ -bridge-$(CONFIG_BRIDGE_MRP) += br_mrp_switchdev.o +bridge-$(CONFIG_BRIDGE_MRP) += br_mrp_switchdev.o br_mrp.o br_mrp_netlink.o diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c new file mode 100644 index 000000000000..8b1e85c11e3b --- /dev/null +++ b/net/bridge/br_mrp.c @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "br_private_mrp.h" + +static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 }; + +static struct net_bridge_port *br_mrp_get_port(struct net_bridge *br, + u32 ifindex) +{ + struct net_bridge_port *res = NULL; + struct net_bridge_port *port; + + list_for_each_entry(port, &br->port_list, list) { + if (port->dev->ifindex == ifindex) { + res = port; + break; + } + } + + return res; +} + +static struct br_mrp *br_mrp_find_id(struct net_bridge *br, u32 ring_id) +{ + struct br_mrp *res = NULL; + struct br_mrp *mrp; + + list_for_each_entry_rcu(mrp, &br->mrp_list, list, + lockdep_rtnl_is_held()) { + if (mrp->ring_id == ring_id) { + res = mrp; + break; + } + } + + return res; +} + +static struct br_mrp *br_mrp_find_port(struct net_bridge *br, + struct net_bridge_port *p) +{ + struct br_mrp *res = NULL; + struct br_mrp *mrp; + + list_for_each_entry_rcu(mrp, &br->mrp_list, list, + lockdep_rtnl_is_held()) { + if (rcu_access_pointer(mrp->p_port) == p || + rcu_access_pointer(mrp->s_port) == p) { + res = mrp; + break; + } + } + + return res; +} + +static int br_mrp_next_seq(struct br_mrp *mrp) +{ + mrp->seq_id++; + return mrp->seq_id; +} + +static struct sk_buff *br_mrp_skb_alloc(struct net_bridge_port *p, + const u8 *src, const u8 *dst) +{ + struct ethhdr *eth_hdr; + struct sk_buff *skb; + u16 *version; + + skb = dev_alloc_skb(MRP_MAX_FRAME_LENGTH); + if (!skb) + return NULL; + + skb->dev = p->dev; + skb->protocol = htons(ETH_P_MRP); + skb->priority = MRP_FRAME_PRIO; + skb_reserve(skb, sizeof(*eth_hdr)); + + eth_hdr = skb_push(skb, sizeof(*eth_hdr)); + ether_addr_copy(eth_hdr->h_dest, dst); + ether_addr_copy(eth_hdr->h_source, src); + eth_hdr->h_proto = htons(ETH_P_MRP); + + version = skb_put(skb, sizeof(*version)); + *version = cpu_to_be16(MRP_VERSION); + + return skb; +} + +static void br_mrp_skb_tlv(struct sk_buff *skb, + enum br_mrp_tlv_header_type type, + u8 length) +{ + struct br_mrp_tlv_hdr *hdr; + + hdr = skb_put(skb, sizeof(*hdr)); + hdr->type = type; + hdr->length = length; +} + +static void br_mrp_skb_common(struct sk_buff *skb, struct br_mrp *mrp) +{ + struct br_mrp_common_hdr *hdr; + + br_mrp_skb_tlv(skb, BR_MRP_TLV_HEADER_COMMON, sizeof(*hdr)); + + hdr = skb_put(skb, sizeof(*hdr)); + hdr->seq_id = cpu_to_be16(br_mrp_next_seq(mrp)); + memset(hdr->domain, 0xff, MRP_DOMAIN_UUID_LENGTH); +} + +static struct sk_buff *br_mrp_alloc_test_skb(struct br_mrp *mrp, + struct net_bridge_port *p, + enum br_mrp_port_role_type port_role) +{ + struct br_mrp_ring_test_hdr *hdr = NULL; + struct sk_buff *skb = NULL; + + if (!p) + return NULL; + + skb = br_mrp_skb_alloc(p, p->dev->dev_addr, mrp_test_dmac); + if (!skb) + return NULL; + + br_mrp_skb_tlv(skb, BR_MRP_TLV_HEADER_RING_TEST, sizeof(*hdr)); + hdr = skb_put(skb, sizeof(*hdr)); + + hdr->prio = cpu_to_be16(MRP_DEFAULT_PRIO); + ether_addr_copy(hdr->sa, p->br->dev->dev_addr); + hdr->port_role = cpu_to_be16(port_role); + hdr->state = cpu_to_be16(mrp->ring_state); + hdr->transitions = cpu_to_be16(mrp->ring_transitions); + hdr->timestamp = cpu_to_be32(jiffies_to_msecs(jiffies)); + + br_mrp_skb_common(skb, mrp); + br_mrp_skb_tlv(skb, BR_MRP_TLV_HEADER_END, 0x0); + + return skb; +} + +static void br_mrp_test_work_expired(struct work_struct *work) +{ + struct delayed_work *del_work = to_delayed_work(work); + struct br_mrp *mrp = container_of(del_work, struct br_mrp, test_work); + struct net_bridge_port *p; + bool notify_open = false; + struct sk_buff *skb; + + if (time_before_eq(mrp->test_end, jiffies)) + return; + + if (mrp->test_count_miss < mrp->test_max_miss) { + mrp->test_count_miss++; + } else { + /* Notify that the ring is open only if the ring state is + * closed, otherwise it would continue to notify at every + * interval. + */ + if (mrp->ring_state == BR_MRP_RING_STATE_CLOSED) + notify_open = true; + } + + rcu_read_lock(); + + p = rcu_dereference(mrp->p_port); + if (p) { + skb = br_mrp_alloc_test_skb(mrp, p, BR_MRP_PORT_ROLE_PRIMARY); + if (!skb) + goto out; + + skb_reset_network_header(skb); + dev_queue_xmit(skb); + + if (notify_open && !mrp->ring_role_offloaded) + br_mrp_port_open(p->dev, true); + } + + p = rcu_dereference(mrp->s_port); + if (p) { + skb = br_mrp_alloc_test_skb(mrp, p, BR_MRP_PORT_ROLE_SECONDARY); + if (!skb) + goto out; + + skb_reset_network_header(skb); + dev_queue_xmit(skb); + + if (notify_open && !mrp->ring_role_offloaded) + br_mrp_port_open(p->dev, true); + } + +out: + rcu_read_unlock(); + + queue_delayed_work(system_wq, &mrp->test_work, + usecs_to_jiffies(mrp->test_interval)); +} + +/* Deletes the MRP instance. + * note: called under rtnl_lock + */ +static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp) +{ + struct net_bridge_port *p; + + /* Stop sending MRP_Test frames */ + cancel_delayed_work_sync(&mrp->test_work); + br_mrp_switchdev_send_ring_test(br, mrp, 0, 0, 0); + + br_mrp_switchdev_del(br, mrp); + + /* Reset the ports */ + p = rtnl_dereference(mrp->p_port); + if (p) { + spin_lock_bh(&br->lock); + p->state = BR_STATE_FORWARDING; + p->flags &= ~BR_MRP_AWARE; + spin_unlock_bh(&br->lock); + br_mrp_port_switchdev_set_state(p, BR_STATE_FORWARDING); + rcu_assign_pointer(mrp->p_port, NULL); + } + + p = rtnl_dereference(mrp->s_port); + if (p) { + spin_lock_bh(&br->lock); + p->state = BR_STATE_FORWARDING; + p->flags &= ~BR_MRP_AWARE; + spin_unlock_bh(&br->lock); + br_mrp_port_switchdev_set_state(p, BR_STATE_FORWARDING); + rcu_assign_pointer(mrp->s_port, NULL); + } + + list_del_rcu(&mrp->list); + kfree_rcu(mrp, rcu); +} + +/* Adds a new MRP instance. + * note: called under rtnl_lock + */ +int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance) +{ + struct net_bridge_port *p; + struct br_mrp *mrp; + int err; + + /* If the ring exists, it is not possible to create another one with the + * same ring_id + */ + mrp = br_mrp_find_id(br, instance->ring_id); + if (mrp) + return -EINVAL; + + if (!br_mrp_get_port(br, instance->p_ifindex) || + !br_mrp_get_port(br, instance->s_ifindex)) + return -EINVAL; + + mrp = kzalloc(sizeof(*mrp), GFP_KERNEL); + if (!mrp) + return -ENOMEM; + + mrp->ring_id = instance->ring_id; + + p = br_mrp_get_port(br, instance->p_ifindex); + spin_lock_bh(&br->lock); + p->state = BR_STATE_FORWARDING; + p->flags |= BR_MRP_AWARE; + spin_unlock_bh(&br->lock); + rcu_assign_pointer(mrp->p_port, p); + + p = br_mrp_get_port(br, instance->s_ifindex); + spin_lock_bh(&br->lock); + p->state = BR_STATE_FORWARDING; + p->flags |= BR_MRP_AWARE; + spin_unlock_bh(&br->lock); + rcu_assign_pointer(mrp->s_port, p); + + INIT_DELAYED_WORK(&mrp->test_work, br_mrp_test_work_expired); + list_add_tail_rcu(&mrp->list, &br->mrp_list); + + err = br_mrp_switchdev_add(br, mrp); + if (err) + goto delete_mrp; + + return 0; + +delete_mrp: + br_mrp_del_impl(br, mrp); + + return err; +} + +/* Deletes the MRP instance from which the port is part of + * note: called under rtnl_lock + */ +void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p) +{ + struct br_mrp *mrp = br_mrp_find_port(br, p); + + /* If the port is not part of a MRP instance just bail out */ + if (!mrp) + return; + + br_mrp_del_impl(br, mrp); +} + +/* Deletes existing MRP instance based on ring_id + * note: called under rtnl_lock + */ +int br_mrp_del(struct net_bridge *br, struct br_mrp_instance *instance) +{ + struct br_mrp *mrp = br_mrp_find_id(br, instance->ring_id); + + if (!mrp) + return -EINVAL; + + br_mrp_del_impl(br, mrp); + + return 0; +} + +/* Set port state, port state can be forwarding, blocked or disabled + * note: already called with rcu_read_lock + */ +int br_mrp_set_port_state(struct net_bridge_port *p, + enum br_mrp_port_state_type state) +{ + if (!p || !(p->flags & BR_MRP_AWARE)) + return -EINVAL; + + spin_lock_bh(&p->br->lock); + + if (state == BR_MRP_PORT_STATE_FORWARDING) + p->state = BR_STATE_FORWARDING; + else + p->state = BR_STATE_BLOCKING; + + spin_unlock_bh(&p->br->lock); + + br_mrp_port_switchdev_set_state(p, state); + + return 0; +} + +/* Set port role, port role can be primary or secondary + * note: already called with rcu_read_lock + */ +int br_mrp_set_port_role(struct net_bridge_port *p, + struct br_mrp_port_role *role) +{ + struct br_mrp *mrp; + + if (!p || !(p->flags & BR_MRP_AWARE)) + return -EINVAL; + + mrp = br_mrp_find_id(p->br, role->ring_id); + + if (!mrp) + return -EINVAL; + + if (role->role == BR_MRP_PORT_ROLE_PRIMARY) + rcu_assign_pointer(mrp->p_port, p); + else + rcu_assign_pointer(mrp->s_port, p); + + br_mrp_port_switchdev_set_role(p, role->role); + + return 0; +} + +/* Set ring state, ring state can be only Open or Closed + * note: already called with rcu_read_lock + */ +int br_mrp_set_ring_state(struct net_bridge *br, + struct br_mrp_ring_state *state) +{ + struct br_mrp *mrp = br_mrp_find_id(br, state->ring_id); + + if (!mrp) + return -EINVAL; + + if (mrp->ring_state == BR_MRP_RING_STATE_CLOSED && + state->ring_state != BR_MRP_RING_STATE_CLOSED) + mrp->ring_transitions++; + + mrp->ring_state = state->ring_state; + + br_mrp_switchdev_set_ring_state(br, mrp, state->ring_state); + + return 0; +} + +/* Set ring role, ring role can be only MRM(Media Redundancy Manager) or + * MRC(Media Redundancy Client). + * note: already called with rcu_read_lock + */ +int br_mrp_set_ring_role(struct net_bridge *br, + struct br_mrp_ring_role *role) +{ + struct br_mrp *mrp = br_mrp_find_id(br, role->ring_id); + int err; + + if (!mrp) + return -EINVAL; + + mrp->ring_role = role->ring_role; + + /* If there is an error just bailed out */ + err = br_mrp_switchdev_set_ring_role(br, mrp, role->ring_role); + if (err && err != -EOPNOTSUPP) + return err; + + /* Now detect if the HW actually applied the role or not. If the HW + * applied the role it means that the SW will not to do those operations + * anymore. For example if the role ir MRM then the HW will notify the + * SW when ring is open, but if the is not pushed to the HW the SW will + * need to detect when the ring is open + */ + mrp->ring_role_offloaded = err == -EOPNOTSUPP ? 0 : 1; + + return 0; +} + +/* Start to generate MRP test frames, the frames are generated by HW and if it + * fails, they are generated by the SW. + * note: already called with rcu_read_lock + */ +int br_mrp_start_test(struct net_bridge *br, + struct br_mrp_start_test *test) +{ + struct br_mrp *mrp = br_mrp_find_id(br, test->ring_id); + + if (!mrp) + return -EINVAL; + + /* Try to push is to the HW and if it fails then continue to generate in + * SW and if that also fails then return error + */ + if (!br_mrp_switchdev_send_ring_test(br, mrp, test->interval, + test->max_miss, test->period)) + return 0; + + mrp->test_interval = test->interval; + mrp->test_end = jiffies + usecs_to_jiffies(test->period); + mrp->test_max_miss = test->max_miss; + mrp->test_count_miss = 0; + queue_delayed_work(system_wq, &mrp->test_work, + usecs_to_jiffies(test->interval)); + + return 0; +} + +/* Process only MRP Test frame. All the other MRP frames are processed by + * userspace application + * note: already called with rcu_read_lock + */ +static void br_mrp_mrm_process(struct br_mrp *mrp, struct net_bridge_port *port, + struct sk_buff *skb) +{ + struct br_mrp_tlv_hdr *hdr; + + hdr = (struct br_mrp_tlv_hdr *)(skb->data + sizeof(uint16_t)); + + if (!hdr) + return; + + if (hdr->type != BR_MRP_TLV_HEADER_RING_TEST) + return; + + mrp->test_count_miss = 0; + + /* Notify the userspace that the ring is closed only when the ring is + * not closed + */ + if (mrp->ring_state != BR_MRP_RING_STATE_CLOSED) + br_mrp_port_open(port->dev, false); +} + +/* This will just forward the frame to the other mrp ring port(MRC role) or will + * not do anything. + * note: already called with rcu_read_lock + */ +static int br_mrp_rcv(struct net_bridge_port *p, + struct sk_buff *skb, struct net_device *dev) +{ + struct net_device *s_dev, *p_dev, *d_dev; + struct net_bridge_port *p_port, *s_port; + struct net_bridge *br; + struct sk_buff *nskb; + struct br_mrp *mrp; + + /* If port is disabled don't accept any frames */ + if (p->state == BR_STATE_DISABLED) + return 0; + + br = p->br; + mrp = br_mrp_find_port(br, p); + if (unlikely(!mrp)) + return 0; + + p_port = rcu_dereference(mrp->p_port); + if (!p_port) + return 0; + + s_port = rcu_dereference(mrp->s_port); + if (!s_port) + return 0; + + /* If the role is MRM then don't forward the frames */ + if (mrp->ring_role == BR_MRP_RING_ROLE_MRM) { + br_mrp_mrm_process(mrp, p, skb); + return 1; + } + + /* Clone the frame and forward it on the other MRP port */ + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) + return 0; + + p_dev = p_port->dev; + s_dev = s_port->dev; + + if (p_dev == dev) + d_dev = s_dev; + else + d_dev = p_dev; + + nskb->dev = d_dev; + skb_push(nskb, ETH_HLEN); + dev_queue_xmit(nskb); + + return 1; +} + +/* Check if the frame was received on a port that is part of MRP ring + * and if the frame has MRP eth. In that case process the frame otherwise do + * normal forwarding. + * note: already called with rcu_read_lock + */ +int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) +{ + /* If there is no MRP instance do normal forwarding */ + if (likely(!(p->flags & BR_MRP_AWARE))) + goto out; + + if (unlikely(skb->protocol == htons(ETH_P_MRP))) + return br_mrp_rcv(p, skb, p->dev); + +out: + return 0; +} + +bool br_mrp_enabled(struct net_bridge *br) +{ + return !list_empty(&br->mrp_list); +} diff --git a/net/bridge/br_mrp_netlink.c b/net/bridge/br_mrp_netlink.c new file mode 100644 index 000000000000..b982db14bbf4 --- /dev/null +++ b/net/bridge/br_mrp_netlink.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include +#include "br_private.h" +#include "br_private_mrp.h" + +int br_mrp_port_open(struct net_device *dev, u8 loc) +{ + struct net_bridge_port *p; + int err = 0; + + p = br_port_get_rcu(dev); + if (!p) { + err = -EINVAL; + goto out; + } + + if (loc) + p->flags |= BR_MRP_LOST_CONT; + else + p->flags &= ~BR_MRP_LOST_CONT; + + br_ifinfo_notify(RTM_NEWLINK, NULL, p); + +out: + return err; +} From patchwork Wed Apr 22 16:18:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220738 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E09BC5518C for ; Wed, 22 Apr 2020 16:22:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1DC3D20776 for ; Wed, 22 Apr 2020 16:22:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="U1IeZUUt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727099AbgDVQWm (ORCPT ); Wed, 22 Apr 2020 12:22:42 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:26247 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726975AbgDVQWO (ORCPT ); Wed, 22 Apr 2020 12:22:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587572534; x=1619108534; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=TRDzYTTkszQZoBi8scNuBHRjQdUT5FUctOqTVt7xLgw=; b=U1IeZUUtYwpboci7qpjyul7AyKw9qX0VG538iccZtDNPgMLQIeAZB3Nv XEp55RlqjJ3nHX7b3Yh+iomHqVuw5mUcvqjp+NZgnRFYimIIHExWtY3XD 25aQ20Ay2TvkZlEZBOjPhUwe2jiGQ9rZk9/oqtuLwz9yl/cVwu8QjFgdS CPWKkUns6H4vJolP9S8TA6UVgbBVSJV5jn/sHpQPwnUc7jAKcsvzkHs/z zzVelXFe/NrqxYMTBsbWe5QO8KzvYjo5AYeQxP/2YcPE8jnURB/cKJuSL +FyDPS/56fPr60xt4MSk/Z4gVjo5yMqjtAEvke9i+E7cAMzpiUVLNw+L0 A==; IronPort-SDR: 3vqZ3NXJ69fiJBmI0T8thEi5Gc87e1QRZjTNTHvQo562wMKLGKcLtPg41KrWgoJi5MKMR54vof qzn/oWxxkKCHUEpwXdUncRLzaGwprbLBzP5HeTXppkW5IzWHkjzMLtbRfxkfSXTALk6arAlgFV 9ybxFzZ/w94I7kBNvJSFhKSfPU8VHeS06cSUFQeAReZtL5Kx2use0iBFpal51LT3nTtR9zG4Sy 2QWbP6TUNCdXey8/079eNA2bM4UzReCUQD9X8rN8vepPTBei+Jjt3mpG7zBMBrCufH5/obY2Db HJE= X-IronPort-AV: E=Sophos;i="5.73,304,1583218800"; d="scan'208";a="71205674" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 22 Apr 2020 09:22:13 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 22 Apr 2020 09:22:15 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Wed, 22 Apr 2020 09:22:12 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v3 11/11] net: bridge: Add checks for enabling the STP. Date: Wed, 22 Apr 2020 18:18:33 +0200 Message-ID: <20200422161833.1123-12-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200422161833.1123-1-horatiu.vultur@microchip.com> References: <20200422161833.1123-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org It is not possible to have the MRP and STP running at the same time on the bridge, therefore add check when enabling the STP to check if MRP is already enabled. In that case return error. Signed-off-by: Horatiu Vultur --- net/bridge/br_ioctl.c | 3 +-- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_stp.c | 6 ++++++ net/bridge/br_stp_if.c | 11 ++++++++++- net/bridge/br_sysfs_br.c | 4 +--- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index ae22d784b88a..5e71fc8b826f 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -242,8 +242,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) return -EPERM; - br_stp_set_enabled(br, args[1]); - ret = 0; + ret = br_stp_set_enabled(br, args[1], NULL); break; case BRCTL_SET_BRIDGE_PRIORITY: diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 1a5e681a626a..a774e19c41bb 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1109,7 +1109,9 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], if (data[IFLA_BR_STP_STATE]) { u32 stp_enabled = nla_get_u32(data[IFLA_BR_STP_STATE]); - br_stp_set_enabled(br, stp_enabled); + err = br_stp_set_enabled(br, stp_enabled, extack); + if (err) + return err; } if (data[IFLA_BR_PRIORITY]) { diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 5835828320b6..c35647cb138a 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1283,7 +1283,8 @@ int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time); /* br_stp_if.c */ void br_stp_enable_bridge(struct net_bridge *br); void br_stp_disable_bridge(struct net_bridge *br); -void br_stp_set_enabled(struct net_bridge *br, unsigned long val); +int br_stp_set_enabled(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack); void br_stp_enable_port(struct net_bridge_port *p); void br_stp_disable_port(struct net_bridge_port *p); bool br_stp_recalculate_bridge_id(struct net_bridge *br); diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 1f14b8455345..3e88be7aa269 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -36,6 +36,12 @@ void br_set_state(struct net_bridge_port *p, unsigned int state) }; int err; + /* Don't change the state of the ports if they are driven by a different + * protocol. + */ + if (p->flags & BR_MRP_AWARE) + return; + p->state = state; err = switchdev_port_attr_set(p->dev, &attr); if (err && err != -EOPNOTSUPP) diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index d174d3a566aa..a42850b7eb9a 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -196,10 +196,17 @@ static void br_stp_stop(struct net_bridge *br) br->stp_enabled = BR_NO_STP; } -void br_stp_set_enabled(struct net_bridge *br, unsigned long val) +int br_stp_set_enabled(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { ASSERT_RTNL(); + if (br_mrp_enabled(br)) { + NL_SET_ERR_MSG_MOD(extack, + "STP can't be enabled if MRP is already enabled\n"); + return -EINVAL; + } + if (val) { if (br->stp_enabled == BR_NO_STP) br_stp_start(br); @@ -207,6 +214,8 @@ void br_stp_set_enabled(struct net_bridge *br, unsigned long val) if (br->stp_enabled != BR_NO_STP) br_stp_stop(br); } + + return 0; } /* called under bridge lock */ diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 9ab0f00b1081..7db06e3f642a 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -126,9 +126,7 @@ static ssize_t stp_state_show(struct device *d, static int set_stp_state(struct net_bridge *br, unsigned long val) { - br_stp_set_enabled(br, val); - - return 0; + return br_stp_set_enabled(br, val, NULL); } static ssize_t stp_state_store(struct device *d,