From patchwork Tue Apr 21 14:37:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220843 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, 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 312B2C54FD0 for ; Tue, 21 Apr 2020 14:42:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F31D8206D4 for ; Tue, 21 Apr 2020 14:42:47 +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="JzOsVOaV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729098AbgDUOmp (ORCPT ); Tue, 21 Apr 2020 10:42:45 -0400 Received: from esa2.microchip.iphmx.com ([68.232.149.84]:61583 "EHLO esa2.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726691AbgDUOmn (ORCPT ); Tue, 21 Apr 2020 10:42:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587480162; x=1619016162; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=EVrsHnpOE3AZe4JWL68hdRpJtAseA7A0xWunJ0r9P4o=; b=JzOsVOaVY1ULE4ZoCradunh9JyKdmAyWfq2HQzYbnOeUVgMuh6ZFU/ef ASgPWSALAaH0yzULtaJbWWiR3zKSL98JHrW21yPuGNBlwZbmZnp+VSzO0 tV/MsFMKs/7fqjXe0PlGDPvHr7WcLtZVR96CGVPKAiBd+vXNF8W0pB4Uz MHmIryNDgzubyfp1Er7dXNcPWOxudVnwFPPLT5WQqeE/pPBHRuPsy91N7 OQVCDxTvZEi+e9KJgNsPifhurBL243wFS9wqYm2CWGuTpqQc5REdV98Vk Hb+3eS5N6UdSwvW9PSIy7x3n3fD01OsBUj/TH5LbrPVu/wtwtZ6yq5O1V w==; IronPort-SDR: fSE02h+z2etsPb+5BR1FJ3MWQMeS3SUmFe5Hsw80V1b70SyeS1AukZxxGjRQmtIgbv63t3ZsT6 gA5oun6+UAKDTl9o//c9awy0acBCsbxtYFgof2Fzkp7TNO8sYs21LkebWF5Gw+6pUWBrYy+BSF R9eeDvqh2mHDvpBZ8iizpilzuGsyo1AWLSRJgauDSrwYEr1YGtf+SABOvY1yyeSjFd6RbcWRNR tGdDf8LbjMeziya0zPSt/ZxvFSIvS417IVNRLHFozrZb0GF6J0rkSCXIIrsYnTQYG+Drj8m2j3 u5o= X-IronPort-AV: E=Sophos;i="5.72,410,1580799600"; d="scan'208";a="72862593" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 21 Apr 2020 07:42:42 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) 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; Tue, 21 Apr 2020 07:42:41 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Tue, 21 Apr 2020 07:42:39 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v2 01/11] bridge: uapi: mrp: Add mrp attributes. Date: Tue, 21 Apr 2020 16:37:42 +0200 Message-ID: <20200421143752.2248-2-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200421143752.2248-1-horatiu.vultur@microchip.com> References: <20200421143752.2248-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 Add new nested netlink attribute to configure the MRP. These attributes are used by the userspace to add/delete/configure MRP instances and by the kernel to notify the userspace when the MRP ring gets open/closed. MRP nested attribute has the following attributes: IFLA_BRIDGE_MRP_INSTANCE - the parameter type is br_mrp_instance which contains the instance id, and the ifindex of the two ports. The ports can't be part of multiple instances. This is used to create/delete MRP instances. IFLA_BRIDGE_MRP_PORT_STATE - the parameter type is u32. Which can be forwarding, blocking or disabled. IFLA_BRIDGE_MRP_PORT_ROLE - the parameter type is br_mrp_port_role which contains the instance id and the role. The role can be primary or secondary. IFLA_BRIDGE_MRP_RING_STATE - the parameter type is br_mrp_ring_state which contains the instance id and the state. The state can be open or closed. IFLA_BRIDGE_MRP_RING_ROLE - the parameter type is br_mrp_ring_role which contains the instance id and the ring role. The role can be MRM or MRC. IFLA_BRIDGE_MRP_START_TEST - the parameter type is br_mrp_start_test which contains the instance id, the interval at which to send the MRP_Test frames, how many test frames can be missed before declaring the ring open and the period which represent for how long to send the test frames. Also add the file include/uapi/linux/mrp_bridge.h which defines all the types used by MRP that are also needed by the userpace. Signed-off-by: Horatiu Vultur --- include/uapi/linux/if_bridge.h | 42 +++++++++++++++++ include/uapi/linux/if_ether.h | 1 + include/uapi/linux/mrp_bridge.h | 84 +++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 include/uapi/linux/mrp_bridge.h diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index bfe621ea51b3..bd8c95488f16 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -120,6 +120,7 @@ enum { IFLA_BRIDGE_MODE, IFLA_BRIDGE_VLAN_INFO, IFLA_BRIDGE_VLAN_TUNNEL_INFO, + IFLA_BRIDGE_MRP, __IFLA_BRIDGE_MAX, }; #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) @@ -157,6 +158,47 @@ struct bridge_vlan_xstats { __u32 pad2; }; +enum { + IFLA_BRIDGE_MRP_UNSPEC, + IFLA_BRIDGE_MRP_INSTANCE, + IFLA_BRIDGE_MRP_PORT_STATE, + IFLA_BRIDGE_MRP_PORT_ROLE, + IFLA_BRIDGE_MRP_RING_STATE, + IFLA_BRIDGE_MRP_RING_ROLE, + IFLA_BRIDGE_MRP_START_TEST, + __IFLA_BRIDGE_MRP_MAX, +}; + +struct br_mrp_instance { + __u32 ring_id; + __u32 p_ifindex; + __u32 s_ifindex; +}; + +struct br_mrp_port_role { + __u32 ring_id; + __u32 role; +}; + +struct br_mrp_ring_state { + __u32 ring_id; + __u32 ring_state; +}; + +struct br_mrp_ring_role { + __u32 ring_id; + __u32 ring_role; +}; + +struct br_mrp_start_test { + __u32 ring_id; + __u32 interval; + __u32 max_miss; + __u32 period; +}; + +#define IFLA_BRIDGE_MRP_MAX (__IFLA_BRIDGE_MRP_MAX - 1) + struct bridge_stp_xstats { __u64 transition_blk; __u64 transition_fwd; diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index f6ceb2e63d1e..d6de2b167448 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -92,6 +92,7 @@ #define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ #define ETH_P_TIPC 0x88CA /* TIPC */ #define ETH_P_LLDP 0x88CC /* Link Layer Discovery Protocol */ +#define ETH_P_MRP 0x88E3 /* Media Redundancy Protocol */ #define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */ #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ #define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ diff --git a/include/uapi/linux/mrp_bridge.h b/include/uapi/linux/mrp_bridge.h new file mode 100644 index 000000000000..2600cdf5a284 --- /dev/null +++ b/include/uapi/linux/mrp_bridge.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ + +#ifndef _UAPI_LINUX_MRP_BRIDGE_H_ +#define _UAPI_LINUX_MRP_BRIDGE_H_ + +#include +#include + +#define MRP_MAX_FRAME_LENGTH 200 +#define MRP_DEFAULT_PRIO 0x8000 +#define MRP_DOMAIN_UUID_LENGTH 16 +#define MRP_VERSION 1 +#define MRP_FRAME_PRIO 7 + +enum br_mrp_ring_role_type { + BR_MRP_RING_ROLE_DISABLED, + BR_MRP_RING_ROLE_MRC, + BR_MRP_RING_ROLE_MRM, +}; + +enum br_mrp_ring_state_type { + BR_MRP_RING_STATE_OPEN, + BR_MRP_RING_STATE_CLOSED, +}; + +enum br_mrp_port_state_type { + BR_MRP_PORT_STATE_DISABLED, + BR_MRP_PORT_STATE_BLOCKED, + BR_MRP_PORT_STATE_FORWARDING, + BR_MRP_PORT_STATE_NOT_CONNECTED, +}; + +enum br_mrp_port_role_type { + BR_MRP_PORT_ROLE_PRIMARY, + BR_MRP_PORT_ROLE_SECONDARY, + BR_MRP_PORT_ROLE_NONE, +}; + +enum br_mrp_tlv_header_type { + BR_MRP_TLV_HEADER_END = 0x0, + BR_MRP_TLV_HEADER_COMMON = 0x1, + BR_MRP_TLV_HEADER_RING_TEST = 0x2, + BR_MRP_TLV_HEADER_RING_TOPO = 0x3, + BR_MRP_TLV_HEADER_RING_LINK_DOWN = 0x4, + BR_MRP_TLV_HEADER_RING_LINK_UP = 0x5, +}; + +struct br_mrp_tlv_hdr { + __u8 type; + __u8 length; +}; + +struct br_mrp_end_hdr { + struct br_mrp_tlv_hdr hdr; +}; + +struct br_mrp_common_hdr { + __u16 seq_id; + __u8 domain[MRP_DOMAIN_UUID_LENGTH]; +}; + +struct br_mrp_ring_test_hdr { + __u16 prio; + __u8 sa[ETH_ALEN]; + __u16 port_role; + __u16 state; + __u16 transitions; + __u32 timestamp; +}; + +struct br_mrp_ring_topo_hdr { + __u16 prio; + __u8 sa[ETH_ALEN]; + __u16 interval; +}; + +struct br_mrp_ring_link_hdr { + __u8 sa[ETH_ALEN]; + __u16 port_role; + __u16 interval; + __u16 blocked; +}; + +#endif From patchwork Tue Apr 21 14:37:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220842 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, 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 29DD7C54FD0 for ; Tue, 21 Apr 2020 14:42:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0BA80206D9 for ; Tue, 21 Apr 2020 14:42:58 +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="B737exln" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729200AbgDUOmz (ORCPT ); Tue, 21 Apr 2020 10:42:55 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:56807 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729166AbgDUOmv (ORCPT ); Tue, 21 Apr 2020 10:42:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587480171; x=1619016171; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=j9vuAzMiBC0XIenmNk+Q7ztffNdq+mbfWZ9t9r+B3uw=; b=B737exlnxR4OpepXo1qi1Hj6TimNr10Mi+Zy8lzI3W71P8kkVJ13haBg SshGEW3/GBfrGGfOR/wKGg99MG3QW89ZfHoUA0hiF9CvdFaeMv2GIE2xa MOjepVLUt9DLJMAo2kX4YXdAeQYwOugZ4d6Djg/6qrzCcrEZ5IoD6CWrn QSy68fBQLEfloo4oyaYQeueUf5qrxJoLzjcJhrq77Ku4R6O7+Fc3/DUYd tJYIUbDi74G7dvMwqby3KRgib4Cd4QtbWbzxZSOsdVJgKu4kpwy7GZkbk K2jUBMxDPses2SmYfXtz7UrKLzaf794EWzmmnlkqETyEW/te1t2L+YIVS Q==; IronPort-SDR: nlMYdjL9kaBLd6h7y1ZZ6NpXq4X4y5UkM24pNfUh/nm4Lww0r7MkV3WLSkV6eO4pdEKqZ584i4 cOgN9BNVqHU6PzpfRWbeCk52q48i8x53Gfralcvswu0bna/oPSQD1U0XwgIp1OXNK7hb/uyFas NCEUA0R+fasUflTJOrDcL+7RiYh21cmXZuzrozY6jbwSreFky6toRe9cWqcYXSkCJb6D2mjNMH HFnFBSeEkR2in5OoSdOGLFKu/1MOCZQi0CVDvBZuyleNOpN6+LeT6q6IHgchl7AXv5t5QBv6yr 9N8= X-IronPort-AV: E=Sophos;i="5.72,410,1580799600"; d="scan'208";a="71040873" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 21 Apr 2020 07:42:50 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) 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; Tue, 21 Apr 2020 07:42:50 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Tue, 21 Apr 2020 07:42:47 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v2 04/11] net: bridge: Add port attribute IFLA_BRPORT_MRP_RING_OPEN Date: Tue, 21 Apr 2020 16:37:45 +0200 Message-ID: <20200421143752.2248-5-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200421143752.2248-1-horatiu.vultur@microchip.com> References: <20200421143752.2248-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 Tue Apr 21 14:37:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220838 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, 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 3A8BCC54FCC for ; Tue, 21 Apr 2020 14:43:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 18E13206D4 for ; Tue, 21 Apr 2020 14:43:43 +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="mQqeBpuS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729225AbgDUOm7 (ORCPT ); Tue, 21 Apr 2020 10:42:59 -0400 Received: from esa2.microchip.iphmx.com ([68.232.149.84]:61621 "EHLO esa2.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729166AbgDUOm5 (ORCPT ); Tue, 21 Apr 2020 10:42:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587480176; x=1619016176; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=Wk5W6JOrVyShu0Bu566DjA/nJMtV0L8hDnh56QYpSOM=; b=mQqeBpuSfv3Ayujr9FkEYzbIyXqy/GAY2JqciV/g9ctPrWsK1J6ZblWI D8Xqv7Sj3HtS00CnWClQazasSllIDCI5p9PCakFY6dbG+JCjyDS5MMZI9 7v1k4lAzaj2E5HDlYgNDbWjy8rHi4FEMhuLvkE2zBnAn/pX7GBHyMQqyd /vANO6KLx8+6J4DBlDy2B4iMeyXTsyrg44H/BaNAww5ncIlMxvoSOPJgi xAtV0jOJnw93CK6RRmAsxZqvhzcFSbjuMjZC+WJeHn+LVu5/6yl1sJQ4j iyzPUPsOo318nrfqE9mafi1poTfja2uYKzmx+8NAgMM78sXIAbYLh1/+P w==; IronPort-SDR: 6u41ZC8mwRw4I4NhUH/7FH3/f7kFSJe7VNO4vX+hFL6OlUVhUdU9Yeuhvo31TtOeczF09nolux D2jXibPabi6Nx+Dd2m7O04zLt3NFArQMAyvJ/q3ZdyD29/s/bWEqUFKKZ8Q4k82aV+lvVoXADf YK0F4I+pwum5b8d29lgKsBxzCwCCuy3kYGlVeDAJLH+1l+38av0/5nPV7vzQnc9G1FN89/JRbN /hIyFUGWNuEv3WN9myACv4wWEcPPCISUrT0hXuQSuY5FIAr5UFqbcxnRxjMM+VcXm1jTtCRWBI xUw= X-IronPort-AV: E=Sophos;i="5.72,410,1580799600"; d="scan'208";a="72862640" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 21 Apr 2020 07:42:56 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) 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; Tue, 21 Apr 2020 07:42:56 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Tue, 21 Apr 2020 07:42:53 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v2 06/11] switchdev: mrp: Extend switchdev API to offload MRP Date: Tue, 21 Apr 2020 16:37:47 +0200 Message-ID: <20200421143752.2248-7-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200421143752.2248-1-horatiu.vultur@microchip.com> References: <20200421143752.2248-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 Tue Apr 21 14:37:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220841 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,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 23243C54FC9 for ; Tue, 21 Apr 2020 14:43:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E7A23206D6 for ; Tue, 21 Apr 2020 14:43:06 +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="1gK6Jk1w" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729265AbgDUOnG (ORCPT ); Tue, 21 Apr 2020 10:43:06 -0400 Received: from esa5.microchip.iphmx.com ([216.71.150.166]:10382 "EHLO esa5.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729138AbgDUOnD (ORCPT ); Tue, 21 Apr 2020 10:43:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587480184; x=1619016184; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=Me54K3hRgrL7rbnFE6CvixGEZRIdsqDmYX6hoIIS07Y=; b=1gK6Jk1w1UD47SPMcVGvNuHFa93ZGozdJMJam8HdPwV4Y5o7WY1G2GTt SZThXWHlB+lQEA6cv00uoZMcWoxaGFF+o1SyhRxaTMl//o0ymWoeFDg87 ynvBQgx3FJQ1VZAX9s7N3PqIP0MhrHMbhdeb4ACYFBTxHh7M+XZhxjGlf dX8WAfWrXJRttZBv3rspOhRzLcuIcykZ6mjej/ue/icGfC4fJQnbrWhe3 9JhkU6nmzd+T7vxSHVau3jDx0a1sUw6XeNj0Uf0iwwVnsPKvgnZny6670 a64YGWPJ1xgVprx2FksepeBcM3W0wkbW6BE0/oeTpI0txZhpOs3+7Tlbx A==; IronPort-SDR: eT2WojjajT1TcgT/s34dmOBCXgJ2zFMMSosQ6KMnj0uD6ImABGcD1Zr5ZmHAxWLYH/1vdCq4VE 7t0WaM75blqjCSJkXwfyEi6VA15rRY/zOCn23i/QaSnDWp6t88Yc3MVhRKC0m1KmcTA9hwCROP KsPyrn+ns5TIErhj4Zp8Tp5maDOkkJHhkGOFqHT3Sex98Zx3IEDO1sH43GVMy+km06pWtbpPJ7 Osx6hM1hRjfCnYMY8OaxW36LywogcyWyXE0PEnSiYGl3afKhEGgLUdWzRwyHaTlLe0SuwRNiiq Onc= X-IronPort-AV: E=Sophos;i="5.72,410,1580799600"; d="scan'208";a="73284499" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 21 Apr 2020 07:43:03 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Tue, 21 Apr 2020 07:42:31 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Tue, 21 Apr 2020 07:42:59 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v2 08/11] bridge: mrp: Connect MRP API with the switchdev API Date: Tue, 21 Apr 2020 16:37:49 +0200 Message-ID: <20200421143752.2248-9-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200421143752.2248-1-horatiu.vultur@microchip.com> References: <20200421143752.2248-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 | 559 ++++++++++++++++++++++++++++++++++++ net/bridge/br_mrp_netlink.c | 29 ++ 3 files changed, 589 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..533f621fa56a --- /dev/null +++ b/net/bridge/br_mrp.c @@ -0,0 +1,559 @@ +// 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 net_bridge *br = p->br; + struct sk_buff *skb = NULL; + + if (!p) + return NULL; + + br = p->br; + + 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 Tue Apr 21 14:37:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220840 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,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 3C82EC54FC9 for ; Tue, 21 Apr 2020 14:43:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1BB5E206D9 for ; Tue, 21 Apr 2020 14:43:14 +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="GLThiMbU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729306AbgDUOnN (ORCPT ); Tue, 21 Apr 2020 10:43:13 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:56853 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729282AbgDUOnJ (ORCPT ); Tue, 21 Apr 2020 10:43:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587480188; x=1619016188; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=0As9yCEoo8wuIjCPpQSANbvOMZTIRzcx0rCbgIibC1w=; b=GLThiMbUHUmfPss4Ig7gUrh7vDTOwC3ionH4an4Xm3iqyFA2OxRjWpis Lp2Ztd1w5D0Pr9RyUk0g9H699pzpKAmtm3OKcqXqQYjdKsSxcwT2azR2o +RQVVOpdEenQlnQ06grsvDyW2Ft8Eu/Ok14WyNJtIBDMNlnQ4wV/1hDTb aH+sroBN+brddo/fkXvrxEXtXxoeW9vljfKYg3jN5/ZydeRUTFTrntr+f So7iYBVtR1Qe4/T40xo89JHb+SsRbAPDGXFJhn241FBOLcY3AywyZ3MIU PZ6pMxqc+lh//pFp8imYo9LRmLcIlliE51cfmRa6ZvSJvq0EDGpc6QnlG A==; IronPort-SDR: qb8SBQ/9S965B9W39hCufnEnZWAlHep+VoXbthAFahLYtEFZa0ktVowW6n7SWepyswve41xa1m KGZb3gD6pAjIOJW3Kfg4wcC3fFX/T7SpqsXB+9dxbA0vOAbrzchD9/uF912La0LhsIydR98GAf 9uTHqCHvBQRZJ6Xr1R4W/0JxQUuy6tPqZ9r3I2wnQJopx6aWMHbBH33gMvDecNAbRLvgOBhDmH zuoPA/kfx3Ga74d41Bkdjx2jrL04/GXmvVKlCdu7Mqn2poPbfl1BuWwrsALSIH0BA5QEn1g1nW /KY= X-IronPort-AV: E=Sophos;i="5.72,410,1580799600"; d="scan'208";a="71040901" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 21 Apr 2020 07:43:07 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) 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; Tue, 21 Apr 2020 07:43:07 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Tue, 21 Apr 2020 07:43:04 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v2 10/11] bridge: mrp: Integrate MRP into the bridge Date: Tue, 21 Apr 2020 16:37:51 +0200 Message-ID: <20200421143752.2248-11-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200421143752.2248-1-horatiu.vultur@microchip.com> References: <20200421143752.2248-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, the bridge needs to do the following: - detect if the MRP frame was received on MRP ring port in that case it would be processed otherwise just forward it as usual. - enable parsing of MRP - before whenever the bridge was set up, it would set all the ports in forwarding state. Add an extra check to not set ports in forwarding state if the port is an MRP ring port. The reason of this change is that if the MRP instance initially sets the port in blocked state by setting the bridge up it would overwrite this setting. Signed-off-by: Horatiu Vultur --- net/bridge/br_device.c | 3 +++ net/bridge/br_if.c | 2 ++ net/bridge/br_input.c | 3 +++ net/bridge/br_netlink.c | 5 +++++ net/bridge/br_private.h | 31 +++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 0e3dbc5f3c34..8ec1362588af 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -463,6 +463,9 @@ void br_dev_setup(struct net_device *dev) spin_lock_init(&br->lock); INIT_LIST_HEAD(&br->port_list); INIT_HLIST_HEAD(&br->fdb_list); +#if IS_ENABLED(CONFIG_BRIDGE_MRP) + INIT_LIST_HEAD(&br->mrp_list); +#endif spin_lock_init(&br->hash_lock); br->bridge_id.prio[0] = 0x80; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4fe30b182ee7..ca685c0cdf95 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -333,6 +333,8 @@ static void del_nbp(struct net_bridge_port *p) br_stp_disable_port(p); spin_unlock_bh(&br->lock); + br_mrp_port_del(br, p); + br_ifinfo_notify(RTM_DELLINK, NULL, p); list_del_rcu(&p->list); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index fcc260840028..d5c34f36f0f4 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -342,6 +342,9 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) } } + if (unlikely(br_mrp_process(p, skb))) + return RX_HANDLER_PASS; + forward: switch (p->state) { case BR_STATE_FORWARDING: diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 4084f1ef8641..1a5e681a626a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -672,6 +672,11 @@ static int br_afspec(struct net_bridge *br, if (err) return err; break; + case IFLA_BRIDGE_MRP: + err = br_mrp_parse(br, p, attr, cmd, extack); + if (err) + return err; + break; } } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 835a70f8d3ea..5835828320b6 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1308,6 +1308,37 @@ unsigned long br_timer_value(const struct timer_list *timer); extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); #endif +/* br_mrp.c */ +#if IS_ENABLED(CONFIG_BRIDGE_MRP) +int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, + struct nlattr *attr, int cmd, struct netlink_ext_ack *extack); +int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb); +bool br_mrp_enabled(struct net_bridge *br); +void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p); +#else +static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, + struct nlattr *attr, int cmd, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} + +static inline int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) +{ + return 0; +} + +static inline bool br_mrp_enabled(struct net_bridge *br) +{ + return 0; +} + +static inline void br_mrp_port_del(struct net_bridge *br, + struct net_bridge_port *p) +{ +} +#endif + /* br_netlink.c */ extern struct rtnl_link_ops br_link_ops; int br_netlink_init(void); From patchwork Tue Apr 21 14:37:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Horatiu Vultur X-Patchwork-Id: 220839 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, 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 1E392C54FD0 for ; Tue, 21 Apr 2020 14:43:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E9EFD206A2 for ; Tue, 21 Apr 2020 14:43:24 +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="g+QPWvhv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729324AbgDUOnS (ORCPT ); Tue, 21 Apr 2020 10:43:18 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:56853 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726018AbgDUOnL (ORCPT ); Tue, 21 Apr 2020 10:43:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1587480191; x=1619016191; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=TRDzYTTkszQZoBi8scNuBHRjQdUT5FUctOqTVt7xLgw=; b=g+QPWvhvNhzFMOv5/iC3CkffCgCsmhMtyIFmtooh4ny9CWVqFLuUyZVG P+eqw4Fe6KjfQlaNnjdzIAnMmFlMwYiFKsCh78HvEhtywYXDOd0sZo/WV wPSKe2/kXEFucT/hN+fGgGCUHJOx2Kl8zqV1SkuOULiiROupyHw1f72zh AUOXGlmWLgPXoLa/A2xL/rTlVuxMtfsEKFAbQzh3VqmINxudU1dcH+F4Z uN3jAxRWnxAwircKg7WwYUpCBTsgTfQPr+TZ+P9y0wg6dBH9Rwwo8ab3L pQXsPJDQ8ziPKpDHgXZic3YtUddev4HJB1j4Z7eAbFpqtgZ5imW0ryRIu w==; IronPort-SDR: /Pe5MOWlkkYHIdchZhyf1TLKNfdY81qua/eWiwm2zE+MoTDNWzcdE0J4yTzjLfklFJye/7YngL gu3Gg4NkKw3Im9erOTy0WwPQULT7S2hTftMdfhmBSclkY+ntkrQpzV/wqduyknwtW2Y0q17Ooe LiwnHVA/WR0S577BQ1VeYg8ctdyFbThz2S5TonVN2yGDaNX2yixhOOsxEojh5WwSlcvU9ILGdY oS6NYhqvruRE1o0SMHfKdVDIeIGYJVW1ZV4iKnXielH51mN6ZIr86FR+CH7l3Vqb2pM47OVHCJ VaU= X-IronPort-AV: E=Sophos;i="5.72,410,1580799600"; d="scan'208";a="71040911" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 21 Apr 2020 07:43:10 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) 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; Tue, 21 Apr 2020 07:43:10 -0700 Received: from soft-dev3.microsemi.net (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Tue, 21 Apr 2020 07:43:07 -0700 From: Horatiu Vultur To: , , , , , , , , , , , CC: Horatiu Vultur Subject: [PATCH net-next v2 11/11] net: bridge: Add checks for enabling the STP. Date: Tue, 21 Apr 2020 16:37:52 +0200 Message-ID: <20200421143752.2248-12-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200421143752.2248-1-horatiu.vultur@microchip.com> References: <20200421143752.2248-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,