From patchwork Mon Jun 10 07:38:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Rybchenko X-Patchwork-Id: 54598 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 69C991BF0C; Mon, 10 Jun 2019 09:39:26 +0200 (CEST) Received: from dispatch1-us1.ppe-hosted.com (dispatch1-us1.ppe-hosted.com [67.231.154.164]) by dpdk.org (Postfix) with ESMTP id C551D1BE99 for ; Mon, 10 Jun 2019 09:38:56 +0200 (CEST) X-Virus-Scanned: Proofpoint Essentials engine Received: from webmail.solarflare.com (webmail.solarflare.com [12.187.104.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mx1-us5.ppe-hosted.com (PPE Hosted ESMTP Server) with ESMTPS id D75084C0058 for ; Mon, 10 Jun 2019 07:38:55 +0000 (UTC) Received: from ocex03.SolarFlarecom.com (10.20.40.36) by ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Mon, 10 Jun 2019 00:38:51 -0700 Received: from opal.uk.solarflarecom.com (10.17.10.1) by ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id 15.0.1395.4 via Frontend Transport; Mon, 10 Jun 2019 00:38:51 -0700 Received: from ukv-loginhost.uk.solarflarecom.com (ukv-loginhost.uk.solarflarecom.com [10.17.10.39]) by opal.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id x5A7cou7008841; Mon, 10 Jun 2019 08:38:50 +0100 Received: from ukv-loginhost.uk.solarflarecom.com (localhost [127.0.0.1]) by ukv-loginhost.uk.solarflarecom.com (Postfix) with ESMTP id 0BEB01627D7; Mon, 10 Jun 2019 08:38:50 +0100 (BST) From: Andrew Rybchenko To: CC: Gautam Dawar Date: Mon, 10 Jun 2019 08:38:36 +0100 Message-ID: <1560152324-20538-22-git-send-email-arybchenko@solarflare.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1560152324-20538-1-git-send-email-arybchenko@solarflare.com> References: <1560152324-20538-1-git-send-email-arybchenko@solarflare.com> MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-12.5.0.1300-8.5.1010-24664.003 X-TM-AS-Result: No-7.145600-4.000000-10 X-TMASE-MatchedRID: +engLLOnT3btSrqhUiNirv3HILfxLV/969xONVZSrH3mWHHSYEnI8dWZ DZFp9sK+qHdHXw8EW4pTvVffeIwvQ8HVNeDWrWSGnFVnNmvv47vGzDycs+smMN9RlPzeVuQQqjq FxcD2zqTueEO1qlH4lCVURVaeV0Rggb1XSSpDa5DnZxuPj9aY+ytTx/ehjzxgj4jFvt2M5IKZu9 GZpmUaWCqO1+vEcPReqb1YkDVelmHdXve1wYbDSiXTnAZkhKflQo4ZOAclX1K+GYmD5FwZEpKi/ 9O2b8wfIEbqlyPU4c5HhDA5WM1bF61mYT2CMxpdGjzBgnFZvQ66hgVvSdGKo3QWhLVqLFM1KDvv C6BqZx61DpGeEMqeQGzHwL0ty3zWGHO3b96QmYNAwvZYEy8IBdUtYzexhQ5/JLfQYoCQHFYTw7j CStQ0rmpecsbV1dfSKbxcKDI8Nr+9j8fJltl0iJ4CIKY/Hg3AGdQnQSTrKGPEQdG7H66TyMdRT5 TQAJnAdDAOSXoybxqKeGZtJ2CYhChe8at/tBZ0IlAn8VS3Z3qeqD9WtJkSIw== X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--7.145600-4.000000 X-TMASE-Version: SMEX-12.5.0.1300-8.5.1010-24664.003 X-MDID: 1560152336-6kkX4IQLwkMf Subject: [dpdk-dev] [PATCH 21/29] net/sfc/base: implement vSwitch create/destroy X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Gautam Dawar The vSwitch create API takes an array of num_vports client driver allocated vPort config entries where entry at index 0 contains the PF configuration and rest num_vports-1 entries refer to vPort configuration for VFs 0 to (num_vports-2). The required hierarchy (vswitch/vport/vadaptor) is created within this API. The destroy API tears down this hierarchy and releases memory for the vSwitch object. Signed-off-by: Gautam Dawar Signed-off-by: Andrew Rybchenko --- drivers/net/sfc/base/efx.h | 40 ++++++ drivers/net/sfc/base/efx_evb.c | 269 +++++++++++++++++++++++++++++++++++++++- drivers/net/sfc/base/efx_impl.h | 16 +++ 3 files changed, 324 insertions(+), 1 deletion(-) diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index 664efc8..492c8c6 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -1411,6 +1411,9 @@ enum { uint32_t enc_assigned_port; } efx_nic_cfg_t; +#define EFX_VPORT_PCI_FUNCTION_IS_PF(configp) \ + ((configp)->evc_function == 0xffff) + #define EFX_PCI_FUNCTION_IS_PF(_encp) ((_encp)->enc_vf == 0xffff) #define EFX_PCI_FUNCTION_IS_VF(_encp) ((_encp)->enc_vf != 0xffff) @@ -3369,6 +3372,31 @@ extern __checkReturn __success(return != B_FALSE) boolean_t #define EFX_FILTER_VID_UNSPEC 0xffff #define EFX_DEFAULT_VSWITCH_ID 1 +/* Default VF VLAN ID on creation */ +#define EFX_VF_VID_DEFAULT EFX_FILTER_VID_UNSPEC +#define EFX_VPORT_ID_INVALID 0 + +typedef struct efx_vport_config_s { + /* Either VF index or 0xffff for PF */ + uint16_t evc_function; + /* VLAN ID of the associated function */ + uint16_t evc_vid; + /* vport id shared with client driver */ + efx_vport_id_t evc_vport_id; + /* MAC address of the associated function */ + uint8_t evc_mac_addr[EFX_MAC_ADDR_LEN]; + /* + * vports created with this flag set may only transfer traffic on the + * VLANs permitted by the vport. Also, an attempt to install filter with + * VLAN will be refused unless requesting function has VLAN privilege. + */ + boolean_t evc_vlan_restrict; + /* Whether this function is assigned or not */ + boolean_t evc_vport_assigned; +} efx_vport_config_t; + +typedef struct efx_vswitch_s efx_vswitch_t; + extern __checkReturn efx_rc_t efx_evb_init( __in efx_nic_t *enp); @@ -3377,6 +3405,18 @@ extern __checkReturn __success(return != B_FALSE) boolean_t efx_evb_fini( __in efx_nic_t *enp); +extern __checkReturn efx_rc_t +efx_evb_vswitch_create( + __in efx_nic_t *enp, + __in uint32_t num_vports, + __inout_ecount(num_vports) efx_vport_config_t *vport_configp, + __deref_out efx_vswitch_t **evpp); + +extern __checkReturn efx_rc_t +efx_evb_vswitch_destroy( + __in efx_nic_t *enp, + __in efx_vswitch_t *evp); + #endif /* EFSYS_OPT_EVB */ #ifdef __cplusplus diff --git a/drivers/net/sfc/base/efx_evb.c b/drivers/net/sfc/base/efx_evb.c index ff240f9..27b466f 100644 --- a/drivers/net/sfc/base/efx_evb.c +++ b/drivers/net/sfc/base/efx_evb.c @@ -107,7 +107,7 @@ return (rc); } - void + void efx_evb_fini( __in efx_nic_t *enp) { @@ -125,4 +125,271 @@ enp->en_mod_flags &= ~EFX_MOD_EVB; } +/* + * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes + * equal to zero. A vport is assigned a MAC address after creation and this + * function checks if that has happened. It is called in the clean-up function + * before calling eeo_vport_mac_addr_del to ensure that the vport actually had + * an allocated MAC address. + */ + +__checkReturn boolean_t +efx_is_zero_eth_addr( + __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp) +{ + return (!(addrp[0] | addrp[1] | addrp[2] | + addrp[3] | addrp[4] | addrp[5])); +} + +static void +efx_evb_free_vport( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __inout efx_vport_config_t *configp) +{ + const efx_evb_ops_t *eeop = enp->en_eeop; + + /* If any callback fails, continue clean-up with others functions */ + if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) { + /* free vadaptor */ + if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) && + (eeop->eeo_vadaptor_free(enp, vswitch_id, + configp->evc_vport_id) != 0)) { + EFSYS_PROBE2(eeo_vadaptor_free, + uint16_t, configp->evc_function, + uint32_t, configp->evc_vport_id); + } + } else { + if (configp->evc_vport_assigned == B_TRUE) { + if (eeop->eeo_vport_assign(enp, vswitch_id, + EVB_PORT_ID_NULL, + configp->evc_function) != 0) { + EFSYS_PROBE1(eeo_vport_assign, + uint16_t, configp->evc_function); + } + configp->evc_vport_assigned = B_FALSE; + } + } + + /* + * Call eeo_vport_mac_addr_del after checking that this vport is + * actually allocated a MAC address in call to efx_evb_configure_vport + */ + if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) { + if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id, + configp->evc_vport_id, + configp->evc_mac_addr) != 0) { + EFSYS_PROBE1(eeo_vport_mac_addr_del, + uint16_t, configp->evc_function); + } + memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN); + } + + if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) { + if (eeop->eeo_vport_free(enp, vswitch_id, + configp->evc_vport_id) != 0) { + EFSYS_PROBE1(eeo_vport_free, + uint16_t, configp->evc_function); + } + configp->evc_vport_id = EFX_VPORT_ID_INVALID; + } +} + +static void +efx_evb_free_vports( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in uint32_t num_vports, + __inout_ecount(num_vports) efx_vport_config_t *vport_configp) +{ + efx_vport_config_t *configp; + uint32_t i; + + if (vport_configp == NULL) { + EFSYS_PROBE(null_vport_config); + return; + } + + for (i = 0; i < num_vports; i++) { + configp = vport_configp + i; + efx_evb_free_vport(enp, vswitch_id, configp); + } +} + +static __checkReturn efx_rc_t +efx_evb_configure_vport( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in const efx_evb_ops_t *eeop, + __inout efx_vport_config_t *configp) +{ + efx_rc_t rc; + efx_vport_id_t vport_id; + + if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id, + EFX_VPORT_TYPE_NORMAL, configp->evc_vid, + configp->evc_vlan_restrict, &vport_id)) != 0) + goto fail1; + + configp->evc_vport_id = vport_id; + + if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id, + configp->evc_vport_id, + configp->evc_mac_addr)) != 0) + goto fail2; + + if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) { + if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id, + configp->evc_vport_id)) != 0) + goto fail3; + } else { + if ((rc = eeop->eeo_vport_assign(enp, vswitch_id, + configp->evc_vport_id, + configp->evc_function)) != 0) + goto fail4; + configp->evc_vport_assigned = B_TRUE; + } + + return (0); + +fail4: + EFSYS_PROBE(fail4); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_evb_vswitch_create( + __in efx_nic_t *enp, + __in uint32_t num_vports, + __inout_ecount(num_vports) efx_vport_config_t *vport_configp, + __deref_out efx_vswitch_t **evpp) +{ + efx_vswitch_t *evp; + efx_rc_t rc; + efx_vswitch_id_t vswitch_id; + efx_vport_config_t *configp; + const efx_evb_ops_t *eeop = enp->en_eeop; + uint32_t i; + + /* vport_configp is a caller allocated array filled in with vports + * configuration. Index 0 carries the PF vport configuration and next + * num_vports - 1 indices carry VFs configuration. + */ + EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) && + (evpp != NULL)); + EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB); + EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); + + if ((eeop->eeo_vswitch_alloc == NULL) || + (eeop->eeo_vport_alloc == NULL) || + (eeop->eeo_vport_free == NULL) || + (eeop->eeo_vport_mac_addr_add == NULL) || + (eeop->eeo_vport_mac_addr_del == NULL) || + (eeop->eeo_vadaptor_alloc == NULL) || + (eeop->eeo_vadaptor_free == NULL) || + (eeop->eeo_vport_assign == NULL) || + (eeop->eeo_vswitch_free == NULL)) { + rc = ENOTSUP; + goto fail1; + } + + /* Allocate a vSwitch object */ + EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp); + + if (evp == NULL) { + rc = ENOMEM; + goto fail2; + } + + if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0) + goto fail3; + + evp->ev_enp = enp; + evp->ev_num_vports = num_vports; + evp->ev_evcp = vport_configp; + evp->ev_vswitch_id = vswitch_id; + + for (i = 0; i < num_vports; i++) { + configp = vport_configp + i; + + if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop, + configp)) != 0) + goto fail4; + } + + enp->en_vswitchp = evp; + *evpp = evp; + return (0); + +fail4: + EFSYS_PROBE(fail4); + efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp); + /* Free the vSwitch */ + eeop->eeo_vswitch_free(enp, vswitch_id); + +fail3: + EFSYS_PROBE(fail3); + /* Free the vSwitch object */ + EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp); + +fail2: + EFSYS_PROBE(fail2); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + + __checkReturn efx_rc_t +efx_evb_vswitch_destroy( + __in efx_nic_t *enp, + __in efx_vswitch_t *evp) +{ + const efx_evb_ops_t *eeop = enp->en_eeop; + efx_vswitch_id_t vswitch_id; + efx_rc_t rc; + + EFSYS_ASSERT(evp != NULL); + EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB); + + if ((eeop->eeo_vport_mac_addr_del == NULL) || + (eeop->eeo_vadaptor_free == NULL) || + (eeop->eeo_vport_assign == NULL) || + (eeop->eeo_vport_free == NULL) || + (eeop->eeo_vswitch_free == NULL)) { + rc = ENOTSUP; + goto fail1; + } + + vswitch_id = evp->ev_vswitch_id; + efx_evb_free_vports(enp, vswitch_id, + evp->ev_num_vports, evp->ev_evcp); + + /* Free the vSwitch object */ + EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp); + enp->en_vswitchp = NULL; + + /* Free the vSwitch */ + if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + #endif diff --git a/drivers/net/sfc/base/efx_impl.h b/drivers/net/sfc/base/efx_impl.h index ef6a97a..46d5389 100644 --- a/drivers/net/sfc/base/efx_impl.h +++ b/drivers/net/sfc/base/efx_impl.h @@ -652,6 +652,17 @@ #if EFSYS_OPT_EVB +struct efx_vswitch_s { + efx_nic_t *ev_enp; + efx_vswitch_id_t ev_vswitch_id; + uint32_t ev_num_vports; + /* + * Vport configuration array: index 0 to store PF configuration + * and next ev_num_vports-1 entries hold VFs configuration. + */ + efx_vport_config_t *ev_evcp; +}; + typedef struct efx_evb_ops_s { efx_rc_t (*eeo_init)(efx_nic_t *); void (*eeo_fini)(efx_nic_t *); @@ -674,6 +685,10 @@ efx_vport_id_t, uint32_t); } efx_evb_ops_t; +extern __checkReturn boolean_t +efx_is_zero_eth_addr( + __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp); + #endif /* EFSYS_OPT_EVB */ #define EFX_DRV_VER_MAX 20 @@ -776,6 +791,7 @@ struct efx_nic_s { #endif /* EFX_OPTS_EF10() */ #if EFSYS_OPT_EVB const efx_evb_ops_t *en_eeop; + struct efx_vswitch_s *en_vswitchp; #endif /* EFSYS_OPT_EVB */ };