Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp331158pxk; Thu, 1 Oct 2020 03:37:57 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx191U9KRaCD3dP9HWbrbO80xpuqiOmymWgXrYEbcVb8eX4lPJvWsNqYtPd3xWHJbDi2RXe X-Received: by 2002:a17:906:8c1:: with SMTP id o1mr7579125eje.478.1601548676762; Thu, 01 Oct 2020 03:37:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1601548676; cv=none; d=google.com; s=arc-20160816; b=0Hj3hgFCvqCJ6pNpmDD1oXV0E9OvJDriQVl9rXlclxP9y0lRkCbB4LIwmVp231jOgU tbk+vAJasgSUu1FwAKvLctEqJ8uRQziJvr60rI3WwDUN0lNKl0xGAaB9kDFkTyFpH/CF 0Jvql8N8mnQwmmpLB/Xm3e/jxLoGH0j9cfsKKEEzHpPgMgcrj8wUijAvMvxyQpZpY8rP BrB/a3Y+158PYd8f5mYwbfhFmJb1Tt9T1I1OuhecUsEhlZucN345mkkDAke1LmP4XTDI I97bBONKnZkyjAq0Qh56NbGe1J1lez5WU4HPdoBkUspl0z7BITaXbpmP04/bc8a1ki2M YXrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:dkim-signature; bh=0TB15P8TWANZHwRJ34EI3CPdP5UBrVeZTAFIHCZF39w=; b=LspvxMZ9MGbVDsacZmq0JsplSFHmxDRzKs/XISm92BUrwBTfxum2C9uCZvl3LpYeW6 yKlphxnSy0vm0cFF5VsYzQ8ujMro9y2ZFyKllEDrD7VQdpzQh0CRJYh4z5a4A7+vjW4k 0ART/REnMRgRLgpsEEQ5z2t2g6y1BsNtoZ9lFsVPTVnhxaY/PVaEs9wgUzuBjnM4CmGs O89RDsfDBYhdaZb2bg1iXn2IYOAmYx6KgEnEKX01/0j9BvLyesVzwV15uebgHZpix+eq FhPEyQy2JzUt3xepq2tK6obN5QlW9O1f+04uqJw4S7zaR9gcyl147E10PqhjT/6eNTA7 f9jw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@microchip.com header.s=mchp header.b="zNu/LRIz"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=microchip.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cb13si3339065edb.153.2020.10.01.03.37.34; Thu, 01 Oct 2020 03:37:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=fail header.i=@microchip.com header.s=mchp header.b="zNu/LRIz"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=microchip.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732205AbgJAKdb (ORCPT + 99 others); Thu, 1 Oct 2020 06:33:31 -0400 Received: from esa4.microchip.iphmx.com ([68.232.154.123]:21343 "EHLO esa4.microchip.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732150AbgJAKdM (ORCPT ); Thu, 1 Oct 2020 06:33:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1601548392; x=1633084392; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v9RWNVkU7uOPL8JOS/0jPuHZ+/LWn2COnY2+d5vrWbk=; b=zNu/LRIz3r7/XGxFKicbeVxSgig7fH74fbgijiJ5ACoFG6VhK3sRBP6f MoryPrM3vfTnqMGy7SstTtMZ2xflHgwJmXGjhNQpBLwesBro9aAsJTRHp b+Lt8XWPvQddeqMuD4wNyneX+DABAW+nmfhxei9q7QkI2W5qrAWcl7xqM Cjq6Dq98PcMFy3Uv3JNsjoi19JCCD7wsIxFqB5/5dn5jrNqNCzqOMhsby 3kQiZe021CXYMz1FaUwrwBSis+1CBGWjveRIHA0Ca/A4lK3SvZRxMkHAJ aN7McGkkUTJoQLOJQQMA+sflnvAPMIa9yUHdAWGDIY8GINx95kebOEIP6 g==; IronPort-SDR: /poEVgRSu8F080Sw4grlKb30E5vP8YR9O56R0+KF/PRLAUwHPbnwk+c6OGWWcKxCHFko4A5GUn hejm/Orjy1vgJLk9WpgV6Ef0LgWWh+EKa8/U9eRaU5+fobmQe84k1Qemyf7xH1OrCpxs/lRflG 3wXMDd+g8G7QBd7/5fVYOQdqOgD+i0GgP/mWn7eci6ON7wOS5hzyV9sKJlYaqpWZLQV4HfLvsO wCy1WzqV2ReUTa22PfS/hE4FhK4ITZCddXWImpDVDMkbC48cQcRaGueKj/CqNJEU2SEZ8XU42S 4Fg= X-IronPort-AV: E=Sophos;i="5.77,323,1596524400"; d="scan'208";a="88772465" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa4.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 01 Oct 2020 03:33:01 -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.1979.3; Thu, 1 Oct 2020 03:32:36 -0700 Received: from soft-test08.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.1979.3 via Frontend Transport; Thu, 1 Oct 2020 03:32:34 -0700 From: Henrik Bjoernlund To: , , , , , , , , , CC: Henrik Bjoernlund , Horatiu Vultur Subject: [net-next v2 10/11] bridge: switchdev: cfm: switchdev interface implementation Date: Thu, 1 Oct 2020 10:30:18 +0000 Message-ID: <20201001103019.1342470-11-henrik.bjoernlund@microchip.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201001103019.1342470-1-henrik.bjoernlund@microchip.com> References: <20201001103019.1342470-1-henrik.bjoernlund@microchip.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is the definition of the CFM switchdev interface. The interface consist of these objects: SWITCHDEV_OBJ_ID_MEP_CFM, SWITCHDEV_OBJ_ID_MEP_CONFIG_CFM, SWITCHDEV_OBJ_ID_CC_CONFIG_CFM, SWITCHDEV_OBJ_ID_CC_PEER_MEP_CFM, SWITCHDEV_OBJ_ID_CC_CCM_TX_CFM, SWITCHDEV_OBJ_ID_MEP_STATUS_CFM, SWITCHDEV_OBJ_ID_PEER_MEP_STATUS_CFM MEP instance add/del switchdev_port_obj_add(SWITCHDEV_OBJ_ID_MEP_CFM) switchdev_port_obj_del(SWITCHDEV_OBJ_ID_MEP_CFM) MEP cofigure switchdev_port_obj_add(SWITCHDEV_OBJ_ID_MEP_CONFIG_CFM) MEP CC cofigure switchdev_port_obj_add(SWITCHDEV_OBJ_ID_CC_CONFIG_CFM) Peer MEP add/del switchdev_port_obj_add(SWITCHDEV_OBJ_ID_CC_PEER_MEP_CFM) switchdev_port_obj_del(SWITCHDEV_OBJ_ID_CC_PEER_MEP_CFM) Start/stop CCM transmission switchdev_port_obj_add(SWITCHDEV_OBJ_ID_CC_CCM_TX_CFM) Get MEP status switchdev_port_obj_get(SWITCHDEV_OBJ_ID_MEP_STATUS_CFM) Get Peer MEP status switchdev_port_obj_get(SWITCHDEV_OBJ_ID_PEER_MEP_STATUS_CFM) Reviewed-by: Horatiu Vultur Signed-off-by: Henrik Bjoernlund --- include/linux/if_bridge.h | 13 +++++ include/net/switchdev.h | 115 ++++++++++++++++++++++++++++++++++++++ net/switchdev/switchdev.c | 54 ++++++++++++++++++ 3 files changed, 182 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 556caed00258..5476880319ae 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -155,4 +155,17 @@ br_port_flag_is_set(const struct net_device *dev, unsigned long flag) } #endif +#if IS_ENABLED(CONFIG_BRIDGE_CFM) +#define BR_CFM_EVENT_CCM_DEFECT (1<<0) + +struct br_cfm_notif_info { + u32 instance; + u32 peer_mep; + u32 events; +}; + +/* Function to be called from CFM switchdev driver to notify change in status */ +void br_cfm_notification(struct net_device *dev, const struct br_cfm_notif_info *const notif_info); +#endif + #endif diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 53e8b4994296..cd5194cd54d0 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -11,6 +11,9 @@ #include #include #include +#include +#include "../net/bridge/br_private.h" +#include "../net/bridge/br_private_cfm.h" #define SWITCHDEV_F_NO_RECURSE BIT(0) #define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) @@ -81,6 +84,15 @@ enum switchdev_obj_id { SWITCHDEV_OBJ_ID_IN_STATE_MRP, #endif +#if IS_ENABLED(CONFIG_BRIDGE_CFM) + SWITCHDEV_OBJ_ID_MEP_CFM, + SWITCHDEV_OBJ_ID_MEP_CONFIG_CFM, + SWITCHDEV_OBJ_ID_CC_CONFIG_CFM, + SWITCHDEV_OBJ_ID_CC_PEER_MEP_CFM, + SWITCHDEV_OBJ_ID_CC_CCM_TX_CFM, + SWITCHDEV_OBJ_ID_MEP_STATUS_CFM, + SWITCHDEV_OBJ_ID_PEER_MEP_STATUS_CFM +#endif }; struct switchdev_obj { @@ -112,6 +124,97 @@ 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_CFM) +/* SWITCHDEV_OBJ_ID_MEP_CFM */ +struct switchdev_obj_cfm_mep { + struct switchdev_obj obj; + u32 instance; + enum br_cfm_domain domain; /* Domain for this MEP */ + enum br_cfm_mep_direction direction; /* Up or Down MEP direction */ + struct net_device *port; /* Residence port */ +}; + +#define SWITCHDEV_OBJ_CFM_MEP(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_mep, obj) + +/* SWITCHDEV_OBJ_ID_MEP_CONFIG_CFM */ +struct switchdev_obj_cfm_mep_config_set { + struct switchdev_obj obj; + u32 instance; + u32 mdlevel; + u32 mepid; + struct mac_addr unicast_mac; +}; + +#define SWITCHDEV_OBJ_CFM_MEP_CONFIG_SET(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_mep_config_set, obj) + +#define SWITCHDEV_CFM_MAID_LENGTH 48 + +/* SWITCHDEV_OBJ_ID_CC_CONFIG_CFM */ +struct switchdev_obj_cfm_cc_config_set { + struct switchdev_obj obj; + u32 instance; + struct br_cfm_maid maid; + enum br_cfm_ccm_interval interval; + bool enable; +}; + +#define SWITCHDEV_OBJ_CFM_CC_CONFIG_SET(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_cc_config_set, obj) + +/* SWITCHDEV_OBJ_ID_CC_PEER_MEP_CFM */ +struct switchdev_obj_cfm_cc_peer_mep { + struct switchdev_obj obj; + u32 instance; + u32 peer_mep_id; +}; + +#define SWITCHDEV_OBJ_CFM_CC_PEER_MEP(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_cc_peer_mep, obj) + +/* SWITCHDEV_OBJ_ID_CC_CCM_TX_CFM */ +struct switchdev_obj_cfm_cc_ccm_tx { + struct switchdev_obj obj; + u32 instance; + u32 period; + struct sk_buff *skb; + enum br_cfm_ccm_interval interval; +}; + +#define SWITCHDEV_OBJ_CFM_CC_CCM_TX(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_cc_ccm_tx, obj) + +/* SWITCHDEV_OBJ_ID_MEP_STATUS_CFM */ +struct switchdev_obj_cfm_mep_status_get { + struct switchdev_obj obj; + u32 instance; + bool clear; + bool opcode_unexp_seen; + bool version_unexp_seen; + bool rx_level_low_seen; +}; + +#define SWITCHDEV_OBJ_CFM_MEP_STATUS_get(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_mep_status_get, obj) + +/* SWITCHDEV_OBJ_ID_PEER_MEP_STATUS_CFM */ +struct switchdev_obj_cfm_cc_peer_status_get { + struct switchdev_obj obj; + u32 instance; + bool clear; + u8 port_tlv_value; + u8 if_tlv_value; + bool ccm_defect; + bool rdi; + bool seen; + bool tlv_seen; + bool seq_unexp_seen; +}; +#define SWITCHDEV_OBJ_CFM_CC_PEER_STATUS_get(OBJ) \ + container_of((OBJ), struct switchdev_obj_cfm_cc_peer_status_get, obj) + +#endif #if IS_ENABLED(CONFIG_BRIDGE_MRP) /* SWITCHDEV_OBJ_ID_MRP */ @@ -208,6 +311,7 @@ enum switchdev_notifier_type { SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */ SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */ SWITCHDEV_PORT_ATTR_SET, /* May be blocking . */ + SWITCHDEV_PORT_OBJ_GET, /* Blocking */ SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, @@ -265,6 +369,9 @@ int switchdev_port_obj_add(struct net_device *dev, struct netlink_ext_ack *extack); int switchdev_port_obj_del(struct net_device *dev, const struct switchdev_obj *obj); +int switchdev_port_obj_get(struct net_device *dev, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack); int register_switchdev_notifier(struct notifier_block *nb); int unregister_switchdev_notifier(struct notifier_block *nb); @@ -326,6 +433,14 @@ static inline int switchdev_port_obj_del(struct net_device *dev, return -EOPNOTSUPP; } +int switchdev_port_obj_get(struct net_device *dev, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} + + static inline int register_switchdev_notifier(struct notifier_block *nb) { return 0; diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 865f3e037425..fefb05b885e0 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -372,6 +372,60 @@ int switchdev_port_obj_del(struct net_device *dev, } EXPORT_SYMBOL_GPL(switchdev_port_obj_del); +static int switchdev_port_obj_get_now(struct net_device *dev, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) +{ + struct switchdev_trans trans; + int err; + + /* Phase I: prepare for obj add. Driver/device should fail + * here if there are going to be issues in the commit phase, + * such as lack of resources or support. The driver/device + * should reserve resources needed for the commit phase here, + * but should not commit the obj. + */ + + trans.ph_prepare = true; + err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_GET, + dev, obj, &trans, extack); + if (err) + return err; + + /* Phase II: commit obj add. This cannot fail as a fault + * of driver/device. If it does, it's a bug in the driver/device + * because the driver said everythings was OK in phase I. + */ + + trans.ph_prepare = false; + err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_GET, + dev, obj, &trans, extack); + WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); + + return err; +} + +/** + * switchdev_port_obj_get - Get information from a port object + * It is expected that the driver fill in information in the + * obj structure. + * + * @dev: port device + * @obj: object to get information from + * @extack: netlink extended ack + * + * Use a 2-phase prepare-commit transaction model to ensure + * system is not left in a partially updated state due to + * failure from driver/device. + */ +int switchdev_port_obj_get(struct net_device *dev, + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) +{ + return switchdev_port_obj_get_now(dev, obj, extack); +} +EXPORT_SYMBOL_GPL(switchdev_port_obj_get); + static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain); static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain); -- 2.28.0