From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 861C9AAEE for ; Mon, 16 Apr 2018 15:14:48 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Apr 2018 06:14:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,459,1517904000"; d="scan'208";a="33739909" Received: from dwdohert-ws.ir.intel.com ([163.33.210.60]) by orsmga007.jf.intel.com with ESMTP; 16 Apr 2018 06:14:46 -0700 From: Declan Doherty To: dev@dpdk.org Cc: Adrien Mazarguil , Ferruh Yigit , Thomas Monjalon , Shahaf Shuler , Declan Doherty , Mohammad Abdul Awal , Remy Horton Date: Mon, 16 Apr 2018 14:06:04 +0100 Message-Id: <20180416130605.6509-9-declan.doherty@intel.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180416130605.6509-1-declan.doherty@intel.com> References: <20180328135433.20203-1-declan.doherty@intel.com> <20180416130605.6509-1-declan.doherty@intel.com> Subject: [dpdk-dev] [PATCH v7 8/9] net/i40e: add support for representor ports 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: , X-List-Received-Date: Mon, 16 Apr 2018 13:14:49 -0000 Add support for virtual function representor ports to the i40e PF driver. When SR-IOV virtual functions devices are enabled a corresponding representor port for each VF can be enabled, in the process in which the i40e PMD is running, by specifying the representor devargs with the list of VF ports that representors are to be created for. An example of the devargs which would create VF representor for virtual functions 0,2,4,5,6 and 7 is: -w pci:D:B:D.F,representor=[0,2,4-7] Signed-off-by: Declan Doherty Signed-off-by: Mohammad Abdul Awal Signed-off-by: Remy Horton --- drivers/net/i40e/Makefile | 3 + drivers/net/i40e/i40e_ethdev.c | 82 ++++++- drivers/net/i40e/i40e_ethdev.h | 16 ++ drivers/net/i40e/i40e_vf_representor.c | 405 +++++++++++++++++++++++++++++++++ drivers/net/i40e/meson.build | 4 +- drivers/net/i40e/rte_pmd_i40e.c | 43 ++++ drivers/net/i40e/rte_pmd_i40e.h | 18 ++ lib/librte_ether/rte_ethdev.c | 2 +- 8 files changed, 564 insertions(+), 9 deletions(-) create mode 100644 drivers/net/i40e/i40e_vf_representor.c diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile index 5663f5b1c..6184b38f3 100644 --- a/drivers/net/i40e/Makefile +++ b/drivers/net/i40e/Makefile @@ -11,6 +11,8 @@ LIB = librte_pmd_i40e.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -DPF_DRIVER -DVF_DRIVER -DINTEGRATED_VF CFLAGS += -DX722_A0_SUPPORT +CFLAGS += -DALLOW_EXPERIMENTAL_API + LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash LDLIBS += -lrte_bus_pci @@ -85,6 +87,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c +SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_vf_representor.c ifeq ($(findstring RTE_MACHINE_CPUFLAG_AVX2,$(CFLAGS)),RTE_MACHINE_CPUFLAG_AVX2) CC_AVX2_SUPPORT=1 diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 180ac7449..ad19af42f 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -213,7 +213,7 @@ /* Bit mask of Extended Tag enable/disable */ #define PCI_DEV_CTRL_EXT_TAG_MASK (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT) -static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev); +static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev, void *init_params); static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev); static int i40e_dev_configure(struct rte_eth_dev *dev); static int i40e_dev_start(struct rte_eth_dev *dev); @@ -607,16 +607,74 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = { #define I40E_NB_TXQ_PRIO_XSTATS (sizeof(rte_i40e_txq_prio_strings) / \ sizeof(rte_i40e_txq_prio_strings[0])) -static int eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + +static int +eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev) { - return rte_eth_dev_pci_generic_probe(pci_dev, - sizeof(struct i40e_adapter), eth_i40e_dev_init); + char name[RTE_ETH_NAME_MAX_LEN]; + struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 }; + int i, retval; + + retval = rte_eth_devargs_parse(pci_dev->device.devargs->args, ð_da); + if (retval) + return retval; + + /* physical port net_bdf_port */ + snprintf(name, sizeof(name), "net_%s", pci_dev->device.name); + + retval = rte_eth_dev_create(&pci_dev->device, name, + sizeof(struct i40e_adapter), + eth_dev_pci_specific_init, pci_dev, + eth_i40e_dev_init, NULL); + + if (retval || eth_da.nb_representor_ports < 1) + return retval; + + /* probe VF representor ports */ + struct rte_eth_dev *pf_ethdev = rte_eth_dev_allocated(name); + + if (pf_ethdev == NULL) + return -ENODEV; + + for (i = 0; i < eth_da.nb_representor_ports; i++) { + struct i40e_vf_representor representor = { + .vf_id = eth_da.representor_ports[i], + .switch_domain_id = I40E_DEV_PRIVATE_TO_PF( + pf_ethdev->data->dev_private)->switch_domain_id, + .adapter = I40E_DEV_PRIVATE_TO_ADAPTER( + pf_ethdev->data->dev_private) + }; + + /* representor port net_bdf_port */ + snprintf(name, sizeof(name), "net_%s_representor_%d", + pci_dev->device.name, eth_da.representor_ports[i]); + + retval = rte_eth_dev_create(&pci_dev->device, name, + sizeof(struct i40e_vf_representor), NULL, NULL, + i40e_vf_representor_init, &representor); + + if (retval) + PMD_DRV_LOG(ERR, "failed to create i40e vf " + "representor %s.", name); + } + + return 0; } static int eth_i40e_pci_remove(struct rte_pci_device *pci_dev) { - return rte_eth_dev_pci_generic_remove(pci_dev, eth_i40e_dev_uninit); + struct rte_eth_dev *ethdev; + + ethdev = rte_eth_dev_allocated(pci_dev->device.name); + if (!ethdev) + return -ENODEV; + + + if (ethdev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) + return rte_eth_dev_destroy(ethdev, i40e_vf_representor_uninit); + else + return rte_eth_dev_destroy(ethdev, eth_i40e_dev_uninit); } static struct rte_pci_driver rte_i40e_pmd = { @@ -1090,7 +1148,7 @@ i40e_support_multi_driver(struct rte_eth_dev *dev) } static int -eth_i40e_dev_init(struct rte_eth_dev *dev) +eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused) { struct rte_pci_device *pci_dev; struct rte_intr_handle *intr_handle; @@ -1517,6 +1575,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev) pci_dev = RTE_ETH_DEV_TO_PCI(dev); intr_handle = &pci_dev->intr_handle; + ret = rte_eth_switch_domain_free(pf->switch_domain_id); + if (ret) + PMD_INIT_LOG(WARNING, "failed to free switch domain: %d", ret); + if (hw->adapter_stopped == 0) i40e_dev_close(dev); @@ -2323,7 +2385,7 @@ i40e_dev_reset(struct rte_eth_dev *dev) if (ret) return ret; - ret = eth_i40e_dev_init(dev); + ret = eth_i40e_dev_init(dev, NULL); return ret; } @@ -5748,6 +5810,12 @@ i40e_pf_setup(struct i40e_pf *pf) PMD_DRV_LOG(ERR, "Could not get switch config, err %d", ret); return ret; } + + ret = rte_eth_switch_domain_alloc(&pf->switch_domain_id); + if (ret) + PMD_INIT_LOG(WARNING, + "failed to allocate switch domain for device %d", ret); + if (pf->flags & I40E_FLAG_FDIR) { /* make queue allocated first, let FDIR use queue pair 0*/ ret = i40e_res_pool_alloc(&pf->qp_pool, I40E_DEFAULT_QP_NUM_FDIR); diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index d33b255e7..7aaae71c0 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -957,6 +957,8 @@ struct i40e_pf { bool gtp_support; /* 1 - support GTP-C and GTP-U */ /* customer customized pctype */ struct i40e_customized_pctype customized_pctype[I40E_CUSTOMIZED_MAX]; + /* Switch Domain Id */ + uint16_t switch_domain_id; }; enum pending_msg { @@ -1062,6 +1064,18 @@ struct i40e_adapter { uint64_t pctypes_mask; }; +/** + * Strucute to store private data for each VF representor instance + */ +struct i40e_vf_representor { + uint16_t switch_domain_id; + /**< Virtual Function ID */ + uint16_t vf_id; + /**< Virtual Function ID */ + struct i40e_adapter *adapter; + /**< Private data store of assocaiated physical function */ +}; + extern const struct rte_flow_ops i40e_flow_ops; union i40e_filter_t { @@ -1221,6 +1235,8 @@ int i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len); int i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size); int i40e_config_rss_filter(struct i40e_pf *pf, struct i40e_rte_flow_rss_conf *conf, bool add); +int i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params); +int i40e_vf_representor_uninit(struct rte_eth_dev *ethdev); #define I40E_DEV_TO_PCI(eth_dev) \ RTE_DEV_TO_PCI((eth_dev)->device) diff --git a/drivers/net/i40e/i40e_vf_representor.c b/drivers/net/i40e/i40e_vf_representor.c new file mode 100644 index 000000000..e11d9c0c9 --- /dev/null +++ b/drivers/net/i40e/i40e_vf_representor.c @@ -0,0 +1,405 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation. + */ + +#include +#include +#include +#include + +#include "base/i40e_type.h" +#include "base/virtchnl.h" +#include "i40e_ethdev.h" +#include "i40e_rxtx.h" +#include "rte_pmd_i40e.h" + +static int +i40e_vf_representor_link_update(struct rte_eth_dev *ethdev, + int wait_to_complete) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + return i40e_dev_link_update(representor->adapter->eth_dev, + wait_to_complete); +} +static void +i40e_vf_representor_dev_infos_get(struct rte_eth_dev *ethdev, + struct rte_eth_dev_info *dev_info) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + /* get dev info for the vdev */ + dev_info->device = ethdev->device; + + dev_info->max_rx_queues = ethdev->data->nb_rx_queues; + dev_info->max_tx_queues = ethdev->data->nb_tx_queues; + + dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN; + dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX; + dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) * + sizeof(uint32_t); + dev_info->reta_size = ETH_RSS_RETA_SIZE_64; + dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL; + dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX; + dev_info->rx_offload_capa = + DEV_RX_OFFLOAD_VLAN_STRIP | + DEV_RX_OFFLOAD_QINQ_STRIP | + DEV_RX_OFFLOAD_IPV4_CKSUM | + DEV_RX_OFFLOAD_UDP_CKSUM | + DEV_RX_OFFLOAD_TCP_CKSUM; + dev_info->tx_offload_capa = + DEV_TX_OFFLOAD_VLAN_INSERT | + DEV_TX_OFFLOAD_QINQ_INSERT | + DEV_TX_OFFLOAD_IPV4_CKSUM | + DEV_TX_OFFLOAD_UDP_CKSUM | + DEV_TX_OFFLOAD_TCP_CKSUM | + DEV_TX_OFFLOAD_SCTP_CKSUM | + DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM | + DEV_TX_OFFLOAD_TCP_TSO | + DEV_TX_OFFLOAD_VXLAN_TNL_TSO | + DEV_TX_OFFLOAD_GRE_TNL_TSO | + DEV_TX_OFFLOAD_IPIP_TNL_TSO | + DEV_TX_OFFLOAD_GENEVE_TNL_TSO; + + dev_info->default_rxconf = (struct rte_eth_rxconf) { + .rx_thresh = { + .pthresh = I40E_DEFAULT_RX_PTHRESH, + .hthresh = I40E_DEFAULT_RX_HTHRESH, + .wthresh = I40E_DEFAULT_RX_WTHRESH, + }, + .rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH, + .rx_drop_en = 0, + }; + + dev_info->default_txconf = (struct rte_eth_txconf) { + .tx_thresh = { + .pthresh = I40E_DEFAULT_TX_PTHRESH, + .hthresh = I40E_DEFAULT_TX_HTHRESH, + .wthresh = I40E_DEFAULT_TX_WTHRESH, + }, + .tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH, + .tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH, + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | + ETH_TXQ_FLAGS_NOOFFLOADS, + }; + + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = I40E_MAX_RING_DESC, + .nb_min = I40E_MIN_RING_DESC, + .nb_align = I40E_ALIGN_RING_DESC, + }; + + dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = I40E_MAX_RING_DESC, + .nb_min = I40E_MIN_RING_DESC, + .nb_align = I40E_ALIGN_RING_DESC, + }; + + dev_info->switch_info.name = + representor->adapter->eth_dev->device->name; + dev_info->switch_info.domain_id = representor->switch_domain_id; + dev_info->switch_info.port_id = representor->vf_id; +} + +static int +i40e_vf_representor_dev_configure(__rte_unused struct rte_eth_dev *dev) +{ + return 0; +} + +static int +i40e_vf_representor_dev_start(__rte_unused struct rte_eth_dev *dev) +{ + return 0; +} + +static void +i40e_vf_representor_dev_stop(__rte_unused struct rte_eth_dev *dev) +{ +} + +static int +i40e_vf_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev, + __rte_unused uint16_t rx_queue_id, + __rte_unused uint16_t nb_rx_desc, + __rte_unused unsigned int socket_id, + __rte_unused const struct rte_eth_rxconf *rx_conf, + __rte_unused struct rte_mempool *mb_pool) +{ + return 0; +} + +static int +i40e_vf_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev, + __rte_unused uint16_t rx_queue_id, + __rte_unused uint16_t nb_rx_desc, + __rte_unused unsigned int socket_id, + __rte_unused const struct rte_eth_txconf *tx_conf) +{ + return 0; +} + +static int +i40e_vf_representor_stats_get(struct rte_eth_dev *ethdev, + struct rte_eth_stats *stats) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + return rte_pmd_i40e_get_vf_stats( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, stats); +} + +static void +i40e_vf_representor_stats_reset(struct rte_eth_dev *ethdev) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_reset_vf_stats( + representor->adapter->eth_dev->data->port_id, + representor->vf_id); +} + +static void +i40e_vf_representor_promiscuous_enable(struct rte_eth_dev *ethdev) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_set_vf_unicast_promisc( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, 1); +} + +static void +i40e_vf_representor_promiscuous_disable(struct rte_eth_dev *ethdev) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_set_vf_unicast_promisc( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, 0); +} + + +static void +i40e_vf_representor_allmulticast_enable(struct rte_eth_dev *ethdev) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_set_vf_multicast_promisc( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, 1); +} + +static void +i40e_vf_representor_allmulticast_disable(struct rte_eth_dev *ethdev) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_set_vf_multicast_promisc( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, 0); +} + +static void +i40e_vf_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_remove_vf_mac_addr( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, ðdev->data->mac_addrs[index]); +} + +static int +i40e_vf_representor_mac_addr_set(struct rte_eth_dev *ethdev, + struct ether_addr *mac_addr) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + return rte_pmd_i40e_set_vf_mac_addr( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, mac_addr); +} + +static int +i40e_vf_representor_vlan_filter_set(struct rte_eth_dev *ethdev, + uint16_t vlan_id, int on) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + uint64_t vf_mask = 1ULL << representor->vf_id; + + return rte_pmd_i40e_set_vf_vlan_filter( + representor->adapter->eth_dev->data->port_id, + vlan_id, vf_mask, on); +} + +static int +i40e_vf_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + struct rte_eth_dev *pdev; + struct i40e_pf_vf *vf; + struct i40e_vsi *vsi; + struct i40e_pf *pf; + uint32_t vfid; + + pdev = representor->adapter->eth_dev; + vfid = representor->vf_id; + + if (!is_i40e_supported(pdev)) { + PMD_DRV_LOG(ERR, "Invalid PF dev."); + return -EINVAL; + } + + pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private); + + if (vfid >= pf->vf_num || !pf->vfs) { + PMD_DRV_LOG(ERR, "Invalid VF ID."); + return -EINVAL; + } + + vf = &pf->vfs[vfid]; + vsi = vf->vsi; + if (!vsi) { + PMD_DRV_LOG(ERR, "Invalid VSI."); + return -EINVAL; + } + + if (mask & ETH_VLAN_FILTER_MASK) { + /* Enable or disable VLAN filtering offload */ + if (ethdev->data->dev_conf.rxmode.hw_vlan_filter) + return i40e_vsi_config_vlan_filter(vsi, TRUE); + else + return i40e_vsi_config_vlan_filter(vsi, FALSE); + } + + if (mask & ETH_VLAN_STRIP_MASK) { + /* Enable or disable VLAN stripping offload */ + if (ethdev->data->dev_conf.rxmode.hw_vlan_strip) + return i40e_vsi_config_vlan_stripping(vsi, TRUE); + else + return i40e_vsi_config_vlan_stripping(vsi, FALSE); + } + + return -EINVAL; +} + +static void +i40e_vf_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev, + __rte_unused uint16_t rx_queue_id, int on) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + rte_pmd_i40e_set_vf_vlan_stripq( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, on); +} + +static int +i40e_vf_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id, + __rte_unused int on) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + return rte_pmd_i40e_set_vf_vlan_insert( + representor->adapter->eth_dev->data->port_id, + representor->vf_id, vlan_id); +} + +struct eth_dev_ops i40e_representor_dev_ops = { + .dev_infos_get = i40e_vf_representor_dev_infos_get, + + .dev_start = i40e_vf_representor_dev_start, + .dev_configure = i40e_vf_representor_dev_configure, + .dev_stop = i40e_vf_representor_dev_stop, + + .rx_queue_setup = i40e_vf_representor_rx_queue_setup, + .tx_queue_setup = i40e_vf_representor_tx_queue_setup, + + .link_update = i40e_vf_representor_link_update, + + .stats_get = i40e_vf_representor_stats_get, + .stats_reset = i40e_vf_representor_stats_reset, + + .promiscuous_enable = i40e_vf_representor_promiscuous_enable, + .promiscuous_disable = i40e_vf_representor_promiscuous_disable, + + .allmulticast_enable = i40e_vf_representor_allmulticast_enable, + .allmulticast_disable = i40e_vf_representor_allmulticast_disable, + + .mac_addr_remove = i40e_vf_representor_mac_addr_remove, + .mac_addr_set = i40e_vf_representor_mac_addr_set, + + .vlan_filter_set = i40e_vf_representor_vlan_filter_set, + .vlan_offload_set = i40e_vf_representor_vlan_offload_set, + .vlan_strip_queue_set = i40e_vf_representor_vlan_strip_queue_set, + .vlan_pvid_set = i40e_vf_representor_vlan_pvid_set + +}; + + +int +i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params) +{ + struct i40e_vf_representor *representor = ethdev->data->dev_private; + + struct i40e_pf *pf; + struct i40e_pf_vf *vf; + struct rte_eth_link *link; + + representor->vf_id = + ((struct i40e_vf_representor *)init_params)->vf_id; + representor->switch_domain_id = + ((struct i40e_vf_representor *)init_params)->switch_domain_id; + representor->adapter = + ((struct i40e_vf_representor *)init_params)->adapter; + + pf = I40E_DEV_PRIVATE_TO_PF( + representor->adapter->eth_dev->data->dev_private); + + if (representor->vf_id >= pf->vf_num) + return -ENODEV; + + /** representor shares the same driver as it's PF device */ + ethdev->device->driver = representor->adapter->eth_dev->device->driver; + + /* Set representor device ops */ + ethdev->dev_ops = &i40e_representor_dev_ops; + + /* No data-path so no RX/TX functions */ + ethdev->rx_pkt_burst = NULL; + ethdev->tx_pkt_burst = NULL; + + vf = &pf->vfs[representor->vf_id]; + + if (!vf->vsi) { + PMD_DRV_LOG(ERR, "Invalid VSI."); + return -ENODEV; + } + + ethdev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; + + /* Setting the number queues allocated to the VF */ + ethdev->data->nb_rx_queues = vf->vsi->nb_qps; + ethdev->data->nb_tx_queues = vf->vsi->nb_qps; + + ethdev->data->mac_addrs = &vf->mac_addr; + + /* Link state. Inherited from PF */ + link = &representor->adapter->eth_dev->data->dev_link; + + ethdev->data->dev_link.link_speed = link->link_speed; + ethdev->data->dev_link.link_duplex = link->link_duplex; + ethdev->data->dev_link.link_status = link->link_status; + ethdev->data->dev_link.link_autoneg = link->link_autoneg; + + return 0; +} + + +int +i40e_vf_representor_uninit(struct rte_eth_dev *ethdev __rte_unused) +{ + return 0; +} diff --git a/drivers/net/i40e/meson.build b/drivers/net/i40e/meson.build index 197e611d8..f2129df07 100644 --- a/drivers/net/i40e/meson.build +++ b/drivers/net/i40e/meson.build @@ -6,7 +6,8 @@ version = 2 cflags += ['-DPF_DRIVER', '-DVF_DRIVER', '-DINTEGRATED_VF', - '-DX722_A0_SUPPORT'] + '-DX722_A0_SUPPORT', + '-DALLOW_EXPERIMENTAL_API'] subdir('base') objs = [base_objs] @@ -19,6 +20,7 @@ sources = files( 'i40e_fdir.c', 'i40e_flow.c', 'i40e_tm.c', + 'i40e_vf_representor.c', 'rte_pmd_i40e.c' ) diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c index 9f9a6504d..7aa1a7518 100644 --- a/drivers/net/i40e/rte_pmd_i40e.c +++ b/drivers/net/i40e/rte_pmd_i40e.c @@ -570,6 +570,49 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id, return 0; } +static const struct ether_addr null_mac_addr; + +int +rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id, + struct ether_addr *mac_addr) +{ + struct rte_eth_dev *dev; + struct i40e_pf_vf *vf; + struct i40e_vsi *vsi; + struct i40e_pf *pf; + + if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS) + return -EINVAL; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); + + dev = &rte_eth_devices[port]; + + if (!is_i40e_supported(dev)) + return -ENOTSUP; + + pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); + + if (vf_id >= pf->vf_num || !pf->vfs) + return -EINVAL; + + vf = &pf->vfs[vf_id]; + vsi = vf->vsi; + if (!vsi) { + PMD_DRV_LOG(ERR, "Invalid VSI."); + return -EINVAL; + } + + if (is_same_ether_addr(mac_addr, &vf->mac_addr)) + /* Reset the mac with NULL address */ + ether_addr_copy(&null_mac_addr, &vf->mac_addr); + + /* Remove the mac */ + i40e_vsi_delete_mac(vsi, mac_addr); + + return 0; +} + /* Set vlan strip on/off for specific VF from host */ int rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on) diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h index d248adb1a..be4a6024a 100644 --- a/drivers/net/i40e/rte_pmd_i40e.h +++ b/drivers/net/i40e/rte_pmd_i40e.h @@ -455,6 +455,24 @@ int rte_pmd_i40e_set_vf_multicast_promisc(uint16_t port, int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id, struct ether_addr *mac_addr); +/** + * Remove the VF MAC address. + * + * @param port + * The port identifier of the Ethernet device. + * @param vf_id + * VF id. + * @param mac_addr + * VF MAC address. + * @return + * - (0) if successful. + * - (-ENODEV) if *port* invalid. + * - (-EINVAL) if *vf* or *mac_addr* is invalid. + */ +int +rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id, + struct ether_addr *mac_addr); + /** * Enable/Disable vf vlan strip for all queues in a pool * diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index d1f95161f..7a4bde127 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -34,7 +34,7 @@ #include #include #include -+#include +#include #include "rte_ether.h" #include "rte_ethdev.h" -- 2.14.3