From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id E6DB01B1F9 for ; Wed, 10 Jan 2018 18:49:39 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Jan 2018 09:49:39 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,341,1511856000"; d="scan'208";a="20544765" Received: from rhorton-mobl1.ger.corp.intel.com (HELO FC23.ger.corp.intel.com) ([10.252.19.205]) by fmsmga001.fm.intel.com with ESMTP; 10 Jan 2018 09:49:38 -0800 From: Remy Horton To: dev@dpdk.org Cc: John McNamara , Beilei Xing , Declan Doherty , Mohammad Abdul Awal Date: Wed, 10 Jan 2018 17:49:29 +0000 Message-Id: <20180110174931.2163-4-remy.horton@intel.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20180110174931.2163-1-remy.horton@intel.com> References: <20180110174931.2163-1-remy.horton@intel.com> Subject: [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality 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: Wed, 10 Jan 2018 17:49:41 -0000 Port Representors provide a logical presentation in DPDK of VF (virtual function) ports for the purposes of control and monitoring. Each port representor device represents a single VF and is associated with it's parent physical function (PF) PMD which provides the back-end hooks for the representor device ops and defines the control domain to which that port belongs. This allows to use existing DPDK APIs to monitor and control the port without the need to create and maintain VF specific APIs. This patch adds to the i40e PMD the functions required to enable port representor functionality. Signed-off-by: Declan Doherty Signed-off-by: Mohammad Abdul Awal Signed-off-by: Remy Horton --- MAINTAINERS | 2 + drivers/net/i40e/Makefile | 2 + drivers/net/i40e/i40e_ethdev.c | 19 + drivers/net/i40e/i40e_ethdev.h | 1 + drivers/net/i40e/i40e_port_representor_ops.c | 516 +++++++++++++++++++++++++++ drivers/net/i40e/i40e_port_representor_ops.h | 19 + drivers/net/i40e/rte_pmd_i40e.c | 43 +++ drivers/net/i40e/rte_pmd_i40e.h | 18 + drivers/net/i40e/rte_pmd_i40e_version.map | 7 + 9 files changed, 627 insertions(+) create mode 100644 drivers/net/i40e/i40e_port_representor_ops.c create mode 100644 drivers/net/i40e/i40e_port_representor_ops.h diff --git a/MAINTAINERS b/MAINTAINERS index c48f1b5..b720566 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -787,6 +787,8 @@ M: Mohammad Abdul Awal M: Remy Horton F: lib/librte_representor F: doc/guides/prog_guide/representor_lib.rst +F: drivers/net/i40e/i40e_prep_ops.c +F: drivers/net/i40e/i40e_prep_ops.h Packet Framework diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile index 4b9634d..521640b 100644 --- a/drivers/net/i40e/Makefile +++ b/drivers/net/i40e/Makefile @@ -14,6 +14,7 @@ CFLAGS += -DX722_A0_SUPPORT LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash LDLIBS += -lrte_bus_pci +LDLIBS += -lrte_representor EXPORT_MAP := rte_pmd_i40e_version.map @@ -85,6 +86,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_port_representor_ops.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 285d92b..7e1443c 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -36,6 +36,7 @@ #include "i40e_ethdev.h" #include "i40e_rxtx.h" #include "i40e_pf.h" +#include "i40e_port_representor_ops.h" #include "i40e_regs.h" #include "rte_pmd_i40e.h" @@ -1093,6 +1094,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev) hw->bus.func = pci_dev->addr.function; hw->adapter_stopped = 0; + /* init representor broker */ + if (rte_representor_enabled()) { + ret = i40e_port_representor_broker_init(dev, &pf->broker, + pci_dev); + if (ret) { + PMD_INIT_LOG(ERR, "Representor broker register failed " + "with ret=%d\n", ret); + return ret; + } + } + /* Make sure all is clean before doing PF reset */ i40e_clear_hw(hw); @@ -1428,6 +1440,13 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev) pci_dev = RTE_ETH_DEV_TO_PCI(dev); intr_handle = &pci_dev->intr_handle; + /* free port representor pmds */ + if (rte_representor_enabled()) { + ret = i40e_port_representor_broker_uninit(dev, pf->broker); + if (ret) + PMD_INIT_LOG(ERR, "Representor broker unregister" + " failed with ret=%d\n", ret); + } if (hw->adapter_stopped == 0) i40e_dev_close(dev); diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index f2b4b70..cadecbf 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -928,6 +928,7 @@ struct i40e_pf { bool gtp_replace_flag; /* 1 - GTP-C/U filter replace is done */ bool qinq_replace_flag; /* QINQ filter replace is done */ struct i40e_tm_conf tm_conf; + struct rte_representor_broker *broker; /* Dynamic Device Personalization */ bool gtp_support; /* 1 - support GTP-C and GTP-U */ diff --git a/drivers/net/i40e/i40e_port_representor_ops.c b/drivers/net/i40e/i40e_port_representor_ops.c new file mode 100644 index 0000000..ddd9e77 --- /dev/null +++ b/drivers/net/i40e/i40e_port_representor_ops.c @@ -0,0 +1,516 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation. + */ + +#include +#include +#include + +#include "base/i40e_type.h" +#include "base/virtchnl.h" +#include "i40e_ethdev.h" +#include "i40e_port_representor_ops.h" +#include "i40e_rxtx.h" +#include "rte_pmd_i40e.h" + + +struct i40e_representor_private_data { + struct rte_eth_dev *pf_ethdev; +}; + +static int +i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + return i40e_dev_link_update(i40e_priv_data->pf_ethdev, + wait_to_complete); +} + +static void +i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev, + struct rte_eth_dev_info *dev_info) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + struct i40e_pf_vf *vf; + struct i40e_vsi *vsi; + struct i40e_pf *pf; + + if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) { + PMD_DRV_LOG(ERR, "Invalid PF dev."); + return; + } + + pf = I40E_DEV_PRIVATE_TO_PF( + i40e_priv_data->pf_ethdev->data->dev_private); + if (representor->vport_id >= pf->vf_num || !pf->vfs) { + PMD_DRV_LOG(ERR, "Invalid VF ID."); + return; + } + + vf = &pf->vfs[representor->vport_id]; + vsi = vf->vsi; + if (!vsi) { + PMD_DRV_LOG(ERR, "Invalid VSI."); + return; + } + + /* get dev info for the vdev */ + dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev); + dev_info->max_rx_queues = vsi->nb_qps; + dev_info->max_tx_queues = vsi->nb_qps; + 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, + }; +} + +static int i40e_representor_dev_configure(__rte_unused struct rte_eth_dev *dev) +{ + return 0; +} + +static int i40e_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_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_representor_dev_start(__rte_unused struct rte_eth_dev *dev) +{ + return 0; +} + +static void i40e_representor_dev_stop(__rte_unused struct rte_eth_dev *dev) +{ +} + +static int +i40e_representor_stats_get(struct rte_eth_dev *ethdev, + struct rte_eth_stats *stats) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + return rte_pmd_i40e_get_vf_stats( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, stats); +} + +static void +i40e_representor_stats_reset(struct rte_eth_dev *ethdev) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id); +} + +static void +i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_set_vf_unicast_promisc( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, 1); +} + +static void +i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_set_vf_unicast_promisc( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, 0); +} + +static void +i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_set_vf_multicast_promisc( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, 1); +} + +static void +i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_set_vf_multicast_promisc( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, 0); +} + +static void +i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_remove_vf_mac_addr( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, ðdev->data->mac_addrs[index]); +} + +static void +i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev, + struct ether_addr *mac_addr) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_set_vf_mac_addr( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, mac_addr); +} + +static int +i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev, + uint16_t vlan_id, int on) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + uint32_t vfid; + uint64_t vf_mask; + + vfid = representor->vport_id; + vf_mask = 1ULL << vfid; + + return rte_pmd_i40e_set_vf_vlan_filter( + i40e_priv_data->pf_ethdev->data->port_id, + vlan_id, vf_mask, on); +} + +static int +i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + struct rte_eth_dev *pdev; + struct i40e_pf_vf *vf; + struct i40e_vsi *vsi; + struct i40e_pf *pf; + uint32_t vfid; + + pdev = i40e_priv_data->pf_ethdev; + vfid = representor->vport_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; + } + + /* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter, + * hw_vlan_strip, and hw_vlan_extend. + * currently the hw_vlan_extend offload by vsi is not implemented. + */ + + 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_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev, + __rte_unused uint16_t rx_queue_id, int on) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + rte_pmd_i40e_set_vf_vlan_stripq( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, on); +} + +static int +i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id, + __rte_unused int on) +{ + struct rte_representor_port *representor = ethdev->data->dev_private; + struct i40e_representor_private_data *i40e_priv_data = + representor->priv_data; + + return rte_pmd_i40e_set_vf_vlan_insert( + i40e_priv_data->pf_ethdev->data->port_id, + representor->vport_id, vlan_id); +} + +struct eth_dev_ops i40e_representor_dev_ops = { + .link_update = i40e_representor_link_update, + .dev_infos_get = i40e_representor_dev_infos_get, + .dev_configure = i40e_representor_dev_configure, + .rx_queue_setup = i40e_representor_rx_queue_setup, + .tx_queue_setup = i40e_representor_tx_queue_setup, + .dev_start = i40e_representor_dev_start, + .dev_stop = i40e_representor_dev_stop, + + .stats_get = i40e_representor_stats_get, + .stats_reset = i40e_representor_stats_reset, + + .promiscuous_enable = i40e_representor_promiscuous_enable, + .promiscuous_disable = i40e_representor_promiscuous_disable, + + .allmulticast_enable = i40e_representor_allmulticast_enable, + .allmulticast_disable = i40e_representor_allmulticast_disable, + + .mac_addr_remove = i40e_representor_mac_addr_remove, + .mac_addr_set = i40e_representor_mac_addr_set, + + .vlan_filter_set = i40e_representor_vlan_filter_set, + .vlan_offload_set = i40e_representor_vlan_offload_set, + .vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set, + .vlan_pvid_set = i40e_representor_vlan_pvid_set +}; + +static uint16_t i40e_representor_rx_burst(__rte_unused void *rxq, + __rte_unused struct rte_mbuf **rx_pkts, + __rte_unused uint16_t nb_pkts) +{ + return 0; +} + +static uint16_t i40e_representor_tx_burst(__rte_unused void *txq, + __rte_unused struct rte_mbuf **tx_pkts, + __rte_unused uint16_t nb_pkts) +{ + return 0; +} + +static int +i40e_port_representor_init(struct rte_representor_broker *broker, + struct rte_eth_dev *ethdev) +{ + struct rte_eth_dev *pf_ethdev; + struct rte_eth_link *link; + struct rte_representor_port *port; + struct i40e_pf *i40e_pf; + struct i40e_pf_vf *i40e_vf; + + port = ethdev->data->dev_private; + + /** + * Allocate private data for i40e port representor and save the physical + * functions ethdev handle + */ + port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data", + sizeof(struct i40e_representor_private_data), + RTE_CACHE_LINE_SIZE, ethdev->device->numa_node); + if (!port->priv_data) + return -ENOMEM; + + pf_ethdev = (struct rte_eth_dev *)broker->private_data; + + ((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev = + pf_ethdev; + + + i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private); + i40e_vf = &i40e_pf->vfs[port->vport_id]; + + if (!i40e_vf->vsi) { + PMD_DRV_LOG(ERR, "Invalid VSI."); + return -EINVAL; + } + + /* Set representor device ops */ + ethdev->dev_ops = &i40e_representor_dev_ops; + + /* Setting the number queues allocated to the VF */ + ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps; + ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps; + + /* Link state. Inherited from PF */ + link = &pf_ethdev->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; + + /* No data-path so no RX/TX functions */ + ethdev->rx_pkt_burst = i40e_representor_rx_burst; + ethdev->tx_pkt_burst = i40e_representor_tx_burst; + + return 0; +} + +static int +i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused, + struct rte_eth_dev *ethdev) +{ + struct rte_representor_port *port = ethdev->data->dev_private; + + rte_free(port->priv_data); + + return 0; +} + +struct rte_representor_broker_port_ops i40e_broker_port_ops = { + .port_init = i40e_port_representor_init, + .port_uninit = i40e_port_representor_uninit +}; + +int +i40e_port_representor_broker_init(struct rte_eth_dev *dev, + struct rte_representor_broker **broker, + const struct rte_pci_device *pci_dev) +{ + struct rte_bus *bus; + + *broker = rte_zmalloc_socket("rte_port_representor_broker", + sizeof(**broker), RTE_CACHE_LINE_SIZE, + rte_socket_id()); + if (!*broker) { + RTE_LOG(ERR, EAL, "Not enough memory for representor " + "broker\n"); + return -ENOMEM; + } + + bus = rte_bus_find_by_device(&pci_dev->device); + + /* Set i40e broker parameters */ + (*broker)->bus = bus->name; + (*broker)->device = pci_dev->name; + (*broker)->nb_virtual_ports = pci_dev->max_vfs; + (*broker)->ops = &i40e_broker_port_ops; + (*broker)->private_data = dev; + + return rte_representor_broker_init(*broker); +} + +int +i40e_port_representor_broker_uninit(__rte_unused struct rte_eth_dev *dev, + struct rte_representor_broker *broker) +{ + int ret; + + ret = rte_representor_broker_uninit(broker); + if (ret) + return ret; + + rte_free(broker); + + return 0; +} diff --git a/drivers/net/i40e/i40e_port_representor_ops.h b/drivers/net/i40e/i40e_port_representor_ops.h new file mode 100644 index 0000000..b7187ee --- /dev/null +++ b/drivers/net/i40e/i40e_port_representor_ops.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation. + */ + +#ifndef _I40E_PORT_REPRESENTOR_OPS_H_ +#define _I40E_PORT_REPRESENTOR_OPS_H_ + +#include + +int +i40e_port_representor_broker_init(struct rte_eth_dev *dev, + struct rte_representor_broker **broker, + const struct rte_pci_device *pci_dev); + +int +i40e_port_representor_broker_uninit(struct rte_eth_dev *dev, + struct rte_representor_broker *broker); + +#endif /* _I40E_PORT_REPRESENTOR_OPS_H_ */ diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c index 947f13b..afe20a8 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 7ca37b1..89f4fea 100644 --- a/drivers/net/i40e/rte_pmd_i40e.h +++ b/drivers/net/i40e/rte_pmd_i40e.h @@ -439,6 +439,24 @@ 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 * * @param port diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map index ebbd24e..4faff5a 100644 --- a/drivers/net/i40e/rte_pmd_i40e_version.map +++ b/drivers/net/i40e/rte_pmd_i40e_version.map @@ -58,3 +58,10 @@ DPDK_17.11 { rte_pmd_i40e_rss_queue_region_conf; } DPDK_17.08; + +DPDK_18.02 { + global: + + rte_pmd_i40e_remove_vf_mac_addr; + +}DPDK_17.11; -- 2.9.5