[dpdk-dev] [PATCH v3 3/5] drivers/net/i40e: add Port Representor functionality

Remy Horton remy.horton at intel.com
Fri Dec 22 15:52:19 CET 2017


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 <declan.doherty at intel.com>
Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal at intel.com>
Signed-off-by: Remy Horton <remy.horton at intel.com>
---
 drivers/net/i40e/Makefile        |   1 +
 drivers/net/i40e/i40e_ethdev.c   |  16 ++
 drivers/net/i40e/i40e_ethdev.h   |   1 +
 drivers/net/i40e/i40e_prep_ops.c | 495 +++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h |  15 ++
 drivers/net/i40e/rte_pmd_i40e.c  |  47 ++++
 drivers/net/i40e/rte_pmd_i40e.h  |  18 ++
 7 files changed, 593 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 9ab8c84..641bf26 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -113,6 +113,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_prep_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 811cc9f..65bb320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -67,6 +67,7 @@
 #include "i40e_pf.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
+#include "i40e_prep_ops.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG	"enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG	"floating_veb_list"
@@ -1122,6 +1123,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);
 
@@ -1457,6 +1469,10 @@ 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())
+		rte_representor_broker_uninit(pf->broker);
+
 	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 cd67453..9e962eb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -957,6 +957,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_prep_ops.c b/drivers/net/i40e/i40e_prep_ops.c
new file mode 100644
index 0000000..41ce4d4
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.c
@@ -0,0 +1,495 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+#include "i40e_prep_ops.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_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, &ethdev->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_prep_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_prep_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_prep_rx_burst;
+	ethdev->tx_pkt_burst = i40e_prep_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);
+}
diff --git a/drivers/net/i40e/i40e_prep_ops.h b/drivers/net/i40e/i40e_prep_ops.h
new file mode 100644
index 0000000..8e28b9e
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _I40E_PREP_OPS_H_
+#define _I40E_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _I40E_PREP_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index aeb92af..641a35c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -599,6 +599,53 @@ 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(uint8_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)) {
+		PMD_DRV_LOG(ERR, "Mac address does not match.");
+		return -EINVAL;
+	}
+
+	/* reset the mac with null mac */
+	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 580ca4a..1b1f725 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -467,6 +467,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(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
-- 
2.9.5



More information about the dev mailing list