From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 594B32BD0 for ; Wed, 29 Jun 2016 15:07:00 +0200 (CEST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga102.jf.intel.com with ESMTP; 29 Jun 2016 06:06:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,546,1459839600"; d="scan'208";a="1012005519" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by fmsmga002.fm.intel.com with ESMTP; 29 Jun 2016 06:06:10 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id u5TD68Qv026969; Wed, 29 Jun 2016 21:06:08 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id u5TD66nC027122; Wed, 29 Jun 2016 21:06:08 +0800 Received: (from zhetao@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id u5TD66qV027118; Wed, 29 Jun 2016 21:06:06 +0800 From: Zhe Tao To: dev@dpdk.org Cc: zhe.tao@intel.com, jingjing.wu@intel.com Date: Wed, 29 Jun 2016 21:06:02 +0800 Message-Id: <1467205563-25901-2-git-send-email-zhe.tao@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1467205563-25901-1-git-send-email-zhe.tao@intel.com> References: <1467012016-8273-1-git-send-email-zhe.tao@intel.com> <1467205563-25901-1-git-send-email-zhe.tao@intel.com> Subject: [dpdk-dev] [PATCH v15 1/2] i40e: add floating VEB support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Jun 2016 13:07:01 -0000 The standard Virtual Ethernet Bridge(VEB) definition in 1Qbg is a bridge which has an uplink port to the outside world (maybe another bridge), but a "floating" VEB is a special VEB without an uplink port to the outside. Instead, traffic can be sent from one VF to another using the floating VEB - even when the physical link on the NIC port is down. VFs VSIs connect either to the standard VEB/VEPA or to the floating VEB, they cannot connect to both of them. The PF, VMDQ and FD VSIs still connect to the normal VEB/VEPA. Signed-off-by: Zhe Tao --- drivers/net/i40e/i40e_ethdev.c | 113 +++++++++++++++++++++++++++++++++-------- drivers/net/i40e/i40e_ethdev.h | 7 +++ drivers/net/i40e/i40e_pf.c | 12 ++++- 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index f94ad87..5efcbc2 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -3768,21 +3768,27 @@ i40e_veb_release(struct i40e_veb *veb) struct i40e_vsi *vsi; struct i40e_hw *hw; - if (veb == NULL || veb->associate_vsi == NULL) + if (veb == NULL) return -EINVAL; if (!TAILQ_EMPTY(&veb->head)) { PMD_DRV_LOG(ERR, "VEB still has VSI attached, can't remove"); return -EACCES; } + /* associate_vsi field is NULL for floating VEB */ + if (veb->associate_vsi != NULL) { + vsi = veb->associate_vsi; + hw = I40E_VSI_TO_HW(vsi); - vsi = veb->associate_vsi; - hw = I40E_VSI_TO_HW(vsi); + vsi->uplink_seid = veb->uplink_seid; + vsi->veb = NULL; + } else { + veb->associate_pf->main_vsi->floating_veb = NULL; + hw = I40E_VSI_TO_HW(veb->associate_pf->main_vsi); + } - vsi->uplink_seid = veb->uplink_seid; i40e_aq_delete_element(hw, veb->seid, NULL); rte_free(veb); - vsi->veb = NULL; return I40E_SUCCESS; } @@ -3794,9 +3800,9 @@ i40e_veb_setup(struct i40e_pf *pf, struct i40e_vsi *vsi) int ret; struct i40e_hw *hw; - if (NULL == pf || vsi == NULL) { - PMD_DRV_LOG(ERR, "veb setup failed, " - "associated VSI shouldn't null"); + if (pf == NULL) { + PMD_DRV_LOG(ERR, + "veb setup failed, associated PF shouldn't null"); return NULL; } hw = I40E_PF_TO_HW(pf); @@ -3808,11 +3814,19 @@ i40e_veb_setup(struct i40e_pf *pf, struct i40e_vsi *vsi) } veb->associate_vsi = vsi; + veb->associate_pf = pf; TAILQ_INIT(&veb->head); - veb->uplink_seid = vsi->uplink_seid; + veb->uplink_seid = vsi ? vsi->uplink_seid : 0; - ret = i40e_aq_add_veb(hw, veb->uplink_seid, vsi->seid, - I40E_DEFAULT_TCMAP, false, &veb->seid, false, NULL); + /* create floating veb if vsi is NULL */ + if (vsi != NULL) { + ret = i40e_aq_add_veb(hw, veb->uplink_seid, vsi->seid, + I40E_DEFAULT_TCMAP, false, + &veb->seid, false, NULL); + } else { + ret = i40e_aq_add_veb(hw, 0, 0, I40E_DEFAULT_TCMAP, + true, &veb->seid, false, NULL); + } if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Add veb failed, aq_err: %d", @@ -3828,10 +3842,10 @@ i40e_veb_setup(struct i40e_pf *pf, struct i40e_vsi *vsi) hw->aq.asq_last_status); goto fail; } - /* Get VEB bandwidth, to be implemented */ /* Now associated vsi binding to the VEB, set uplink to this VEB */ - vsi->uplink_seid = veb->seid; + if (vsi) + vsi->uplink_seid = veb->seid; return veb; fail: @@ -3847,6 +3861,7 @@ i40e_vsi_release(struct i40e_vsi *vsi) struct i40e_vsi_list *vsi_list; int ret; struct i40e_mac_filter *f; + uint16_t user_param = vsi->user_param; if (!vsi) return I40E_SUCCESS; @@ -3864,12 +3879,22 @@ i40e_vsi_release(struct i40e_vsi *vsi) i40e_veb_release(vsi->veb); } + if (vsi->floating_veb) { + TAILQ_FOREACH(vsi_list, &vsi->floating_veb->head, list) { + if (i40e_vsi_release(vsi_list->vsi) != I40E_SUCCESS) + return -1; + TAILQ_REMOVE(&vsi->floating_veb->head, vsi_list, list); + } + } + /* Remove all macvlan filters of the VSI */ i40e_vsi_remove_all_macvlan_filter(vsi); TAILQ_FOREACH(f, &vsi->mac_list, next) rte_free(f); - if (vsi->type != I40E_VSI_MAIN) { + if (vsi->type != I40E_VSI_MAIN && + ((vsi->type != I40E_VSI_SRIOV) || + !pf->floating_veb_list[user_param])) { /* Remove vsi from parent's sibling list */ if (vsi->parent_vsi == NULL || vsi->parent_vsi->veb == NULL) { PMD_DRV_LOG(ERR, "VSI's parent VSI is NULL"); @@ -3883,6 +3908,24 @@ i40e_vsi_release(struct i40e_vsi *vsi) if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to delete element"); } + + if ((vsi->type == I40E_VSI_SRIOV) && + pf->floating_veb_list[user_param]) { + /* Remove vsi from parent's sibling list */ + if (vsi->parent_vsi == NULL || + vsi->parent_vsi->floating_veb == NULL) { + PMD_DRV_LOG(ERR, "VSI's parent VSI is NULL"); + return I40E_ERR_PARAM; + } + TAILQ_REMOVE(&vsi->parent_vsi->floating_veb->head, + &vsi->sib_vsi_list, list); + + /* Remove all switch element of the VSI */ + ret = i40e_aq_delete_element(hw, vsi->seid, NULL); + if (ret != I40E_SUCCESS) + PMD_DRV_LOG(ERR, "Failed to delete element"); + } + i40e_res_pool_free(&pf->qp_pool, vsi->base_queue); if (vsi->type != I40E_VSI_SRIOV) @@ -4051,7 +4094,8 @@ i40e_vsi_setup(struct i40e_pf *pf, struct ether_addr broadcast = {.addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; - if (type != I40E_VSI_MAIN && uplink_vsi == NULL) { + if (type != I40E_VSI_MAIN && type != I40E_VSI_SRIOV && + uplink_vsi == NULL) { PMD_DRV_LOG(ERR, "VSI setup failed, " "VSI link shouldn't be NULL"); return NULL; @@ -4063,11 +4107,18 @@ i40e_vsi_setup(struct i40e_pf *pf, return NULL; } - /* If uplink vsi didn't setup VEB, create one first */ - if (type != I40E_VSI_MAIN && uplink_vsi->veb == NULL) { + /* two situations + * 1.type is not MAIN and uplink vsi is not NULL + * If uplink vsi didn't setup VEB, create one first under veb field + * 2.type is SRIOV and the uplink is NULL + * If floating VEB is NULL, create one veb under floating veb field + */ + + if (type != I40E_VSI_MAIN && uplink_vsi != NULL && + uplink_vsi->veb == NULL) { uplink_vsi->veb = i40e_veb_setup(pf, uplink_vsi); - if (NULL == uplink_vsi->veb) { + if (uplink_vsi->veb == NULL) { PMD_DRV_LOG(ERR, "VEB setup failed"); return NULL; } @@ -4075,6 +4126,16 @@ i40e_vsi_setup(struct i40e_pf *pf, i40e_enable_pf_lb(pf); } + if (type == I40E_VSI_SRIOV && uplink_vsi == NULL && + pf->main_vsi->floating_veb == NULL) { + pf->main_vsi->floating_veb = i40e_veb_setup(pf, uplink_vsi); + + if (pf->main_vsi->floating_veb == NULL) { + PMD_DRV_LOG(ERR, "VEB setup failed"); + return NULL; + } + } + vsi = rte_zmalloc("i40e_vsi", sizeof(struct i40e_vsi), 0); if (!vsi) { PMD_DRV_LOG(ERR, "Failed to allocate memory for vsi"); @@ -4084,7 +4145,7 @@ i40e_vsi_setup(struct i40e_pf *pf, vsi->type = type; vsi->adapter = I40E_PF_TO_ADAPTER(pf); vsi->max_macaddrs = I40E_NUM_MACADDR_MAX; - vsi->parent_vsi = uplink_vsi; + vsi->parent_vsi = uplink_vsi ? uplink_vsi : pf->main_vsi; vsi->user_param = user_param; /* Allocate queues */ switch (vsi->type) { @@ -4238,7 +4299,10 @@ i40e_vsi_setup(struct i40e_pf *pf, * For other VSI, the uplink_seid equals to uplink VSI's * uplink_seid since they share same VEB */ - vsi->uplink_seid = uplink_vsi->uplink_seid; + if (uplink_vsi == NULL) + vsi->uplink_seid = pf->main_vsi->floating_veb->seid; + else + vsi->uplink_seid = uplink_vsi->uplink_seid; ctxt.pf_num = hw->pf_id; ctxt.vf_num = hw->func_caps.vf_base_id + user_param; ctxt.uplink_seid = vsi->uplink_seid; @@ -4346,8 +4410,13 @@ i40e_vsi_setup(struct i40e_pf *pf, vsi->seid = ctxt.seid; vsi->vsi_id = ctxt.vsi_number; vsi->sib_vsi_list.vsi = vsi; - TAILQ_INSERT_TAIL(&uplink_vsi->veb->head, - &vsi->sib_vsi_list, list); + if (vsi->type == I40E_VSI_SRIOV && uplink_vsi == NULL) { + TAILQ_INSERT_TAIL(&pf->main_vsi->floating_veb->head, + &vsi->sib_vsi_list, list); + } else { + TAILQ_INSERT_TAIL(&uplink_vsi->veb->head, + &vsi->sib_vsi_list, list); + } } /* MAC/VLAN configuration */ diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index cfd2399..19c9dea 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -55,6 +55,8 @@ #define I40E_VFTA_SIZE (4096 / I40E_UINT32_BIT_SIZE) /* Maximun number of MAC addresses */ #define I40E_NUM_MACADDR_MAX 64 +/* Maximum number of VFs */ +#define I40E_MAX_VF 128 /* * vlan_id is a 12 bit number. @@ -219,6 +221,7 @@ struct i40e_bw_info { struct i40e_veb { struct i40e_vsi_list_head head; struct i40e_vsi *associate_vsi; /* Associate VSI who owns the VEB */ + struct i40e_pf *associate_pf; /* Associate PF who owns the VEB */ uint16_t seid; /* The seid of VEB itself */ uint16_t uplink_seid; /* The uplink seid of this VEB */ uint16_t stats_idx; @@ -259,6 +262,7 @@ struct i40e_vsi { struct i40e_vsi_list sib_vsi_list; /* sibling vsi list */ struct i40e_vsi *parent_vsi; struct i40e_veb *veb; /* Associated veb, could be null */ + struct i40e_veb *floating_veb; /* Associated floating veb */ bool offset_loaded; enum i40e_vsi_type type; /* VSI types */ uint16_t vlan_num; /* Total VLAN number */ @@ -450,6 +454,9 @@ struct i40e_pf { struct i40e_fc_conf fc_conf; /* Flow control conf */ struct i40e_mirror_rule_list mirror_list; uint16_t nb_mirror_rule; /* The number of mirror rules */ + bool floating_veb; /* The flag to use the floating VEB */ + /* The floating enable flag for the specific VF */ + bool floating_veb_list[I40E_MAX_VF]; }; enum pending_msg { diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c index 5afd61a..dc5b079 100644 --- a/drivers/net/i40e/i40e_pf.c +++ b/drivers/net/i40e/i40e_pf.c @@ -124,6 +124,7 @@ i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset) { uint32_t val, i; struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); + struct i40e_pf *pf; uint16_t vf_id, abs_vf_id, vf_msix_num; int ret; struct i40e_virtchnl_queue_select qsel; @@ -131,6 +132,7 @@ i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset) if (vf == NULL) return -EINVAL; + pf = vf->pf; vf_id = vf->vf_idx; abs_vf_id = vf_id + hw->func_caps.vf_base_id; @@ -224,8 +226,14 @@ i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset) I40E_WRITE_FLUSH(hw); /* Allocate resource again */ - vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV, - vf->pf->main_vsi, vf->vf_idx); + if (pf->floating_veb && pf->floating_veb_list[vf_id]) { + vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV, + NULL, vf->vf_idx); + } else { + vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV, + vf->pf->main_vsi, vf->vf_idx); + } + if (vf->vsi == NULL) { PMD_DRV_LOG(ERR, "Add vsi failed"); return -EFAULT; -- 2.1.4