[RFC PATCH 0/5] add API's for VF management

STALE3638d

Revision rfc of 10 in this series.

90 messages, 9 authors, 2016-10-12 · page 1 of 2 · open the first message on its own page

[RFC PATCH 0/5] add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-08-18 13:48:50

This RFC patchset contains new DPDK API's requested by AT&T for use
with the Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the
point where AT&T have devloped a DPDK based tool, VFD, to do this.

This RFC proposes to add the following API extensions to DPDK:
  mailbox communication callback support
  VF configuration

Nine new functions have been added to the eth_dev_ops structure.
Corresponding functions have been added to the ixgbe PMD for the
Niantic NIC.

Two new callback functions have been added.
Changes have been made to the ixgbe_rcv_msg_from_vf function to
use the callback functions.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd changes.

Note:
Adding new functions to the eth_dev_ops structure will cause an
ABI breakage.

Bernard Iremonger (5):
  librte_ether: add internal callback functions
  net/ixgbe: add callback to user app on VF to PF mbox msg
  librte_ether: add API's for VF management
  net/ixgbe: add functions for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 700 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  68 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c            | 179 +++++++
 drivers/net/ixgbe/ixgbe_pf.c                |  39 +-
 lib/librte_ether/rte_ethdev.c               | 176 +++++++
 lib/librte_ether/rte_ethdev.h               | 284 +++++++++++
 lib/librte_ether/rte_ether_version.map      |  16 +
 7 files changed, 1455 insertions(+), 7 deletions(-)

-- 
2.9.0

[RFC PATCH 1/5] librte_ether: add internal callback functions

From: Bernard Iremonger <hidden>
Date: 2016-08-18 13:48:52

add _rte_eth_dev_callback_process_vf function.
add _rte_eth_dev_callback_process_generic function

Adding a callback to the user application on VF to PF mailbox message,
allows passing information to the application controlling the PF
when a VF mailbox event message is received, such as VF reset.

Signed-off-by: azelezniak <redacted>
Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 17 ++++++++++
 lib/librte_ether/rte_ethdev.h          | 61 ++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 ++++
 3 files changed, 85 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f62a9ec..1388ea3 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2690,6 +2690,20 @@ void
 _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 	enum rte_eth_event_type event)
 {
+	return _rte_eth_dev_callback_process_generic(dev, event, NULL);
+}
+
+void
+_rte_eth_dev_callback_process_vf(struct rte_eth_dev *dev,
+	enum rte_eth_event_type event, void *param)
+{
+	return _rte_eth_dev_callback_process_generic(dev, event, param);
+}
+
+void
+_rte_eth_dev_callback_process_generic(struct rte_eth_dev *dev,
+	enum rte_eth_event_type event, void *param)
+{
 	struct rte_eth_dev_callback *cb_lst;
 	struct rte_eth_dev_callback dev_cb;
 
@@ -2699,6 +2713,9 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 			continue;
 		dev_cb = *cb_lst;
 		cb_lst->active = 1;
+		if (param != NULL)
+			dev_cb.cb_arg = (void *) param;
+
 		rte_spinlock_unlock(&rte_eth_dev_cb_lock);
 		dev_cb.cb_fn(dev->data->port_id, dev_cb.event,
 						dev_cb.cb_arg);
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index b0fe033..4fb0b9c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3047,9 +3047,27 @@ enum rte_eth_event_type {
 				/**< queue state event (enabled/disabled) */
 	RTE_ETH_EVENT_INTR_RESET,
 			/**< reset interrupt event, sent to VF on PF reset */
+	RTE_ETH_EVENT_VF_MBOX,  /**< PF mailbox processing callback */
 	RTE_ETH_EVENT_MAX       /**< max value of this enum */
 };
 
+/**
+ * Response sent back to ixgbe driver from user app after callback
+ */
+enum rte_eth_mb_event_rsp {
+	RTE_ETH_MB_EVENT_NOOP_ACK,  /**< skip mbox request and ACK */
+	RTE_ETH_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+	RTE_ETH_MB_EVENT_PROCEED,  /**< proceed with mbox request  */
+	RTE_ETH_MB_EVENT_MAX       /**< max value of this enum */
+};
+
+struct rte_eth_mb_event_param {
+	uint16_t vfid;
+	uint16_t msg_type;
+	uint16_t retval;
+	void *userdata;
+};
+
 typedef void (*rte_eth_dev_cb_fn)(uint8_t port_id, \
 		enum rte_eth_event_type event, void *cb_arg);
 /**< user application callback to be registered for interrupts */
@@ -3114,6 +3132,49 @@ void _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 				enum rte_eth_event_type event);
 
 /**
+ * @internal Executes all the user application registered callbacks for
+ * the specific device where parameter have to be passed to user application.
+ * It is for DPDK internal user only. User application should not call it
+ * directly.
+ *
+ * @param dev
+ *  Pointer to struct rte_eth_dev.
+ * @param event
+ *  Eth device interrupt event type.
+ *
+ * @param param
+ *  parameters to pass back to user application.
+ *
+ * @return
+ *  void
+ */
+
+void
+_rte_eth_dev_callback_process_vf(struct rte_eth_dev *dev,
+				enum rte_eth_event_type event, void *param);
+
+/**
+ * @internal Executes all the user application registered callbacks. Used by:
+ * _rte_eth_dev_callback_process and _rte_eth_dev_callback_process_vf
+ * It is for DPDK internal user only. User application should not call it
+ * directly.
+ *
+ * @param dev
+ *  Pointer to struct rte_eth_dev.
+ * @param event
+ *  Eth device interrupt event type.
+ *
+ * @param param
+ *  parameters to pass back to user application.
+ *
+ * @return
+ *  void
+ */
+void
+_rte_eth_dev_callback_process_generic(struct rte_eth_dev *dev,
+				enum rte_eth_event_type event, void *param);
+
+/**
  * When there is no rx packet coming in Rx Queue for a long time, we can
  * sleep lcore related to RX Queue for power saving, and enable rx interrupt
  * to be triggered when rx packect arrives.
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 45ddf44..cb7ef15 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,10 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	_rte_eth_dev_callback_process_generic;
+	_rte_eth_dev_callback_process_vf;
+} DPDK_16.07;
-- 
2.9.0

[RFC PATCH 2/5] net/ixgbe: add callback to user app on VF to PF mbox msg

From: Bernard Iremonger <hidden>
Date: 2016-08-18 13:48:53

call _rte_eth_dev_callback_process_vf from ixgbe_rcv_msg_from_vf function.

The callback asks the user application if it is allowed to perform
the function.
If the cb_param.retval is RTE_ETH_MB_EVENT_PROCEED then continue,
if 0, do nothing and send ACK to VF
if > 1, do nothing and send NAK to VF.

Signed-off-by: azelezniak <redacted>
Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_pf.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_pf.c b/drivers/net/ixgbe/ixgbe_pf.c
index 56393ff..bb14106 100644
--- a/drivers/net/ixgbe/ixgbe_pf.c
+++ b/drivers/net/ixgbe/ixgbe_pf.c
@@ -660,6 +660,7 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_vf_info *vfinfo =
 		*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+	struct rte_eth_mb_event_param cb_param;
 
 	retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
 	if (retval) {
@@ -674,27 +675,54 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 	/* flush the ack before we write any messages back */
 	IXGBE_WRITE_FLUSH(hw);
 
+	/**
+	 * initialise structure to send to user application
+	 * will return response from user in retval field
+	 */
+	cb_param.retval = RTE_ETH_MB_EVENT_PROCEED;
+	cb_param.vfid = vf;
+	cb_param.msg_type = msgbuf[0] & 0xFFFF;
+	cb_param.userdata = (void *)msgbuf;
+
 	/* perform VF reset */
 	if (msgbuf[0] == IXGBE_VF_RESET) {
 		int ret = ixgbe_vf_reset(dev, vf, msgbuf);
 
 		vfinfo[vf].clear_to_send = true;
+
+		/* notify application about VF reset */
+		_rte_eth_dev_callback_process_vf(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
 		return ret;
 	}
 
+	/**
+	 * ask user application if we allowed to perform those functions
+	 * if we get cb_param.retval == RTE_ETH_MB_EVENT_PROCEED then business
+	 * as usual,
+	 * if 0, do nothing and send ACK to VF
+	 * if cb_param.retval > 1, do nothing and send NAK to VF
+	 */
+	_rte_eth_dev_callback_process_vf(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
+
+	retval = cb_param.retval;
+
 	/* check & process VF to PF mailbox message */
 	switch ((msgbuf[0] & 0xFFFF)) {
 	case IXGBE_VF_SET_MAC_ADDR:
-		retval = ixgbe_vf_set_mac_addr(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_vf_set_mac_addr(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_SET_MULTICAST:
-		retval = ixgbe_vf_set_multicast(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_vf_set_multicast(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_SET_LPE:
-		retval = ixgbe_set_vf_lpe(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_set_vf_lpe(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_SET_VLAN:
-		retval = ixgbe_vf_set_vlan(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_vf_set_vlan(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_API_NEGOTIATE:
 		retval = ixgbe_negotiate_vf_api(dev, vf, msgbuf);
@@ -704,7 +732,8 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 		msg_size = IXGBE_VF_GET_QUEUE_MSG_SIZE;
 		break;
 	case IXGBE_VF_UPDATE_XCAST_MODE:
-		retval = ixgbe_set_vf_mc_promisc(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_set_vf_mc_promisc(dev, vf, msgbuf);
 		break;
 	default:
 		PMD_DRV_LOG(DEBUG, "Unhandled Msg %8.8x", (unsigned)msgbuf[0]);
-- 
2.9.0

[RFC PATCH 4/5] net/ixgbe: add functions for VF management

From: Bernard Iremonger <hidden>
Date: 2016-08-18 13:48:54

Add new functions to configure and manage VF's on a Niantic NIC.

add ixgbe_vf_ping function.
add ixgbe_set_vf_vlan_anti_spoof function.
add ixgbe_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add ixgbe_set_vf_vlan_strip function
add ixgbe_set_vf_vlan_insert function.
add ixgbe_set_tx_loopback function.
add ixgbe_set_all_queues_drop function.
add ixgbe_set_vf_split_drop_en function.
add ixgbe_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 179 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 179 insertions(+)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index d478a15..3b0ee82 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -240,6 +240,8 @@ static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
 static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev,
 					   struct ether_addr *mac_addr);
+static int ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf,
+				struct ether_addr *mac_addr);
 static void ixgbe_dcb_init(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config);
 
 /* For Virtual Function support */
@@ -280,6 +282,19 @@ static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
 static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
 static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 		uint64_t pool_mask, uint8_t vlan_on);
+static void ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static void ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static int ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf);
+static void ixgbe_set_vf_vlan_strip(struct rte_eth_dev *dev,
+		int on, uint16_t queues_per_pool);
+static void ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf,
+		int vlan);
+static void ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on);
+static void ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state);
+static void ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf,
+		int state);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 		struct rte_eth_mirror_conf *mirror_conf,
 		uint8_t rule_id, uint8_t on);
@@ -505,6 +520,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.mac_addr_add         = ixgbe_add_rar,
 	.mac_addr_remove      = ixgbe_remove_rar,
 	.mac_addr_set         = ixgbe_set_default_mac_addr,
+	.set_vf_mac_addr      = ixgbe_set_vf_mac_addr,
 	.uc_hash_table_set    = ixgbe_uc_hash_table_set,
 	.uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
 	.mirror_rule_set      = ixgbe_mirror_rule_set,
@@ -513,6 +529,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.set_vf_rx            = ixgbe_set_pool_rx,
 	.set_vf_tx            = ixgbe_set_pool_tx,
 	.set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
+	.set_vf_vlan_anti_spoof  = ixgbe_set_vf_vlan_anti_spoof,
+	.set_vf_mac_anti_spoof   = ixgbe_set_vf_mac_anti_spoof,
+	.vf_ping              = ixgbe_vf_ping,
+	.set_vf_vlan_strip    = ixgbe_set_vf_vlan_strip,
+	.set_vf_vlan_insert   = ixgbe_set_vf_vlan_insert,
+	.set_tx_loopback      = ixgbe_set_tx_loopback,
+	.set_all_queues_drop_en = ixgbe_set_all_queues_drop_en,
+	.set_vf_split_drop_en = ixgbe_set_vf_split_drop_en,
 	.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
 	.set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
 	.reta_update          = ixgbe_dev_rss_reta_update,
@@ -4012,6 +4036,22 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
 }
 
 static int
+ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf, struct ether_addr *mac_addr)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_vf_info *vfinfo =
+		*(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+	uint8_t *new_mac = (uint8_t *)(mac_addr);
+
+	if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
+		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, ETHER_ADDR_LEN);
+		return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV);
+	}
+	return -1;
+}
+
+static int
 ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
 	uint32_t hlreg0;
@@ -4315,6 +4355,16 @@ ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on)
 }
 
 static void
+ixgbe_set_vf_vlan_strip(struct rte_eth_dev *dev, int on,
+		uint16_t queues_per_pool)
+{
+	uint16_t q;
+
+	for (q = 0; q < queues_per_pool; q++)
+		ixgbevf_vlan_strip_queue_set(dev, q, on);
+}
+
+static void
 ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct ixgbe_hw *hw =
@@ -4604,6 +4654,135 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 	return ret;
 }
 
+static void
+ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_vlan_anti_spoofing(hw, on, vf);
+}
+
+static void
+ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_mac_anti_spoofing(hw, on, vf);
+}
+
+static int
+ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_vf_info *vfinfo =
+		*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+
+	u32 ping;
+	int i;
+
+	for (i = 0; i < dev->pci_dev->max_vfs; i++) {
+		ping = IXGBE_PF_CONTROL_MSG;
+		if (vfinfo[i].clear_to_send)
+			ping |= IXGBE_VT_MSGTYPE_CTS;
+
+		/* ping every VF or only one specified */
+		if (vf < 0 || vf == i)
+			ixgbe_write_mbx(hw, &ping, 1, i);
+	}
+
+	return ret;
+}
+
+static void
+ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf, int vlan)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+	if (vlan) {
+		ctrl = vlan;
+		ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
+	} else {
+		ctrl = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
+}
+
+static void
+ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+	/* enable or disable VMDQ loopback */
+	if (on)
+		ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
+	else
+		ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
+}
+
+static void
+ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+	int i;
+	int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i <= num_queues; i++) {
+		reg_value = IXGBE_QDE_WRITE |
+				(i << IXGBE_QDE_IDX_SHIFT) |
+				(state & IXGBE_QDE_ENABLE);
+		IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
+	}
+}
+
+static void
+ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* only support VF's 0 to 63 */
+	if (vf > 63)
+		return;
+
+	reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
+	if (state)
+		reg_value |= IXGBE_SRRCTL_DROP_EN;
+	else
+		reg_value &= ~IXGBE_SRRCTL_DROP_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
-- 
2.9.0

[RFC PATCH 3/5] librte_ether: add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-08-18 13:48:54

Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_strip function.
add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function
add rte_eth_dev_set_vf_mac_addr function.
increment LIBABIVER to 5.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 159 +++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 223 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |   9 ++
 3 files changed, 391 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1388ea3..2a3d2ae 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2306,6 +2306,22 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 }
 
 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct ether_addr *addr)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -ENOTSUP);
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr);
+}
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2490,6 +2506,149 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF VLAN anti spoof:VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF MAC anti spoof:VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_mac_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_vf_ping(uint8_t port_id, int32_t vf)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF ping: VF %d > 64\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_ping, -ENOTSUP);
+	return (*dev->dev_ops->vf_ping)(dev, vf);
+}
+
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint16_t queues_per_pool;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF vlan strip set VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_strip, -ENOTSUP);
+
+	rte_eth_dev_info_get(port_id, &dev_info);
+	queues_per_pool = dev_info.vmdq_queue_num/dev_info.max_vmdq_pools;
+
+	(*dev->dev_ops->set_vf_vlan_strip)(dev, on, queues_per_pool);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF vlan insert set VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_insert, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_vlan_insert)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_tx_loopback(uint8_t port_id, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_tx_loopback, -ENOTSUP);
+
+	(*dev->dev_ops->set_tx_loopback)(dev, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port_id, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_all_queues_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_all_queues_drop_en)(dev, state);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port_id, uint16_t vf, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_split_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_split_drop_en)(dev, vf, state);
+	return 0;
+}
+
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 4fb0b9c..ed3d61b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1230,6 +1230,11 @@ typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr);
 /**< @internal Set a MAC address into Receive Address Address Register */
 
+typedef int (*eth_set_vf_mac_addr_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  struct ether_addr *mac_addr);
+/**< @internal Set VF address into Receive Address Address Register */
+
 typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr,
 				  uint8_t on);
@@ -1261,6 +1266,43 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
 				  uint8_t vlan_on);
 /**< @internal Set VF VLAN pool filter */
 
+typedef void (*eth_set_vf_vlan_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF VLAN anti spoof */
+
+typedef void (*eth_set_vf_mac_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF MAC anti spoof */
+
+typedef int (*eth_vf_ping_t)(struct rte_eth_dev *dev,
+				int32_t vf);
+/**< @internal ping one or all vf's */
+
+typedef void (*eth_set_vf_vlan_strip_t)(struct rte_eth_dev *dev,
+				  int on,
+				  uint16_t queues_per_pool);
+/**< @internal Set VF vlan strip */
+
+typedef void (*eth_set_vf_vlan_insert_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int vlan);
+/**< @internal Set VF vlan insert */
+
+typedef void (*eth_set_tx_loopback_t)(struct rte_eth_dev *dev,
+				  int on);
+/**< @internal Set tx loopback */
+
+typedef void (*eth_set_all_queues_drop_en_t)(struct rte_eth_dev *dev,
+				  int state);
+/**< @internal Set all queues drop */
+
+typedef void (*eth_set_vf_split_drop_en_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int state);
+/**< @internal Set the enable drop bit in the VF split rx control register */
+
 typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
 				uint16_t queue_idx,
 				uint16_t tx_rate);
@@ -1465,6 +1507,7 @@ struct eth_dev_ops {
 	eth_mac_addr_remove_t      mac_addr_remove; /**< Remove MAC address */
 	eth_mac_addr_add_t         mac_addr_add;  /**< Add a MAC address */
 	eth_mac_addr_set_t         mac_addr_set;  /**< Set a MAC address */
+	eth_set_vf_mac_addr_t      set_vf_mac_addr;  /**< Set a VF MAC address */
 	eth_uc_hash_table_set_t    uc_hash_table_set;  /**< Set Unicast Table Array */
 	eth_uc_all_hash_table_set_t uc_all_hash_table_set;  /**< Set Unicast hash bitmap */
 	eth_mirror_rule_set_t	   mirror_rule_set;  /**< Add a traffic mirror rule.*/
@@ -1473,6 +1516,14 @@ struct eth_dev_ops {
 	eth_set_vf_rx_t            set_vf_rx;  /**< enable/disable a VF receive */
 	eth_set_vf_tx_t            set_vf_tx;  /**< enable/disable a VF transmit */
 	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
+	eth_set_vf_vlan_anti_spoof_t  set_vf_vlan_anti_spoof; /**< Set VF VLAN anti spoof */
+	eth_set_vf_mac_anti_spoof_t   set_vf_mac_anti_spoof;  /**< Set VF MAC anti spoof */
+	eth_vf_ping_t             vf_ping;  /**< Ping one or all VF's */
+	eth_set_vf_vlan_strip_t   set_vf_vlan_strip; /** <Set VF VLAN strip */
+	eth_set_vf_vlan_insert_t  set_vf_vlan_insert; /** <Set VF VLAN insert */
+	eth_set_tx_loopback_t  set_tx_loopback; /** <Set tx loopback */
+	eth_set_all_queues_drop_en_t  set_all_queues_drop_en; /** <Set queue drop enable bit */
+	eth_set_vf_split_drop_en_t  set_vf_split_drop_en; /** <Set split drop enable bit.*/
 	/** Add UDP tunnel port. */
 	eth_udp_tunnel_port_add_t udp_tunnel_port_add;
 	/** Del UDP tunnel port. */
@@ -3389,7 +3440,25 @@ int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr);
  */
 int rte_eth_dev_default_mac_addr_set(uint8_t port, struct ether_addr *mac_addr);
 
+/**
+ * Set the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
 
+ * @return
+ *   - (0) if successful, or *mac_addr* didn't exist.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if MAC address is invalid.
+ */
+
+int rte_eth_dev_set_vf_mac_addr(uint8_t port, uint16_t vf,
+				struct ether_addr *mac_addr);
 /**
  * Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device.
  *
@@ -3556,6 +3625,160 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
 				uint8_t vlan_on);
 
 /**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Ping all or specified VF
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   specify VF to ping or all if -1.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_vf_ping(uint8_t port, int32_t vf);
+
+/**
+ * Enable/Disable vf vlan strip
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan strip.
+ *    0 - Disable VF's vlan strip
+ * @param queues_per_pool
+ *    The number of queues per pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable vf vlan insert
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan insert.
+ *    0 - Disable VF's vlan insert
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable tx loopback
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable tx loopback.
+ *    0 - Disable tx loopback.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_tx_loopback(uint8_t port, int on);
+/**
+ * set all queues drop enable bit
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param state
+ *    1 - set the queue drop enable bit for all pools.
+ *    0 - reset the queue drop enable bit for all pools.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port, int state);
+/**
+ * set drop enable bit in the VF split rx control register
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param state
+ *    1 - set the drop enable bit in the split rx control register.
+ *    0 - reset the drop enable bit in the split rx control register.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port, uint16_t vf, int state);
+/**
  * Set a traffic mirroring rule on an Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index cb7ef15..c9649ee 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -145,4 +145,13 @@ DPDK_16.11 {
 
 	_rte_eth_dev_callback_process_generic;
 	_rte_eth_dev_callback_process_vf;
+	rte_eth_dev_set_all_queues_drop_en;
+	rte_eth_dev_set_tx_loopback;
+	rte_eth_dev_set_vf_mac_addr;
+	rte_eth_dev_set_vf_mac_anti_spoof;
+	rte_eth_dev_set_vf_split_drop_en;
+	rte_eth_dev_set_vf_vlan_anti_spoof;
+	rte_eth_dev_set_vf_vlan_insert;
+	rte_eth_dev_set_vf_vlan_strip;
+	rte_eth_dev_vf_ping;
 } DPDK_16.07;
-- 
2.9.0

[RFC PATCH 5/5] app/test_pmd: add tests for new API's

From: Bernard Iremonger <hidden>
Date: 2016-08-18 13:48:56

add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf ping
add test for vf vlan strip
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit
add test for vf split drop enable bit
add test for vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
---
 app/test-pmd/cmdline.c                      | 700 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  68 ++-
 2 files changed, 766 insertions(+), 2 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f90befc..12e89c3 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -10585,6 +10585,697 @@ cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
 	},
 };
 
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+	ret = rte_eth_dev_set_vf_vlan_anti_spoof(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan anti spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+	.f = cmd_set_vf_vlan_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan anti spoof",
+	.tokens = {
+		(void *)&cmd_vf_vlan_anti_spoof_set,
+		(void *)&cmd_vf_vlan_anti_spoof_vf,
+		(void *)&cmd_vf_vlan_anti_spoof_vlan,
+		(void *)&cmd_vf_vlan_anti_spoof_antispoof,
+		(void *)&cmd_vf_vlan_anti_spoof_port_id,
+		(void *)&cmd_vf_vlan_anti_spoof_vf_id,
+		(void *)&cmd_vf_vlan_anti_spoof_on,
+		NULL,
+	},
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_anti_spoof(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan mac spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+	.f = cmd_set_vf_mac_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf mac anti spoof",
+	.tokens = {
+		(void *)&cmd_vf_mac_anti_spoof_set,
+		(void *)&cmd_vf_mac_anti_spoof_vf,
+		(void *)&cmd_vf_mac_anti_spoof_mac,
+		(void *)&cmd_vf_mac_anti_spoof_antispoof,
+		(void *)&cmd_vf_mac_anti_spoof_port_id,
+		(void *)&cmd_vf_mac_anti_spoof_vf_id,
+		(void *)&cmd_vf_mac_anti_spoof_on,
+		NULL,
+	},
+};
+
+/* vf ping configuration */
+
+/* Common result structure for vf ping */
+struct cmd_vf_ping_result {
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t ping;
+	uint8_t port_id;
+	int32_t vf_id;
+};
+
+/* Common CLI fields for ping vfs */
+cmdline_parse_token_string_t cmd_vf_ping_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_ping_ping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 ping, "ping");
+cmdline_parse_token_num_t cmd_vf_ping_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_ping_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf_id, INT32);
+
+static void
+cmd_vf_ping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_ping_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_vf_ping(res->port_id, res->vf_id);
+	if (ret < 0)
+		printf("ping vfs programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_vf_ping = {
+	.f = cmd_vf_ping_parsed,
+	.data = NULL,
+	.help_str = "ping all or specified vf",
+	.tokens = {
+		(void *)&cmd_vf_ping_vf,
+		(void *)&cmd_vf_ping_ping,
+		(void *)&cmd_vf_ping_port_id,
+		(void *)&cmd_vf_ping_vf_id,
+		NULL,
+	},
+};
+
+/* vf vlan strip configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_strip_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t strip;
+	uint8_t port_id;
+	uint16_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_strip_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_strip =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 strip, "strip");
+cmdline_parse_token_num_t cmd_vf_vlan_strip_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_strip_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_strip_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_vlan_strip_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_strip_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_strip(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan strip programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_strip = {
+	.f = cmd_set_vf_vlan_strip_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan strip",
+	.tokens = {
+		(void *)&cmd_vf_vlan_strip_set,
+		(void *)&cmd_vf_vlan_strip_vf,
+		(void *)&cmd_vf_vlan_strip_vlan,
+		(void *)&cmd_vf_vlan_strip_strip,
+		(void *)&cmd_vf_vlan_strip_port_id,
+		(void *)&cmd_vf_vlan_strip_vf_id,
+		(void *)&cmd_vf_vlan_strip_on,
+		NULL,
+	},
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t insert;
+	uint8_t port_id;
+	uint16_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_insert_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_insert_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_insert(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan insert programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+	.f = cmd_set_vf_vlan_insert_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan insert",
+	.tokens = {
+		(void *)&cmd_vf_vlan_insert_set,
+		(void *)&cmd_vf_vlan_insert_vf,
+		(void *)&cmd_vf_vlan_insert_vlan,
+		(void *)&cmd_vf_vlan_insert_insert,
+		(void *)&cmd_vf_vlan_insert_port_id,
+		(void *)&cmd_vf_vlan_insert_vf_id,
+		(void *)&cmd_vf_vlan_insert_on,
+		NULL,
+	},
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t tx;
+	cmdline_fixed_string_t loopback;
+	uint8_t port_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_tx_loopback_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 on, UINT8);
+
+static void
+cmd_set_tx_loopback_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_tx_loopback_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_tx_loopback(res->port_id, res->on);
+	if (ret < 0)
+		printf("tx loopback programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+	.f = cmd_set_tx_loopback_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan insert",
+	.tokens = {
+		(void *)&cmd_tx_loopback_set,
+		(void *)&cmd_tx_loopback_tx,
+		(void *)&cmd_tx_loopback_loopback,
+		(void *)&cmd_tx_loopback_port_id,
+		(void *)&cmd_tx_loopback_on,
+		NULL,
+	},
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t queues;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 on, UINT8);
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_all_queues_drop_en_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_all_queues_drop_en(res->port_id, res->on);
+	if (ret < 0)
+		printf("all queues drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+	.f = cmd_set_all_queues_drop_en_parsed,
+	.data = NULL,
+	.help_str = "enable/disable all queues drop enable bits",
+	.tokens = {
+		(void *)&cmd_all_queues_drop_en_set,
+		(void *)&cmd_all_queues_drop_en_all,
+		(void *)&cmd_all_queues_drop_en_queues,
+		(void *)&cmd_all_queues_drop_en_drop,
+		(void *)&cmd_all_queues_drop_en_port_id,
+		(void *)&cmd_all_queues_drop_en_on,
+		NULL,
+	},
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t split;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint16_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_split_drop_en_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_split_drop_en(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf split drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+	.f = cmd_set_vf_split_drop_en_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf split drop enable",
+	.tokens = {
+		(void *)&cmd_vf_split_drop_en_set,
+		(void *)&cmd_vf_split_drop_en_vf,
+		(void *)&cmd_vf_split_drop_en_split,
+		(void *)&cmd_vf_split_drop_en_drop,
+		(void *)&cmd_vf_split_drop_en_port_id,
+		(void *)&cmd_vf_split_drop_en_vf_id,
+		(void *)&cmd_vf_split_drop_en_on,
+		NULL,
+	},
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t addr;
+	uint8_t port_id;
+	uint16_t vf_id;
+	struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+	TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+		 mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_vf_mac_addr_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_addr(res->port_id, res->vf_id, &res->mac_addr);
+	if (ret < 0)
+		printf("set vf mac addr programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+	.f = cmd_set_vf_mac_addr_parsed,
+	.data = NULL,
+	.help_str = "set vf mac address",
+	.tokens = {
+		(void *)&cmd_set_vf_mac_addr_set,
+		(void *)&cmd_set_vf_mac_addr_vf,
+		(void *)&cmd_set_vf_mac_addr_mac,
+		(void *)&cmd_set_vf_mac_addr_addr,
+		(void *)&cmd_set_vf_mac_addr_port_id,
+		(void *)&cmd_set_vf_mac_addr_vf_id,
+		(void *)&cmd_set_vf_mac_addr_mac_addr,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10739,6 +11430,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_vf_ping,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_strip,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f87e0c2..c26d901 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -473,6 +473,41 @@ For example, to change the port forwarding:
    RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03
    RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02
 
+set tx loopback
+~~~~~~~~~~~~~~~
+
+Enable/disable tx loopback::
+
+   testpmd> set tx loopback (port_id) (on|off)
+
+set drop enable
+~~~~~~~~~~~~~~~
+
+set drop enable bit for all queues::
+
+   testpmd> set all queues drop (port_id) (on|off)
+
+set split drop enable (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+set split drop enable bit for VF from PF::
+
+   testpmd> set vf split drop (port_id) (vf_id) (on|off)
+
+set mac antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set mac antispoof for a VF from the PF::
+
+   testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
+
+ping VF
+~~~~~~~
+
+Ping VF or all VF's from PF::
+
+   testpmd> vf ping (port_id) (vf_id | -1)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
@@ -487,6 +522,28 @@ Set the VLAN strip for a queue on a port::
 
    testpmd> vlan set stripq (on|off) (port_id,queue_id)
 
+vlan set strip (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN strip for a VF from the PF::
+
+   testpmd> set vf vlan strip (port_id) (vf_id) (on|off)
+
+vlan set insert (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN insert for a VF from the PF::
+
+   testpmd> set vf vlan insert  (port_id) (vf_id) (on|off)
+
+vlan set antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN antispoof for a VF from the PF::
+
+   testpmd> set vf vlan antispoof  (port_id) (vf_id) (on|off)
+
+
 vlan set filter
 ~~~~~~~~~~~~~~~
 
@@ -727,13 +784,20 @@ Remove a MAC address from a port::
 
    testpmd> mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)
 
-mac_addr add(for VF)
-~~~~~~~~~~~~~~~~~~~~
+mac_addr add (for VF)
+~~~~~~~~~~~~~~~~~~~~~
 
 Add an alternative MAC address for a VF to a port::
 
    testpmd> mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX)
 
+mac_addr set (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set the MAC address for a VF from the PF::
+
+   testpmd> set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)
+
 set port-uta
 ~~~~~~~~~~~~
 
-- 
2.9.0

[RFC PATCH v2 0/5] add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-08-26 09:10:25

This RFC patchset contains new DPDK API's requested by AT&T for use
with the Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the
point where AT&T have devloped a DPDK based tool, VFD, to do this.

This RFC proposes to add the following API extensions to DPDK:
  mailbox communication callback support
  VF configuration

Nine new functions have been added to the eth_dev_ops structure.
Corresponding functions have been added to the ixgbe PMD for the
Niantic NIC.

Two new callback functions have been added.
Changes have been made to the ixgbe_rcv_msg_from_vf function to
use the callback functions.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd changes.

Note:
Adding new functions to the eth_dev_ops structure will cause an
ABI breakage.

Changes in V2:
rebase to latest master branch.
fix compile  error with clang.

Bernard Iremonger (5):
  librte_ether: add internal callback functions
  net/ixgbe: add callback to user app on VF to PF mbox msg
  librte_ether: add API's for VF management
  net/ixgbe: add functions for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 700 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  68 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c            | 179 +++++++
 drivers/net/ixgbe/ixgbe_pf.c                |  39 +-
 lib/librte_ether/rte_ethdev.c               | 176 +++++++
 lib/librte_ether/rte_ethdev.h               | 284 +++++++++++
 lib/librte_ether/rte_ether_version.map      |  16 +
 7 files changed, 1455 insertions(+), 7 deletions(-)

-- 
2.9.0

[RFC PATCH v2 1/5] librte_ether: add internal callback functions

From: Bernard Iremonger <hidden>
Date: 2016-08-26 09:10:27

add _rte_eth_dev_callback_process_vf function.
add _rte_eth_dev_callback_process_generic function

Adding a callback to the user application on VF to PF mailbox message,
allows passing information to the application controlling the PF
when a VF mailbox event message is received, such as VF reset.

Signed-off-by: azelezniak <redacted>
Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 17 ++++++++++
 lib/librte_ether/rte_ethdev.h          | 61 ++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 ++++
 3 files changed, 85 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f62a9ec..1388ea3 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2690,6 +2690,20 @@ void
 _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 	enum rte_eth_event_type event)
 {
+	return _rte_eth_dev_callback_process_generic(dev, event, NULL);
+}
+
+void
+_rte_eth_dev_callback_process_vf(struct rte_eth_dev *dev,
+	enum rte_eth_event_type event, void *param)
+{
+	return _rte_eth_dev_callback_process_generic(dev, event, param);
+}
+
+void
+_rte_eth_dev_callback_process_generic(struct rte_eth_dev *dev,
+	enum rte_eth_event_type event, void *param)
+{
 	struct rte_eth_dev_callback *cb_lst;
 	struct rte_eth_dev_callback dev_cb;
 
@@ -2699,6 +2713,9 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 			continue;
 		dev_cb = *cb_lst;
 		cb_lst->active = 1;
+		if (param != NULL)
+			dev_cb.cb_arg = (void *) param;
+
 		rte_spinlock_unlock(&rte_eth_dev_cb_lock);
 		dev_cb.cb_fn(dev->data->port_id, dev_cb.event,
 						dev_cb.cb_arg);
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index b0fe033..4fb0b9c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3047,9 +3047,27 @@ enum rte_eth_event_type {
 				/**< queue state event (enabled/disabled) */
 	RTE_ETH_EVENT_INTR_RESET,
 			/**< reset interrupt event, sent to VF on PF reset */
+	RTE_ETH_EVENT_VF_MBOX,  /**< PF mailbox processing callback */
 	RTE_ETH_EVENT_MAX       /**< max value of this enum */
 };
 
+/**
+ * Response sent back to ixgbe driver from user app after callback
+ */
+enum rte_eth_mb_event_rsp {
+	RTE_ETH_MB_EVENT_NOOP_ACK,  /**< skip mbox request and ACK */
+	RTE_ETH_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+	RTE_ETH_MB_EVENT_PROCEED,  /**< proceed with mbox request  */
+	RTE_ETH_MB_EVENT_MAX       /**< max value of this enum */
+};
+
+struct rte_eth_mb_event_param {
+	uint16_t vfid;
+	uint16_t msg_type;
+	uint16_t retval;
+	void *userdata;
+};
+
 typedef void (*rte_eth_dev_cb_fn)(uint8_t port_id, \
 		enum rte_eth_event_type event, void *cb_arg);
 /**< user application callback to be registered for interrupts */
@@ -3114,6 +3132,49 @@ void _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 				enum rte_eth_event_type event);
 
 /**
+ * @internal Executes all the user application registered callbacks for
+ * the specific device where parameter have to be passed to user application.
+ * It is for DPDK internal user only. User application should not call it
+ * directly.
+ *
+ * @param dev
+ *  Pointer to struct rte_eth_dev.
+ * @param event
+ *  Eth device interrupt event type.
+ *
+ * @param param
+ *  parameters to pass back to user application.
+ *
+ * @return
+ *  void
+ */
+
+void
+_rte_eth_dev_callback_process_vf(struct rte_eth_dev *dev,
+				enum rte_eth_event_type event, void *param);
+
+/**
+ * @internal Executes all the user application registered callbacks. Used by:
+ * _rte_eth_dev_callback_process and _rte_eth_dev_callback_process_vf
+ * It is for DPDK internal user only. User application should not call it
+ * directly.
+ *
+ * @param dev
+ *  Pointer to struct rte_eth_dev.
+ * @param event
+ *  Eth device interrupt event type.
+ *
+ * @param param
+ *  parameters to pass back to user application.
+ *
+ * @return
+ *  void
+ */
+void
+_rte_eth_dev_callback_process_generic(struct rte_eth_dev *dev,
+				enum rte_eth_event_type event, void *param);
+
+/**
  * When there is no rx packet coming in Rx Queue for a long time, we can
  * sleep lcore related to RX Queue for power saving, and enable rx interrupt
  * to be triggered when rx packect arrives.
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 45ddf44..cb7ef15 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,10 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	_rte_eth_dev_callback_process_generic;
+	_rte_eth_dev_callback_process_vf;
+} DPDK_16.07;
-- 
2.9.0

[RFC PATCH v2 2/5] net/ixgbe: add callback to user app on VF to PF mbox msg

From: Bernard Iremonger <hidden>
Date: 2016-08-26 09:10:28

call _rte_eth_dev_callback_process_vf from ixgbe_rcv_msg_from_vf function.

The callback asks the user application if it is allowed to perform
the function.
If the cb_param.retval is RTE_ETH_MB_EVENT_PROCEED then continue,
if 0, do nothing and send ACK to VF
if > 1, do nothing and send NAK to VF.

Signed-off-by: azelezniak <redacted>
Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_pf.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_pf.c b/drivers/net/ixgbe/ixgbe_pf.c
index 56393ff..bb14106 100644
--- a/drivers/net/ixgbe/ixgbe_pf.c
+++ b/drivers/net/ixgbe/ixgbe_pf.c
@@ -660,6 +660,7 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_vf_info *vfinfo =
 		*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+	struct rte_eth_mb_event_param cb_param;
 
 	retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
 	if (retval) {
@@ -674,27 +675,54 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 	/* flush the ack before we write any messages back */
 	IXGBE_WRITE_FLUSH(hw);
 
+	/**
+	 * initialise structure to send to user application
+	 * will return response from user in retval field
+	 */
+	cb_param.retval = RTE_ETH_MB_EVENT_PROCEED;
+	cb_param.vfid = vf;
+	cb_param.msg_type = msgbuf[0] & 0xFFFF;
+	cb_param.userdata = (void *)msgbuf;
+
 	/* perform VF reset */
 	if (msgbuf[0] == IXGBE_VF_RESET) {
 		int ret = ixgbe_vf_reset(dev, vf, msgbuf);
 
 		vfinfo[vf].clear_to_send = true;
+
+		/* notify application about VF reset */
+		_rte_eth_dev_callback_process_vf(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
 		return ret;
 	}
 
+	/**
+	 * ask user application if we allowed to perform those functions
+	 * if we get cb_param.retval == RTE_ETH_MB_EVENT_PROCEED then business
+	 * as usual,
+	 * if 0, do nothing and send ACK to VF
+	 * if cb_param.retval > 1, do nothing and send NAK to VF
+	 */
+	_rte_eth_dev_callback_process_vf(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
+
+	retval = cb_param.retval;
+
 	/* check & process VF to PF mailbox message */
 	switch ((msgbuf[0] & 0xFFFF)) {
 	case IXGBE_VF_SET_MAC_ADDR:
-		retval = ixgbe_vf_set_mac_addr(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_vf_set_mac_addr(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_SET_MULTICAST:
-		retval = ixgbe_vf_set_multicast(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_vf_set_multicast(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_SET_LPE:
-		retval = ixgbe_set_vf_lpe(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_set_vf_lpe(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_SET_VLAN:
-		retval = ixgbe_vf_set_vlan(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_vf_set_vlan(dev, vf, msgbuf);
 		break;
 	case IXGBE_VF_API_NEGOTIATE:
 		retval = ixgbe_negotiate_vf_api(dev, vf, msgbuf);
@@ -704,7 +732,8 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 		msg_size = IXGBE_VF_GET_QUEUE_MSG_SIZE;
 		break;
 	case IXGBE_VF_UPDATE_XCAST_MODE:
-		retval = ixgbe_set_vf_mc_promisc(dev, vf, msgbuf);
+		if (retval == RTE_ETH_MB_EVENT_PROCEED)
+			retval = ixgbe_set_vf_mc_promisc(dev, vf, msgbuf);
 		break;
 	default:
 		PMD_DRV_LOG(DEBUG, "Unhandled Msg %8.8x", (unsigned)msgbuf[0]);
-- 
2.9.0

[RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-08-26 09:10:28

Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_strip function.
add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function
add rte_eth_dev_set_vf_mac_addr function.
increment LIBABIVER to 5.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 159 +++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 223 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |   9 ++
 3 files changed, 391 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1388ea3..2a3d2ae 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2306,6 +2306,22 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 }
 
 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct ether_addr *addr)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -ENOTSUP);
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr);
+}
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2490,6 +2506,149 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF VLAN anti spoof:VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF MAC anti spoof:VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_mac_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_vf_ping(uint8_t port_id, int32_t vf)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF ping: VF %d > 64\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_ping, -ENOTSUP);
+	return (*dev->dev_ops->vf_ping)(dev, vf);
+}
+
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint16_t queues_per_pool;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF vlan strip set VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_strip, -ENOTSUP);
+
+	rte_eth_dev_info_get(port_id, &dev_info);
+	queues_per_pool = dev_info.vmdq_queue_num/dev_info.max_vmdq_pools;
+
+	(*dev->dev_ops->set_vf_vlan_strip)(dev, on, queues_per_pool);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
+		RTE_PMD_DEBUG_TRACE("VF vlan insert set VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_insert, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_vlan_insert)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_tx_loopback(uint8_t port_id, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_tx_loopback, -ENOTSUP);
+
+	(*dev->dev_ops->set_tx_loopback)(dev, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port_id, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_all_queues_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_all_queues_drop_en)(dev, state);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port_id, uint16_t vf, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_split_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_split_drop_en)(dev, vf, state);
+	return 0;
+}
+
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 4fb0b9c..ed3d61b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1230,6 +1230,11 @@ typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr);
 /**< @internal Set a MAC address into Receive Address Address Register */
 
+typedef int (*eth_set_vf_mac_addr_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  struct ether_addr *mac_addr);
+/**< @internal Set VF address into Receive Address Address Register */
+
 typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr,
 				  uint8_t on);
@@ -1261,6 +1266,43 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
 				  uint8_t vlan_on);
 /**< @internal Set VF VLAN pool filter */
 
+typedef void (*eth_set_vf_vlan_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF VLAN anti spoof */
+
+typedef void (*eth_set_vf_mac_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF MAC anti spoof */
+
+typedef int (*eth_vf_ping_t)(struct rte_eth_dev *dev,
+				int32_t vf);
+/**< @internal ping one or all vf's */
+
+typedef void (*eth_set_vf_vlan_strip_t)(struct rte_eth_dev *dev,
+				  int on,
+				  uint16_t queues_per_pool);
+/**< @internal Set VF vlan strip */
+
+typedef void (*eth_set_vf_vlan_insert_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int vlan);
+/**< @internal Set VF vlan insert */
+
+typedef void (*eth_set_tx_loopback_t)(struct rte_eth_dev *dev,
+				  int on);
+/**< @internal Set tx loopback */
+
+typedef void (*eth_set_all_queues_drop_en_t)(struct rte_eth_dev *dev,
+				  int state);
+/**< @internal Set all queues drop */
+
+typedef void (*eth_set_vf_split_drop_en_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int state);
+/**< @internal Set the enable drop bit in the VF split rx control register */
+
 typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
 				uint16_t queue_idx,
 				uint16_t tx_rate);
@@ -1465,6 +1507,7 @@ struct eth_dev_ops {
 	eth_mac_addr_remove_t      mac_addr_remove; /**< Remove MAC address */
 	eth_mac_addr_add_t         mac_addr_add;  /**< Add a MAC address */
 	eth_mac_addr_set_t         mac_addr_set;  /**< Set a MAC address */
+	eth_set_vf_mac_addr_t      set_vf_mac_addr;  /**< Set a VF MAC address */
 	eth_uc_hash_table_set_t    uc_hash_table_set;  /**< Set Unicast Table Array */
 	eth_uc_all_hash_table_set_t uc_all_hash_table_set;  /**< Set Unicast hash bitmap */
 	eth_mirror_rule_set_t	   mirror_rule_set;  /**< Add a traffic mirror rule.*/
@@ -1473,6 +1516,14 @@ struct eth_dev_ops {
 	eth_set_vf_rx_t            set_vf_rx;  /**< enable/disable a VF receive */
 	eth_set_vf_tx_t            set_vf_tx;  /**< enable/disable a VF transmit */
 	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
+	eth_set_vf_vlan_anti_spoof_t  set_vf_vlan_anti_spoof; /**< Set VF VLAN anti spoof */
+	eth_set_vf_mac_anti_spoof_t   set_vf_mac_anti_spoof;  /**< Set VF MAC anti spoof */
+	eth_vf_ping_t             vf_ping;  /**< Ping one or all VF's */
+	eth_set_vf_vlan_strip_t   set_vf_vlan_strip; /** <Set VF VLAN strip */
+	eth_set_vf_vlan_insert_t  set_vf_vlan_insert; /** <Set VF VLAN insert */
+	eth_set_tx_loopback_t  set_tx_loopback; /** <Set tx loopback */
+	eth_set_all_queues_drop_en_t  set_all_queues_drop_en; /** <Set queue drop enable bit */
+	eth_set_vf_split_drop_en_t  set_vf_split_drop_en; /** <Set split drop enable bit.*/
 	/** Add UDP tunnel port. */
 	eth_udp_tunnel_port_add_t udp_tunnel_port_add;
 	/** Del UDP tunnel port. */
@@ -3389,7 +3440,25 @@ int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr);
  */
 int rte_eth_dev_default_mac_addr_set(uint8_t port, struct ether_addr *mac_addr);
 
+/**
+ * Set the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
 
+ * @return
+ *   - (0) if successful, or *mac_addr* didn't exist.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if MAC address is invalid.
+ */
+
+int rte_eth_dev_set_vf_mac_addr(uint8_t port, uint16_t vf,
+				struct ether_addr *mac_addr);
 /**
  * Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device.
  *
@@ -3556,6 +3625,160 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
 				uint8_t vlan_on);
 
 /**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Ping all or specified VF
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   specify VF to ping or all if -1.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_vf_ping(uint8_t port, int32_t vf);
+
+/**
+ * Enable/Disable vf vlan strip
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan strip.
+ *    0 - Disable VF's vlan strip
+ * @param queues_per_pool
+ *    The number of queues per pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable vf vlan insert
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan insert.
+ *    0 - Disable VF's vlan insert
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable tx loopback
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable tx loopback.
+ *    0 - Disable tx loopback.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_tx_loopback(uint8_t port, int on);
+/**
+ * set all queues drop enable bit
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param state
+ *    1 - set the queue drop enable bit for all pools.
+ *    0 - reset the queue drop enable bit for all pools.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port, int state);
+/**
+ * set drop enable bit in the VF split rx control register
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param state
+ *    1 - set the drop enable bit in the split rx control register.
+ *    0 - reset the drop enable bit in the split rx control register.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port, uint16_t vf, int state);
+/**
  * Set a traffic mirroring rule on an Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index cb7ef15..c9649ee 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -145,4 +145,13 @@ DPDK_16.11 {
 
 	_rte_eth_dev_callback_process_generic;
 	_rte_eth_dev_callback_process_vf;
+	rte_eth_dev_set_all_queues_drop_en;
+	rte_eth_dev_set_tx_loopback;
+	rte_eth_dev_set_vf_mac_addr;
+	rte_eth_dev_set_vf_mac_anti_spoof;
+	rte_eth_dev_set_vf_split_drop_en;
+	rte_eth_dev_set_vf_vlan_anti_spoof;
+	rte_eth_dev_set_vf_vlan_insert;
+	rte_eth_dev_set_vf_vlan_strip;
+	rte_eth_dev_vf_ping;
 } DPDK_16.07;
-- 
2.9.0

[RFC PATCH v2 4/5] net/ixgbe: add functions for VF management

From: Bernard Iremonger <hidden>
Date: 2016-08-26 09:10:31

Add new functions to configure and manage VF's on a Niantic NIC.

add ixgbe_vf_ping function.
add ixgbe_set_vf_vlan_anti_spoof function.
add ixgbe_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add ixgbe_set_vf_vlan_strip function
add ixgbe_set_vf_vlan_insert function.
add ixgbe_set_tx_loopback function.
add ixgbe_set_all_queues_drop function.
add ixgbe_set_vf_split_drop_en function.
add ixgbe_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 179 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 179 insertions(+)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index fb618ef..e8220ba 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -240,6 +240,8 @@ static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
 static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev,
 					   struct ether_addr *mac_addr);
+static int ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf,
+				struct ether_addr *mac_addr);
 static void ixgbe_dcb_init(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config);
 
 /* For Virtual Function support */
@@ -280,6 +282,19 @@ static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
 static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
 static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 		uint64_t pool_mask, uint8_t vlan_on);
+static void ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static void ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static int ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf);
+static void ixgbe_set_vf_vlan_strip(struct rte_eth_dev *dev,
+		int on, uint16_t queues_per_pool);
+static void ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf,
+		int vlan);
+static void ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on);
+static void ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state);
+static void ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf,
+		int state);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 		struct rte_eth_mirror_conf *mirror_conf,
 		uint8_t rule_id, uint8_t on);
@@ -562,6 +577,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.mac_addr_add         = ixgbe_add_rar,
 	.mac_addr_remove      = ixgbe_remove_rar,
 	.mac_addr_set         = ixgbe_set_default_mac_addr,
+	.set_vf_mac_addr      = ixgbe_set_vf_mac_addr,
 	.uc_hash_table_set    = ixgbe_uc_hash_table_set,
 	.uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
 	.mirror_rule_set      = ixgbe_mirror_rule_set,
@@ -570,6 +586,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.set_vf_rx            = ixgbe_set_pool_rx,
 	.set_vf_tx            = ixgbe_set_pool_tx,
 	.set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
+	.set_vf_vlan_anti_spoof  = ixgbe_set_vf_vlan_anti_spoof,
+	.set_vf_mac_anti_spoof   = ixgbe_set_vf_mac_anti_spoof,
+	.vf_ping              = ixgbe_vf_ping,
+	.set_vf_vlan_strip    = ixgbe_set_vf_vlan_strip,
+	.set_vf_vlan_insert   = ixgbe_set_vf_vlan_insert,
+	.set_tx_loopback      = ixgbe_set_tx_loopback,
+	.set_all_queues_drop_en = ixgbe_set_all_queues_drop_en,
+	.set_vf_split_drop_en = ixgbe_set_vf_split_drop_en,
 	.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
 	.set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
 	.reta_update          = ixgbe_dev_rss_reta_update,
@@ -4069,6 +4093,22 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
 }
 
 static int
+ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf, struct ether_addr *mac_addr)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_vf_info *vfinfo =
+		*(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+	uint8_t *new_mac = (uint8_t *)(mac_addr);
+
+	if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
+		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, ETHER_ADDR_LEN);
+		return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV);
+	}
+	return -1;
+}
+
+static int
 ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
 	uint32_t hlreg0;
@@ -4372,6 +4412,16 @@ ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on)
 }
 
 static void
+ixgbe_set_vf_vlan_strip(struct rte_eth_dev *dev, int on,
+		uint16_t queues_per_pool)
+{
+	uint16_t q;
+
+	for (q = 0; q < queues_per_pool; q++)
+		ixgbevf_vlan_strip_queue_set(dev, q, on);
+}
+
+static void
 ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct ixgbe_hw *hw =
@@ -4661,6 +4711,135 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 	return ret;
 }
 
+static void
+ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_vlan_anti_spoofing(hw, on, vf);
+}
+
+static void
+ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_mac_anti_spoofing(hw, on, vf);
+}
+
+static int
+ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_vf_info *vfinfo =
+		*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+
+	u32 ping;
+	int i;
+
+	for (i = 0; i < dev->pci_dev->max_vfs; i++) {
+		ping = IXGBE_PF_CONTROL_MSG;
+		if (vfinfo[i].clear_to_send)
+			ping |= IXGBE_VT_MSGTYPE_CTS;
+
+		/* ping every VF or only one specified */
+		if (vf < 0 || vf == i)
+			ixgbe_write_mbx(hw, &ping, 1, i);
+	}
+
+	return ret;
+}
+
+static void
+ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf, int vlan)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+	if (vlan) {
+		ctrl = vlan;
+		ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
+	} else {
+		ctrl = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
+}
+
+static void
+ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+	/* enable or disable VMDQ loopback */
+	if (on)
+		ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
+	else
+		ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
+}
+
+static void
+ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+	int i;
+	int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i <= num_queues; i++) {
+		reg_value = IXGBE_QDE_WRITE |
+				(i << IXGBE_QDE_IDX_SHIFT) |
+				(state & IXGBE_QDE_ENABLE);
+		IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
+	}
+}
+
+static void
+ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* only support VF's 0 to 63 */
+	if (vf > 63)
+		return;
+
+	reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
+	if (state)
+		reg_value |= IXGBE_SRRCTL_DROP_EN;
+	else
+		reg_value &= ~IXGBE_SRRCTL_DROP_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
-- 
2.9.0

[RFC PATCH v2 5/5] app/test_pmd: add tests for new API's

From: Bernard Iremonger <hidden>
Date: 2016-08-26 09:10:33

add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf ping
add test for vf vlan strip
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit
add test for vf split drop enable bit
add test for vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
---
 app/test-pmd/cmdline.c                      | 700 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  68 ++-
 2 files changed, 766 insertions(+), 2 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f90befc..fb29c0a 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -10585,6 +10585,697 @@ cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
 	},
 };
 
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+	ret = rte_eth_dev_set_vf_vlan_anti_spoof(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan anti spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+	.f = cmd_set_vf_vlan_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan anti spoof",
+	.tokens = {
+		(void *)&cmd_vf_vlan_anti_spoof_set,
+		(void *)&cmd_vf_vlan_anti_spoof_vf,
+		(void *)&cmd_vf_vlan_anti_spoof_vlan,
+		(void *)&cmd_vf_vlan_anti_spoof_antispoof,
+		(void *)&cmd_vf_vlan_anti_spoof_port_id,
+		(void *)&cmd_vf_vlan_anti_spoof_vf_id,
+		(void *)&cmd_vf_vlan_anti_spoof_on,
+		NULL,
+	},
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_anti_spoof(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan mac spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+	.f = cmd_set_vf_mac_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf mac anti spoof",
+	.tokens = {
+		(void *)&cmd_vf_mac_anti_spoof_set,
+		(void *)&cmd_vf_mac_anti_spoof_vf,
+		(void *)&cmd_vf_mac_anti_spoof_mac,
+		(void *)&cmd_vf_mac_anti_spoof_antispoof,
+		(void *)&cmd_vf_mac_anti_spoof_port_id,
+		(void *)&cmd_vf_mac_anti_spoof_vf_id,
+		(void *)&cmd_vf_mac_anti_spoof_on,
+		NULL,
+	},
+};
+
+/* vf ping configuration */
+
+/* Common result structure for vf ping */
+struct cmd_vf_ping_result {
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t ping;
+	uint8_t port_id;
+	int32_t vf_id;
+};
+
+/* Common CLI fields for ping vfs */
+cmdline_parse_token_string_t cmd_vf_ping_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_ping_ping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 ping, "ping");
+cmdline_parse_token_num_t cmd_vf_ping_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_ping_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf_id, INT32);
+
+static void
+cmd_vf_ping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_ping_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_vf_ping(res->port_id, res->vf_id);
+	if (ret < 0)
+		printf("ping vfs programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_vf_ping = {
+	.f = cmd_vf_ping_parsed,
+	.data = NULL,
+	.help_str = "ping all or specified vf",
+	.tokens = {
+		(void *)&cmd_vf_ping_vf,
+		(void *)&cmd_vf_ping_ping,
+		(void *)&cmd_vf_ping_port_id,
+		(void *)&cmd_vf_ping_vf_id,
+		NULL,
+	},
+};
+
+/* vf vlan strip configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_strip_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t strip;
+	uint8_t port_id;
+	uint16_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_strip_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_strip =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 strip, "strip");
+cmdline_parse_token_num_t cmd_vf_vlan_strip_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_strip_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_strip_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_vlan_strip_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_strip_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_strip(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan strip programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_strip = {
+	.f = cmd_set_vf_vlan_strip_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan strip",
+	.tokens = {
+		(void *)&cmd_vf_vlan_strip_set,
+		(void *)&cmd_vf_vlan_strip_vf,
+		(void *)&cmd_vf_vlan_strip_vlan,
+		(void *)&cmd_vf_vlan_strip_strip,
+		(void *)&cmd_vf_vlan_strip_port_id,
+		(void *)&cmd_vf_vlan_strip_vf_id,
+		(void *)&cmd_vf_vlan_strip_on,
+		NULL,
+	},
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t insert;
+	uint8_t port_id;
+	uint16_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_insert_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_insert(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf vlan insert programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+	.f = cmd_set_vf_vlan_insert_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan insert",
+	.tokens = {
+		(void *)&cmd_vf_vlan_insert_set,
+		(void *)&cmd_vf_vlan_insert_vf,
+		(void *)&cmd_vf_vlan_insert_vlan,
+		(void *)&cmd_vf_vlan_insert_insert,
+		(void *)&cmd_vf_vlan_insert_port_id,
+		(void *)&cmd_vf_vlan_insert_vf_id,
+		(void *)&cmd_vf_vlan_insert_on,
+		NULL,
+	},
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t tx;
+	cmdline_fixed_string_t loopback;
+	uint8_t port_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_tx_loopback_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 on, UINT8);
+
+static void
+cmd_set_tx_loopback_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_tx_loopback_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_tx_loopback(res->port_id, res->on);
+	if (ret < 0)
+		printf("tx loopback programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+	.f = cmd_set_tx_loopback_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf vlan insert",
+	.tokens = {
+		(void *)&cmd_tx_loopback_set,
+		(void *)&cmd_tx_loopback_tx,
+		(void *)&cmd_tx_loopback_loopback,
+		(void *)&cmd_tx_loopback_port_id,
+		(void *)&cmd_tx_loopback_on,
+		NULL,
+	},
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t queues;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_all_queues_drop_en_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 on, UINT8);
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_all_queues_drop_en_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_all_queues_drop_en(res->port_id, res->on);
+	if (ret < 0)
+		printf("all queues drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+	.f = cmd_set_all_queues_drop_en_parsed,
+	.data = NULL,
+	.help_str = "enable/disable all queues drop enable bits",
+	.tokens = {
+		(void *)&cmd_all_queues_drop_en_set,
+		(void *)&cmd_all_queues_drop_en_all,
+		(void *)&cmd_all_queues_drop_en_queues,
+		(void *)&cmd_all_queues_drop_en_drop,
+		(void *)&cmd_all_queues_drop_en_port_id,
+		(void *)&cmd_all_queues_drop_en_on,
+		NULL,
+	},
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t split;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint16_t vf_id;
+	uint8_t on;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_on =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 on, UINT8);
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_split_drop_en_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_split_drop_en(res->port_id, res->vf_id, res->on);
+	if (ret < 0)
+		printf("vf split drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+	.f = cmd_set_vf_split_drop_en_parsed,
+	.data = NULL,
+	.help_str = "enable/disable vf split drop enable",
+	.tokens = {
+		(void *)&cmd_vf_split_drop_en_set,
+		(void *)&cmd_vf_split_drop_en_vf,
+		(void *)&cmd_vf_split_drop_en_split,
+		(void *)&cmd_vf_split_drop_en_drop,
+		(void *)&cmd_vf_split_drop_en_port_id,
+		(void *)&cmd_vf_split_drop_en_vf_id,
+		(void *)&cmd_vf_split_drop_en_on,
+		NULL,
+	},
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t addr;
+	uint8_t port_id;
+	uint16_t vf_id;
+	struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+	TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+		 mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_vf_mac_addr_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_addr(res->port_id, res->vf_id, &res->mac_addr);
+	if (ret < 0)
+		printf("set vf mac addr programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+	.f = cmd_set_vf_mac_addr_parsed,
+	.data = NULL,
+	.help_str = "set vf mac address",
+	.tokens = {
+		(void *)&cmd_set_vf_mac_addr_set,
+		(void *)&cmd_set_vf_mac_addr_vf,
+		(void *)&cmd_set_vf_mac_addr_mac,
+		(void *)&cmd_set_vf_mac_addr_addr,
+		(void *)&cmd_set_vf_mac_addr_port_id,
+		(void *)&cmd_set_vf_mac_addr_vf_id,
+		(void *)&cmd_set_vf_mac_addr_mac_addr,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10739,6 +11430,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_vf_ping,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_strip,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f87e0c2..c26d901 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -473,6 +473,41 @@ For example, to change the port forwarding:
    RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03
    RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02
 
+set tx loopback
+~~~~~~~~~~~~~~~
+
+Enable/disable tx loopback::
+
+   testpmd> set tx loopback (port_id) (on|off)
+
+set drop enable
+~~~~~~~~~~~~~~~
+
+set drop enable bit for all queues::
+
+   testpmd> set all queues drop (port_id) (on|off)
+
+set split drop enable (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+set split drop enable bit for VF from PF::
+
+   testpmd> set vf split drop (port_id) (vf_id) (on|off)
+
+set mac antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set mac antispoof for a VF from the PF::
+
+   testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
+
+ping VF
+~~~~~~~
+
+Ping VF or all VF's from PF::
+
+   testpmd> vf ping (port_id) (vf_id | -1)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
@@ -487,6 +522,28 @@ Set the VLAN strip for a queue on a port::
 
    testpmd> vlan set stripq (on|off) (port_id,queue_id)
 
+vlan set strip (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN strip for a VF from the PF::
+
+   testpmd> set vf vlan strip (port_id) (vf_id) (on|off)
+
+vlan set insert (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN insert for a VF from the PF::
+
+   testpmd> set vf vlan insert  (port_id) (vf_id) (on|off)
+
+vlan set antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN antispoof for a VF from the PF::
+
+   testpmd> set vf vlan antispoof  (port_id) (vf_id) (on|off)
+
+
 vlan set filter
 ~~~~~~~~~~~~~~~
 
@@ -727,13 +784,20 @@ Remove a MAC address from a port::
 
    testpmd> mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)
 
-mac_addr add(for VF)
-~~~~~~~~~~~~~~~~~~~~
+mac_addr add (for VF)
+~~~~~~~~~~~~~~~~~~~~~
 
 Add an alternative MAC address for a VF to a port::
 
    testpmd> mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX)
 
+mac_addr set (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set the MAC address for a VF from the PF::
+
+   testpmd> set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)
+
 set port-uta
 ~~~~~~~~~~~~
 
-- 
2.9.0

Re: [RFC PATCH v2 0/5] add API's for VF management

From: Pattan, Reshma <hidden>
Date: 2016-09-07 09:18:50

Hi,

Ping for comments on this patch series.

Thanks,
Reshma
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard Iremonger
Sent: Friday, August 26, 2016 10:10 AM
To: Shah, Rahul R <redacted>; Lu, Wenzhuo
[off-list ref]; dev@dpdk.org
Cc: Iremonger, Bernard <redacted>
Subject: [dpdk-dev] [RFC PATCH v2 0/5] add API's for VF management

Re: [RFC PATCH v2 0/5] add API's for VF management

From: Pattan, Reshma <hidden>
Date: 2016-09-09 08:49:46

Hi Thomas and Ferruh,

Can you take a look and  provide comments on ixgbe driver and ethdev changes.

Thanks,
Reshma
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard Iremonger
Sent: Friday, August 26, 2016 10:10 AM
To: Shah, Rahul R <redacted>; Lu, Wenzhuo
[off-list ref]; dev@dpdk.org
Cc: Iremonger, Bernard <redacted>
Subject: [dpdk-dev] [RFC PATCH v2 0/5] add API's for VF management

This RFC patchset contains new DPDK API's requested by AT&T for use with the
Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the point where
AT&T have devloped a DPDK based tool, VFD, to do this.

This RFC proposes to add the following API extensions to DPDK:
  mailbox communication callback support
  VF configuration

Nine new functions have been added to the eth_dev_ops structure.
Corresponding functions have been added to the ixgbe PMD for the Niantic NIC.

Two new callback functions have been added.
Changes have been made to the ixgbe_rcv_msg_from_vf function to use the
callback functions.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd
changes.

Note:
Adding new functions to the eth_dev_ops structure will cause an ABI breakage.

Changes in V2:
rebase to latest master branch.
fix compile  error with clang.

Bernard Iremonger (5):
  librte_ether: add internal callback functions
  net/ixgbe: add callback to user app on VF to PF mbox msg
  librte_ether: add API's for VF management
  net/ixgbe: add functions for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 700 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  68 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c            | 179 +++++++
 drivers/net/ixgbe/ixgbe_pf.c                |  39 +-
 lib/librte_ether/rte_ethdev.c               | 176 +++++++
 lib/librte_ether/rte_ethdev.h               | 284 +++++++++++
 lib/librte_ether/rte_ether_version.map      |  16 +
 7 files changed, 1455 insertions(+), 7 deletions(-)

--
2.9.0

Re: [RFC PATCH v2 0/5] add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-09 13:02:49

2016-09-09 08:49, Pattan, Reshma:
Hi Thomas and Ferruh,

Can you take a look and  provide comments on ixgbe driver and ethdev changes.
We could try.
But honestly we have a lot of work to do for DPDK, except reviews.
So I would appreciate to see more reviewers on ethdev stuff.

Volunteers are more than welcome!

Re: [RFC PATCH v2 1/5] librte_ether: add internal callback functions

From: Jerin Jacob <hidden>
Date: 2016-09-09 14:11:00

On Fri, Aug 26, 2016 at 10:10:16AM +0100, Bernard Iremonger wrote:
quoted hunk
add _rte_eth_dev_callback_process_vf function.
add _rte_eth_dev_callback_process_generic function

Adding a callback to the user application on VF to PF mailbox message,
allows passing information to the application controlling the PF
when a VF mailbox event message is received, such as VF reset.

Signed-off-by: azelezniak <redacted>
Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 17 ++++++++++
 lib/librte_ether/rte_ethdev.h          | 61 ++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 ++++
 3 files changed, 85 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f62a9ec..1388ea3 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2690,6 +2690,20 @@ void
 _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 	enum rte_eth_event_type event)
 {
+	return _rte_eth_dev_callback_process_generic(dev, event, NULL);
+}
+
+void
+_rte_eth_dev_callback_process_vf(struct rte_eth_dev *dev,
+	enum rte_eth_event_type event, void *param)
+{
+	return _rte_eth_dev_callback_process_generic(dev, event, param);
+}
+
+void
+_rte_eth_dev_callback_process_generic(struct rte_eth_dev *dev,
+	enum rte_eth_event_type event, void *param)
+{
 	struct rte_eth_dev_callback *cb_lst;
 	struct rte_eth_dev_callback dev_cb;
 
@@ -2699,6 +2713,9 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
 			continue;
 		dev_cb = *cb_lst;
 		cb_lst->active = 1;
+		if (param != NULL)
+			dev_cb.cb_arg = (void *) param;
+
 		rte_spinlock_unlock(&rte_eth_dev_cb_lock);
 		dev_cb.cb_fn(dev->data->port_id, dev_cb.event,
 						dev_cb.cb_arg);
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index b0fe033..4fb0b9c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3047,9 +3047,27 @@ enum rte_eth_event_type {
 				/**< queue state event (enabled/disabled) */
 	RTE_ETH_EVENT_INTR_RESET,
 			/**< reset interrupt event, sent to VF on PF reset */
+	RTE_ETH_EVENT_VF_MBOX,  /**< PF mailbox processing callback */
 	RTE_ETH_EVENT_MAX       /**< max value of this enum */
 };
 
+/**
+ * Response sent back to ixgbe driver from user app after callback
+ */
+enum rte_eth_mb_event_rsp {
+	RTE_ETH_MB_EVENT_NOOP_ACK,  /**< skip mbox request and ACK */
+	RTE_ETH_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+	RTE_ETH_MB_EVENT_PROCEED,  /**< proceed with mbox request  */
+	RTE_ETH_MB_EVENT_MAX       /**< max value of this enum */
+};
Do we really need to define the specifics of PF to VF MBOX communication
in normative ethdev specification?
Each drivers may have different PF to VF MBOX definitions so it may not be
very portable.
What is the use-case here? If its for VF configuration, I think we can
do it as separate 'sync' functions for each functionality so that
PMDs will have room hiding the specifics on MBOX definitions.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Jerin Jacob <hidden>
Date: 2016-09-09 14:23:18

On Fri, Aug 26, 2016 at 10:10:18AM +0100, Bernard Iremonger wrote:
Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_strip function.
add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function
add rte_eth_dev_set_vf_mac_addr function.
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id, uint8_t on))
For instance, In Thunderx PMD, We are not exposing a separate port_id
for PF. We only enumerate 0..N VFs as 0..N ethdev port_id
quoted hunk
increment LIBABIVER to 5.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 159 +++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 223 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |   9 ++
 3 files changed, 391 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1388ea3..2a3d2ae 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2306,6 +2306,22 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 }
 
 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct ether_addr *addr)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -ENOTSUP);
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr);
+}
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2490,6 +2506,149 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
PMD may have more than 64 VFs.

+		RTE_PMD_DEBUG_TRACE("VF VLAN anti spoof:VF %d > 63\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+

Re: [RFC PATCH v2 5/5] app/test_pmd: add tests for new API's

From: Yuanhan Liu <hidden>
Date: 2016-09-11 12:35:25

On Fri, Aug 26, 2016 at 10:10:20AM +0100, Bernard Iremonger wrote:
add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf ping
add test for vf vlan strip
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit
add test for vf split drop enable bit
add test for vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
Hi,

FYI, my testrobot caught some errors when this patch is applied.
(BTW, gcc builds fine)

        --yliu

---

x86_64-native-linuxapp-clang
============================
/root/dpdk/app/test-pmd/cmdline.c:10629:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:10710:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:10856:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:10938:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11010:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11080:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11156:8: error: expression which evaluates to zero treated as a null pointer constant of type 'const char *' [-Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-clang/include/cmdline_parse_num.h:107:3: note: expanded from macro 'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
7 errors generated.
make[5]: *** [cmdline.o] Error 1
make[5]: *** Waiting for unfinished jobs....
make[4]: *** [test-pmd] Error 2
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [app] Error 2
make[2]: *** [all] Error 2
make[1]: *** [pre_install] Error 2
make: *** [install] Error 2
error: build failed

Re: [RFC PATCH v2 5/5] app/test_pmd: add tests for new API's

From: Iremonger, Bernard <hidden>
Date: 2016-09-12 15:57:22

Hi Yuanhan,

<snip>
Subject: Re: [dpdk-dev] [RFC PATCH v2 5/5] app/test_pmd: add tests for
new API's

On Fri, Aug 26, 2016 at 10:10:20AM +0100, Bernard Iremonger wrote:
quoted
add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf ping
add test for vf vlan strip
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit add test for vf split drop
enable bit add test for vf mac address add new API's to the testpmd
guide

Signed-off-by: Bernard Iremonger <redacted>
Hi,

FYI, my testrobot caught some errors when this patch is applied.
(BTW, gcc builds fine)

        --yliu

---

x86_64-native-linuxapp-clang
============================
/root/dpdk/app/test-pmd/cmdline.c:10629:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:10710:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:10856:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:10938:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11010:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11080:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11156:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
7 errors generated.
make[5]: *** [cmdline.o] Error 1
make[5]: *** Waiting for unfinished jobs....
make[4]: *** [test-pmd] Error 2
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [app] Error 2
make[2]: *** [all] Error 2
make[1]: *** [pre_install] Error 2
make: *** [install] Error 2
error: build failed
I am not seeing the above errors when I build with the following commands:

make config T=x86_64-native-linuxapp-clang
make install T=x86_64-native-linuxapp-clang -j

Are you using a different clang config file?

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-12 16:28:10

Hi Jerin,

<snip>
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

On Fri, Aug 26, 2016 at 10:10:18AM +0100, Bernard Iremonger wrote:
quoted
Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_strip function.
add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function add
rte_eth_dev_set_vf_mac_addr function.
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id, uint8_t on))
For instance, In Thunderx PMD, We are not exposing a separate port_id for
PF. We only enumerate 0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
quoted
increment LIBABIVER to 5.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 159 +++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 223
+++++++++++++++++++++++++++++++++
quoted
 lib/librte_ether/rte_ether_version.map |   9 ++
 3 files changed, 391 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c
b/lib/librte_ether/rte_ethdev.c index 1388ea3..2a3d2ae 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2306,6 +2306,22 @@ rte_eth_dev_default_mac_addr_set(uint8_t
port_id, struct ether_addr *addr)  }

 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct
+ether_addr *addr) {
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -
ENOTSUP);
quoted
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr); }
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2490,6 +2506,149 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t
port_id, uint16_t vlan_id,
quoted
 						   vf_mask, vlan_on);
 }

+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	if (vf > 63) {
PMD may have more than 64 VFs.
Yes, it would be better to check on max_vfs,  the same way as the already implemented functions mentioned above.
 
quoted
+		RTE_PMD_DEBUG_TRACE("VF VLAN anti spoof:VF %d >
63\n", vf);
quoted
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
Thanks for reviewing.
Regards,

Bernard.

Re: [RFC PATCH v2 5/5] app/test_pmd: add tests for new API's

From: Yuanhan Liu <hidden>
Date: 2016-09-13 04:34:28

On Mon, Sep 12, 2016 at 03:57:19PM +0000, Iremonger, Bernard wrote:
quoted
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11156:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const char *' [-
Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
7 errors generated.
make[5]: *** [cmdline.o] Error 1
make[5]: *** Waiting for unfinished jobs....
make[4]: *** [test-pmd] Error 2
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [app] Error 2
make[2]: *** [all] Error 2
make[1]: *** [pre_install] Error 2
make: *** [install] Error 2
error: build failed
I am not seeing the above errors when I build with the following commands:

make config T=x86_64-native-linuxapp-clang
make install T=x86_64-native-linuxapp-clang -j

Are you using a different clang config file?
Not really (well, I disabled KNI and UIO stuff). FYI, I'm using the
default clang compiler from ubuntu 16.04-x86_64.

	--yliu

Re: [RFC PATCH v2 5/5] app/test_pmd: add tests for new API's

From: Iremonger, Bernard <hidden>
Date: 2016-09-13 08:38:15

Hi Yuanhan,

<snip)
Subject: Re: [dpdk-dev] [RFC PATCH v2 5/5] app/test_pmd: add tests for
new API's

On Mon, Sep 12, 2016 at 03:57:19PM +0000, Iremonger, Bernard wrote:
quoted
quoted
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11156:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const
char *' [- Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
7 errors generated.
make[5]: *** [cmdline.o] Error 1
make[5]: *** Waiting for unfinished jobs....
make[4]: *** [test-pmd] Error 2
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [app] Error 2
make[2]: *** [all] Error 2
make[1]: *** [pre_install] Error 2
make: *** [install] Error 2
error: build failed
I am not seeing the above errors when I build with the following
commands:
quoted
make config T=x86_64-native-linuxapp-clang make install
T=x86_64-native-linuxapp-clang -j

Are you using a different clang config file?
Not really (well, I disabled KNI and UIO stuff). FYI, I'm using the default clang
compiler from ubuntu 16.04-x86_64.

	--yliu
The clang I am using is version 3.4-1, what is your clang version?

Regards,

Bernard.

Re: [RFC PATCH v2 5/5] app/test_pmd: add tests for new API's

From: Yuanhan Liu <hidden>
Date: 2016-09-13 08:42:21

On Tue, Sep 13, 2016 at 08:38:08AM +0000, Iremonger, Bernard wrote:
Hi Yuanhan,

<snip)
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 5/5] app/test_pmd: add tests for
new API's

On Mon, Sep 12, 2016 at 03:57:19PM +0000, Iremonger, Bernard wrote:
quoted
quoted
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
/root/dpdk/app/test-pmd/cmdline.c:11156:8: error: expression which
evaluates to zero treated as a null pointer constant of type 'const
char *' [- Werror,-Wnon-literal-null-conversion]
                 on, UINT8);
                     ^~~~~
/root/dpdk/x86_64-native-linuxapp-
clang/include/cmdline_parse_num.h:107:3: note: expanded from macro
'TOKEN_NUM_INITIALIZER'
                numtype,                        /* type */          \
                ^~~~~~~
7 errors generated.
make[5]: *** [cmdline.o] Error 1
make[5]: *** Waiting for unfinished jobs....
make[4]: *** [test-pmd] Error 2
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [app] Error 2
make[2]: *** [all] Error 2
make[1]: *** [pre_install] Error 2
make: *** [install] Error 2
error: build failed
I am not seeing the above errors when I build with the following
commands:
quoted
make config T=x86_64-native-linuxapp-clang make install
T=x86_64-native-linuxapp-clang -j

Are you using a different clang config file?
Not really (well, I disabled KNI and UIO stuff). FYI, I'm using the default clang
compiler from ubuntu 16.04-x86_64.

	--yliu
The clang I am using is version 3.4-1, what is your clang version?
The clang shipped with ubuntu 16.04 is v3.8:

# clang --version
clang version 3.8.0-2ubuntu1 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

	--yliu

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-13 09:24:31

2016-09-12 16:28, Iremonger, Bernard:
quoted
On Fri, Aug 26, 2016 at 10:10:18AM +0100, Bernard Iremonger wrote:
quoted
Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_strip function.
add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function add
rte_eth_dev_set_vf_mac_addr function.
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id, uint8_t on))
For instance, In Thunderx PMD, We are not exposing a separate port_id for
PF. We only enumerate 0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-15 16:47:04

Hi Thomas,

<snip>
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-12 16:28, Iremonger, Bernard:
quoted
quoted
On Fri, Aug 26, 2016 at 10:10:18AM +0100, Bernard Iremonger wrote:
quoted
Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_strip function.
add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function add
rte_eth_dev_set_vf_mac_addr function.
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id,
uint8_t on)) For instance, In Thunderx PMD, We are not exposing a
separate port_id for PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t
rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t
tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to the PF.
I don't think there is another way to do this.

Regards,

Bernard.

[PATCH v3 2/3] net/ixgbe: add functions for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-16 11:05:44

Add new functions to configure and manage VF's on an Intel 82559 NIC.

add ixgbe_vf_ping function.
add ixgbe_set_vf_vlan_anti_spoof function.
add ixgbe_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add ixgbe_set_vf_vlan_insert function.
add ixgbe_set_tx_loopback function.
add ixgbe_set_all_queues_drop function.
add ixgbe_set_vf_split_drop_en function.
add ixgbe_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 166 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index fb618ef..9875290 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -240,6 +240,8 @@ static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
 static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev,
 					   struct ether_addr *mac_addr);
+static int ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf,
+				struct ether_addr *mac_addr);
 static void ixgbe_dcb_init(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config);
 
 /* For Virtual Function support */
@@ -280,6 +282,17 @@ static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
 static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
 static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 		uint64_t pool_mask, uint8_t vlan_on);
+static void ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static void ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static int ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf);
+static void ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf,
+		int vlan);
+static void ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on);
+static void ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state);
+static void ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf,
+		int state);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 		struct rte_eth_mirror_conf *mirror_conf,
 		uint8_t rule_id, uint8_t on);
@@ -562,6 +575,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.mac_addr_add         = ixgbe_add_rar,
 	.mac_addr_remove      = ixgbe_remove_rar,
 	.mac_addr_set         = ixgbe_set_default_mac_addr,
+	.set_vf_mac_addr      = ixgbe_set_vf_mac_addr,
 	.uc_hash_table_set    = ixgbe_uc_hash_table_set,
 	.uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
 	.mirror_rule_set      = ixgbe_mirror_rule_set,
@@ -570,6 +584,13 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.set_vf_rx            = ixgbe_set_pool_rx,
 	.set_vf_tx            = ixgbe_set_pool_tx,
 	.set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
+	.set_vf_vlan_anti_spoof  = ixgbe_set_vf_vlan_anti_spoof,
+	.set_vf_mac_anti_spoof   = ixgbe_set_vf_mac_anti_spoof,
+	.vf_ping              = ixgbe_vf_ping,
+	.set_vf_vlan_insert   = ixgbe_set_vf_vlan_insert,
+	.set_tx_loopback      = ixgbe_set_tx_loopback,
+	.set_all_queues_drop_en = ixgbe_set_all_queues_drop_en,
+	.set_vf_split_drop_en = ixgbe_set_vf_split_drop_en,
 	.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
 	.set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
 	.reta_update          = ixgbe_dev_rss_reta_update,
@@ -4069,6 +4090,22 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
 }
 
 static int
+ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf, struct ether_addr *mac_addr)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_vf_info *vfinfo =
+		*(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+	uint8_t *new_mac = (uint8_t *)(mac_addr);
+
+	if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
+		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, ETHER_ADDR_LEN);
+		return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV);
+	}
+	return -1;
+}
+
+static int
 ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
 	uint32_t hlreg0;
@@ -4661,6 +4698,135 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 	return ret;
 }
 
+static void
+ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_vlan_anti_spoofing(hw, on, vf);
+}
+
+static void
+ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_mac_anti_spoofing(hw, on, vf);
+}
+
+static int
+ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_vf_info *vfinfo =
+		*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+
+	u32 ping;
+	int i;
+
+	for (i = 0; i < dev->pci_dev->max_vfs; i++) {
+		ping = IXGBE_PF_CONTROL_MSG;
+		if (vfinfo[i].clear_to_send)
+			ping |= IXGBE_VT_MSGTYPE_CTS;
+
+		/* ping every VF or only one specified */
+		if (vf < 0 || vf == i)
+			ixgbe_write_mbx(hw, &ping, 1, i);
+	}
+
+	return ret;
+}
+
+static void
+ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf, int vlan)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+	if (vlan) {
+		ctrl = vlan;
+		ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
+	} else {
+		ctrl = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
+}
+
+static void
+ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+	/* enable or disable VMDQ loopback */
+	if (on)
+		ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
+	else
+		ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
+}
+
+static void
+ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+	int i;
+	int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i <= num_queues; i++) {
+		reg_value = IXGBE_QDE_WRITE |
+				(i << IXGBE_QDE_IDX_SHIFT) |
+				(state & IXGBE_QDE_ENABLE);
+		IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
+	}
+}
+
+static void
+ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* only support VF's 0 to 63 */
+	if (vf > 63)
+		return;
+
+	reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
+	if (state)
+		reg_value |= IXGBE_SRRCTL_DROP_EN;
+	else
+		reg_value &= ~IXGBE_SRRCTL_DROP_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
-- 
2.9.0

[PATCH v3 1/3] librte_ether: add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-16 11:05:47

Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.
add rte_eth_dev_set_vf_vlan_strip function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function
add rte_eth_dev_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 192 +++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 217 ++++++++++++++++++++++++++++++++-
 lib/librte_ether/rte_ether_version.map |  14 +++
 3 files changed, 422 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 382c959..4f83c29 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2305,6 +2305,30 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 }
 
 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct ether_addr *addr)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF mac addr: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -ENOTSUP);
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr);
+}
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2489,6 +2513,174 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF VLAN anti spoof: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF MAC anti spoof:invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_mac_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_vf_ping(uint8_t port_id, int32_t vf)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("VF ping: invalid VF %d\n", vf);
+		return -EINVAL;
+	} else if (vf < -1) {
+			RTE_PMD_DEBUG_TRACE("VF ping: invalid value %d\n", vf);
+			return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_ping, -ENOTSUP);
+	return (*dev->dev_ops->vf_ping)(dev, vf);
+}
+
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint16_t queues_per_pool;
+	uint32_t q;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan strip: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_strip_queue_set, -ENOTSUP);
+
+	queues_per_pool = dev_info.vmdq_queue_num/dev_info.max_vmdq_pools;
+
+	for (q = 0; q < queues_per_pool; q++)
+		(*dev->dev_ops->vlan_strip_queue_set)(dev, q + vf * queues_per_pool, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan insert: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_insert, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_vlan_insert)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_tx_loopback(uint8_t port_id, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_tx_loopback, -ENOTSUP);
+
+	(*dev->dev_ops->set_tx_loopback)(dev, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port_id, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_all_queues_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_all_queues_drop_en)(dev, state);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port_id, uint16_t vf, int state)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF split drop enable: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_split_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_split_drop_en)(dev, vf, state);
+	return 0;
+}
+
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 96575e8..68b477f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1233,6 +1233,11 @@ typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr);
 /**< @internal Set a MAC address into Receive Address Address Register */
 
+typedef int (*eth_set_vf_mac_addr_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  struct ether_addr *mac_addr);
+/**< @internal Set VF address into Receive Address Address Register */
+
 typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr,
 				  uint8_t on);
@@ -1264,6 +1269,38 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
 				  uint8_t vlan_on);
 /**< @internal Set VF VLAN pool filter */
 
+typedef void (*eth_set_vf_vlan_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF VLAN anti spoof */
+
+typedef void (*eth_set_vf_mac_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF MAC anti spoof */
+
+typedef int (*eth_vf_ping_t)(struct rte_eth_dev *dev,
+				int32_t vf);
+/**< @internal ping one or all vf's */
+
+typedef void (*eth_set_vf_vlan_insert_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int vlan);
+/**< @internal Set VF vlan insert */
+
+typedef void (*eth_set_tx_loopback_t)(struct rte_eth_dev *dev,
+				  int on);
+/**< @internal Set tx loopback */
+
+typedef void (*eth_set_all_queues_drop_en_t)(struct rte_eth_dev *dev,
+				  int state);
+/**< @internal Set all queues drop */
+
+typedef void (*eth_set_vf_split_drop_en_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int state);
+/**< @internal Set the enable drop bit in the VF split rx control register */
+
 typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
 				uint16_t queue_idx,
 				uint16_t tx_rate);
@@ -1468,6 +1505,7 @@ struct eth_dev_ops {
 	eth_mac_addr_remove_t      mac_addr_remove; /**< Remove MAC address */
 	eth_mac_addr_add_t         mac_addr_add;  /**< Add a MAC address */
 	eth_mac_addr_set_t         mac_addr_set;  /**< Set a MAC address */
+	eth_set_vf_mac_addr_t      set_vf_mac_addr;  /**< Set a VF MAC address */
 	eth_uc_hash_table_set_t    uc_hash_table_set;  /**< Set Unicast Table Array */
 	eth_uc_all_hash_table_set_t uc_all_hash_table_set;  /**< Set Unicast hash bitmap */
 	eth_mirror_rule_set_t	   mirror_rule_set;  /**< Add a traffic mirror rule.*/
@@ -1476,6 +1514,13 @@ struct eth_dev_ops {
 	eth_set_vf_rx_t            set_vf_rx;  /**< enable/disable a VF receive */
 	eth_set_vf_tx_t            set_vf_tx;  /**< enable/disable a VF transmit */
 	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
+	eth_set_vf_vlan_anti_spoof_t  set_vf_vlan_anti_spoof; /**< Set VF VLAN anti spoof */
+	eth_set_vf_mac_anti_spoof_t   set_vf_mac_anti_spoof;  /**< Set VF MAC anti spoof */
+	eth_vf_ping_t             vf_ping;  /**< Ping one or all VF's */
+	eth_set_vf_vlan_insert_t  set_vf_vlan_insert; /** <Set VF VLAN insert */
+	eth_set_tx_loopback_t  set_tx_loopback; /** <Set tx loopback */
+	eth_set_all_queues_drop_en_t  set_all_queues_drop_en; /** <Set queue drop enable bit */
+	eth_set_vf_split_drop_en_t  set_vf_split_drop_en; /** <Set split drop enable bit.*/
 	/** Add UDP tunnel port. */
 	eth_udp_tunnel_port_add_t udp_tunnel_port_add;
 	/** Del UDP tunnel port. */
@@ -3332,7 +3377,23 @@ int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr);
  */
 int rte_eth_dev_default_mac_addr_set(uint8_t port, struct ether_addr *mac_addr);
 
-
+/**
+ * Set the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful, or *mac_addr* didn't exist.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if MAC address is invalid.
+ */
+int rte_eth_dev_set_vf_mac_addr(uint8_t port, uint16_t vf,
+				struct ether_addr *mac_addr);
 /**
  * Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device.
  *
@@ -3499,6 +3560,160 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
 				uint8_t vlan_on);
 
 /**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Ping all or specified VF
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   specify VF to ping or all if -1.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_vf_ping(uint8_t port, int32_t vf);
+
+/**
+ * Enable/Disable vf vlan strip
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan strip.
+ *    0 - Disable VF's vlan strip
+ * @param queues_per_pool
+ *    The number of queues per pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable vf vlan insert
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan insert.
+ *    0 - Disable VF's vlan insert
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable tx loopback
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable tx loopback.
+ *    0 - Disable tx loopback.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_tx_loopback(uint8_t port, int on);
+/**
+ * set all queues drop enable bit
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param state
+ *    1 - set the queue drop enable bit for all pools.
+ *    0 - reset the queue drop enable bit for all pools.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port, int state);
+/**
+ * set drop enable bit in the VF split rx control register
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param state
+ *    1 - set the drop enable bit in the split rx control register.
+ *    0 - reset the drop enable bit in the split rx control register.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port, uint16_t vf, int state);
+/**
  * Set a traffic mirroring rule on an Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 45ddf44..3fe149f 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,17 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	rte_eth_dev_set_all_queues_drop_en;
+	rte_eth_dev_set_tx_loopback;
+	rte_eth_dev_set_vf_mac_addr;
+	rte_eth_dev_set_vf_mac_anti_spoof;
+	rte_eth_dev_set_vf_split_drop_en;
+	rte_eth_dev_set_vf_vlan_anti_spoof;
+	rte_eth_dev_set_vf_vlan_insert;
+	rte_eth_dev_set_vf_vlan_strip;
+	rte_eth_dev_vf_ping;
+} DPDK_16.07;
-- 
2.9.0

[PATCH v3 3/3] app/test_pmd: add tests for new API's

From: Bernard Iremonger <hidden>
Date: 2016-09-16 11:05:47

add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf ping
add test for vf vlan strip
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit
add test for vf split drop enable bit
add test for vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
---
 app/test-pmd/cmdline.c                      | 707 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  70 ++-
 2 files changed, 774 insertions(+), 3 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f90befc..264aa90 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -10585,6 +10585,704 @@ cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
 	},
 };
 
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+	ret = rte_eth_dev_set_vf_vlan_anti_spoof(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan anti spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+	.f = cmd_set_vf_vlan_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_anti_spoof_set,
+		(void *)&cmd_vf_vlan_anti_spoof_vf,
+		(void *)&cmd_vf_vlan_anti_spoof_vlan,
+		(void *)&cmd_vf_vlan_anti_spoof_antispoof,
+		(void *)&cmd_vf_vlan_anti_spoof_port_id,
+		(void *)&cmd_vf_vlan_anti_spoof_vf_id,
+		(void *)&cmd_vf_vlan_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_anti_spoof(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan mac spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+	.f = cmd_set_vf_mac_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf mac antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_mac_anti_spoof_set,
+		(void *)&cmd_vf_mac_anti_spoof_vf,
+		(void *)&cmd_vf_mac_anti_spoof_mac,
+		(void *)&cmd_vf_mac_anti_spoof_antispoof,
+		(void *)&cmd_vf_mac_anti_spoof_port_id,
+		(void *)&cmd_vf_mac_anti_spoof_vf_id,
+		(void *)&cmd_vf_mac_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf ping configuration */
+
+/* Common result structure for vf ping */
+struct cmd_vf_ping_result {
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t ping;
+	uint8_t port_id;
+	int32_t vf_id;
+};
+
+/* Common CLI fields for ping vfs */
+cmdline_parse_token_string_t cmd_vf_ping_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_ping_ping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 ping, "ping");
+cmdline_parse_token_num_t cmd_vf_ping_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_ping_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf_id, INT32);
+
+static void
+cmd_vf_ping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_ping_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_vf_ping(res->port_id, res->vf_id);
+	if (ret < 0)
+		printf("ping vfs programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_vf_ping = {
+	.f = cmd_vf_ping_parsed,
+	.data = NULL,
+	.help_str = "vf ping port_id vf_id|-1",
+	.tokens = {
+		(void *)&cmd_vf_ping_vf,
+		(void *)&cmd_vf_ping_ping,
+		(void *)&cmd_vf_ping_port_id,
+		(void *)&cmd_vf_ping_vf_id,
+		NULL,
+	},
+};
+
+/* vf vlan strip configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_strip_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t strip;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_strip_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_strip =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 strip, "strip");
+cmdline_parse_token_num_t cmd_vf_vlan_strip_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_strip_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_strip_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_strip_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_strip_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_strip(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan strip programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_strip = {
+	.f = cmd_set_vf_vlan_strip_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan strip port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_strip_set,
+		(void *)&cmd_vf_vlan_strip_vf,
+		(void *)&cmd_vf_vlan_strip_vlan,
+		(void *)&cmd_vf_vlan_strip_strip,
+		(void *)&cmd_vf_vlan_strip_port_id,
+		(void *)&cmd_vf_vlan_strip_vf_id,
+		(void *)&cmd_vf_vlan_strip_on_off,
+		NULL,
+	},
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t insert;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_insert_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_insert_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_insert(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan insert programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+	.f = cmd_set_vf_vlan_insert_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan insert port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_insert_set,
+		(void *)&cmd_vf_vlan_insert_vf,
+		(void *)&cmd_vf_vlan_insert_vlan,
+		(void *)&cmd_vf_vlan_insert_insert,
+		(void *)&cmd_vf_vlan_insert_port_id,
+		(void *)&cmd_vf_vlan_insert_vf_id,
+		(void *)&cmd_vf_vlan_insert_on_off,
+		NULL,
+	},
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t tx;
+	cmdline_fixed_string_t loopback;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_tx_loopback_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_tx_loopback_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_tx_loopback_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_tx_loopback(res->port_id, is_on);
+	if (ret < 0)
+		printf("tx loopback programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+	.f = cmd_set_tx_loopback_parsed,
+	.data = NULL,
+	.help_str = "set tx loopback port_id on|off",
+	.tokens = {
+		(void *)&cmd_tx_loopback_set,
+		(void *)&cmd_tx_loopback_tx,
+		(void *)&cmd_tx_loopback_loopback,
+		(void *)&cmd_tx_loopback_port_id,
+		(void *)&cmd_tx_loopback_on_off,
+		NULL,
+	},
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t queues;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_all_queues_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_all_queues_drop_en(res->port_id, is_on);
+	if (ret < 0)
+		printf("all queues drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+	.f = cmd_set_all_queues_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set all queues drop port_id on|off",
+	.tokens = {
+		(void *)&cmd_all_queues_drop_en_set,
+		(void *)&cmd_all_queues_drop_en_all,
+		(void *)&cmd_all_queues_drop_en_queues,
+		(void *)&cmd_all_queues_drop_en_drop,
+		(void *)&cmd_all_queues_drop_en_port_id,
+		(void *)&cmd_all_queues_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t split;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_split_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_split_drop_en(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf split drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+	.f = cmd_set_vf_split_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set vf split drop port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_split_drop_en_set,
+		(void *)&cmd_vf_split_drop_en_vf,
+		(void *)&cmd_vf_split_drop_en_split,
+		(void *)&cmd_vf_split_drop_en_drop,
+		(void *)&cmd_vf_split_drop_en_port_id,
+		(void *)&cmd_vf_split_drop_en_vf_id,
+		(void *)&cmd_vf_split_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t addr;
+	uint8_t port_id;
+	uint16_t vf_id;
+	struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+	TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+		 mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_vf_mac_addr_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_addr(res->port_id, res->vf_id, &res->mac_addr);
+	if (ret < 0)
+		printf("set vf mac addr programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+	.f = cmd_set_vf_mac_addr_parsed,
+	.data = NULL,
+	.help_str = "set vf mac addr port_id vf_id xx:xx:xx:xx:xx:xx",
+	.tokens = {
+		(void *)&cmd_set_vf_mac_addr_set,
+		(void *)&cmd_set_vf_mac_addr_vf,
+		(void *)&cmd_set_vf_mac_addr_mac,
+		(void *)&cmd_set_vf_mac_addr_addr,
+		(void *)&cmd_set_vf_mac_addr_port_id,
+		(void *)&cmd_set_vf_mac_addr_vf_id,
+		(void *)&cmd_set_vf_mac_addr_mac_addr,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10739,6 +11437,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_vf_ping,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_strip,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f87e0c2..c84d5e2 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -473,6 +473,41 @@ For example, to change the port forwarding:
    RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03
    RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02
 
+set tx loopback
+~~~~~~~~~~~~~~~
+
+Enable/disable tx loopback::
+
+   testpmd> set tx loopback (port_id) (on|off)
+
+set drop enable
+~~~~~~~~~~~~~~~
+
+set drop enable bit for all queues::
+
+   testpmd> set all queues drop (port_id) (on|off)
+
+set split drop enable (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+set split drop enable bit for VF from PF::
+
+   testpmd> set vf split drop (port_id) (vf_id) (on|off)
+
+set mac antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set mac antispoof for a VF from the PF::
+
+   testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
+
+ping VF
+~~~~~~~
+
+Ping VF or all VF's from PF::
+
+   testpmd> vf ping (port_id) (vf_id | -1)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
@@ -487,6 +522,28 @@ Set the VLAN strip for a queue on a port::
 
    testpmd> vlan set stripq (on|off) (port_id,queue_id)
 
+vlan set strip (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN strip for a VF from the PF::
+
+   testpmd> set vf vlan strip (port_id) (vf_id) (on|off)
+
+vlan set insert (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN insert for a VF from the PF::
+
+   testpmd> set vf vlan insert  (port_id) (vf_id) (on|off)
+
+vlan set antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN antispoof for a VF from the PF::
+
+   testpmd> set vf vlan antispoof  (port_id) (vf_id) (on|off)
+
+
 vlan set filter
 ~~~~~~~~~~~~~~~
 
@@ -727,13 +784,20 @@ Remove a MAC address from a port::
 
    testpmd> mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)
 
-mac_addr add(for VF)
-~~~~~~~~~~~~~~~~~~~~
+mac_addr add (for VF)
+~~~~~~~~~~~~~~~~~~~~~
 
 Add an alternative MAC address for a VF to a port::
 
    testpmd> mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX)
 
+mac_addr set (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set the MAC address for a VF from the PF::
+
+   testpmd> set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)
+
 set port-uta
 ~~~~~~~~~~~~
 
-- 
2.9.0

[PATCH v3 0/3] add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-16 11:06:37

This patchset contains new DPDK API's requested by AT&T for use
with the Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the
point where AT&T have devloped a DPDK based tool, VFD, to do this.

This patch set adds API extensions to DPDK VF configuration.

Nine new functions have been added to the eth_dev_ops structure.
Corresponding functions have been added to the ixgbe PMD for the
Intel 82559 NIC.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd changes.

Note:
Adding new functions to the eth_dev_ops structure will cause an
ABI breakage.

Changes in v3:
rebase to latest master branch.
drop patches for callback functions
revise VF id checks in new librte_ether functions
revise testpmd commands for new API's

Changes in V2:
rebase to latest master branch.
fix compile  error with clang.

Bernard Iremonger (3):
  librte_ether: add API's for VF management
  net/ixgbe: add functions for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 707 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  70 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c            | 166 +++++++
 lib/librte_ether/rte_ethdev.c               | 192 ++++++++
 lib/librte_ether/rte_ethdev.h               | 217 ++++++++-
 lib/librte_ether/rte_ether_version.map      |  14 +
 6 files changed, 1362 insertions(+), 4 deletions(-)

-- 
2.9.0

[PATCH v3 0/3] add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-16 14:16:00

This patchset contains new DPDK API's requested by AT&T for use
with the Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the
point where AT&T have devloped a DPDK based tool, VFD, to do this.

This patch set adds API extensions to DPDK VF configuration.

Nine new functions have been added to the eth_dev_ops structure.
Corresponding functions have been added to the ixgbe PMD for the
Intel 82559 NIC.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd changes.

Note:
Adding new functions to the eth_dev_ops structure will cause an
ABI breakage.

Changes in v3:
rebase to latest master branch.
drop patches for callback functions
revise VF id checks in new librte_ether functions
revise testpmd commands for new API's

Changes in V2:
rebase to latest master branch.
fix compile  error with clang.

Bernard Iremonger (3):
  librte_ether: add API's for VF management
  net/ixgbe: add functions for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 707 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  70 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c            | 166 +++++++
 lib/librte_ether/rte_ethdev.c               | 192 ++++++++
 lib/librte_ether/rte_ethdev.h               | 217 ++++++++-
 lib/librte_ether/rte_ether_version.map      |  14 +
 6 files changed, 1362 insertions(+), 4 deletions(-)

-- 
2.9.0

[PATCH v3 1/3] librte_ether: add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-16 14:16:01

Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_vf_ping function.
add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.
add rte_eth_dev_set_vf_vlan_strip function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function
add rte_eth_dev_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 192 +++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 217 ++++++++++++++++++++++++++++++++-
 lib/librte_ether/rte_ether_version.map |  14 +++
 3 files changed, 422 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 382c959..4f83c29 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2305,6 +2305,30 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 }
 
 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct ether_addr *addr)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF mac addr: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -ENOTSUP);
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr);
+}
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2489,6 +2513,174 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF VLAN anti spoof: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF MAC anti spoof:invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_mac_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_vf_ping(uint8_t port_id, int32_t vf)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("VF ping: invalid VF %d\n", vf);
+		return -EINVAL;
+	} else if (vf < -1) {
+			RTE_PMD_DEBUG_TRACE("VF ping: invalid value %d\n", vf);
+			return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_ping, -ENOTSUP);
+	return (*dev->dev_ops->vf_ping)(dev, vf);
+}
+
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint16_t queues_per_pool;
+	uint32_t q;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan strip: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_strip_queue_set, -ENOTSUP);
+
+	queues_per_pool = dev_info.vmdq_queue_num/dev_info.max_vmdq_pools;
+
+	for (q = 0; q < queues_per_pool; q++)
+		(*dev->dev_ops->vlan_strip_queue_set)(dev, q + vf * queues_per_pool, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan insert: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_insert, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_vlan_insert)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_tx_loopback(uint8_t port_id, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_tx_loopback, -ENOTSUP);
+
+	(*dev->dev_ops->set_tx_loopback)(dev, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port_id, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_all_queues_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_all_queues_drop_en)(dev, state);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port_id, uint16_t vf, int state)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF split drop enable: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_split_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_split_drop_en)(dev, vf, state);
+	return 0;
+}
+
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 96575e8..68b477f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1233,6 +1233,11 @@ typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr);
 /**< @internal Set a MAC address into Receive Address Address Register */
 
+typedef int (*eth_set_vf_mac_addr_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  struct ether_addr *mac_addr);
+/**< @internal Set VF address into Receive Address Address Register */
+
 typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr,
 				  uint8_t on);
@@ -1264,6 +1269,38 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
 				  uint8_t vlan_on);
 /**< @internal Set VF VLAN pool filter */
 
+typedef void (*eth_set_vf_vlan_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF VLAN anti spoof */
+
+typedef void (*eth_set_vf_mac_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF MAC anti spoof */
+
+typedef int (*eth_vf_ping_t)(struct rte_eth_dev *dev,
+				int32_t vf);
+/**< @internal ping one or all vf's */
+
+typedef void (*eth_set_vf_vlan_insert_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int vlan);
+/**< @internal Set VF vlan insert */
+
+typedef void (*eth_set_tx_loopback_t)(struct rte_eth_dev *dev,
+				  int on);
+/**< @internal Set tx loopback */
+
+typedef void (*eth_set_all_queues_drop_en_t)(struct rte_eth_dev *dev,
+				  int state);
+/**< @internal Set all queues drop */
+
+typedef void (*eth_set_vf_split_drop_en_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int state);
+/**< @internal Set the enable drop bit in the VF split rx control register */
+
 typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
 				uint16_t queue_idx,
 				uint16_t tx_rate);
@@ -1468,6 +1505,7 @@ struct eth_dev_ops {
 	eth_mac_addr_remove_t      mac_addr_remove; /**< Remove MAC address */
 	eth_mac_addr_add_t         mac_addr_add;  /**< Add a MAC address */
 	eth_mac_addr_set_t         mac_addr_set;  /**< Set a MAC address */
+	eth_set_vf_mac_addr_t      set_vf_mac_addr;  /**< Set a VF MAC address */
 	eth_uc_hash_table_set_t    uc_hash_table_set;  /**< Set Unicast Table Array */
 	eth_uc_all_hash_table_set_t uc_all_hash_table_set;  /**< Set Unicast hash bitmap */
 	eth_mirror_rule_set_t	   mirror_rule_set;  /**< Add a traffic mirror rule.*/
@@ -1476,6 +1514,13 @@ struct eth_dev_ops {
 	eth_set_vf_rx_t            set_vf_rx;  /**< enable/disable a VF receive */
 	eth_set_vf_tx_t            set_vf_tx;  /**< enable/disable a VF transmit */
 	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
+	eth_set_vf_vlan_anti_spoof_t  set_vf_vlan_anti_spoof; /**< Set VF VLAN anti spoof */
+	eth_set_vf_mac_anti_spoof_t   set_vf_mac_anti_spoof;  /**< Set VF MAC anti spoof */
+	eth_vf_ping_t             vf_ping;  /**< Ping one or all VF's */
+	eth_set_vf_vlan_insert_t  set_vf_vlan_insert; /** <Set VF VLAN insert */
+	eth_set_tx_loopback_t  set_tx_loopback; /** <Set tx loopback */
+	eth_set_all_queues_drop_en_t  set_all_queues_drop_en; /** <Set queue drop enable bit */
+	eth_set_vf_split_drop_en_t  set_vf_split_drop_en; /** <Set split drop enable bit.*/
 	/** Add UDP tunnel port. */
 	eth_udp_tunnel_port_add_t udp_tunnel_port_add;
 	/** Del UDP tunnel port. */
@@ -3332,7 +3377,23 @@ int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr);
  */
 int rte_eth_dev_default_mac_addr_set(uint8_t port, struct ether_addr *mac_addr);
 
-
+/**
+ * Set the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful, or *mac_addr* didn't exist.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if MAC address is invalid.
+ */
+int rte_eth_dev_set_vf_mac_addr(uint8_t port, uint16_t vf,
+				struct ether_addr *mac_addr);
 /**
  * Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device.
  *
@@ -3499,6 +3560,160 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
 				uint8_t vlan_on);
 
 /**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Ping all or specified VF
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   specify VF to ping or all if -1.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_vf_ping(uint8_t port, int32_t vf);
+
+/**
+ * Enable/Disable vf vlan strip
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan strip.
+ *    0 - Disable VF's vlan strip
+ * @param queues_per_pool
+ *    The number of queues per pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_strip(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable vf vlan insert
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan insert.
+ *    0 - Disable VF's vlan insert
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable tx loopback
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable tx loopback.
+ *    0 - Disable tx loopback.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_tx_loopback(uint8_t port, int on);
+/**
+ * set all queues drop enable bit
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param state
+ *    1 - set the queue drop enable bit for all pools.
+ *    0 - reset the queue drop enable bit for all pools.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port, int state);
+/**
+ * set drop enable bit in the VF split rx control register
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param state
+ *    1 - set the drop enable bit in the split rx control register.
+ *    0 - reset the drop enable bit in the split rx control register.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port, uint16_t vf, int state);
+/**
  * Set a traffic mirroring rule on an Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 45ddf44..3fe149f 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,17 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	rte_eth_dev_set_all_queues_drop_en;
+	rte_eth_dev_set_tx_loopback;
+	rte_eth_dev_set_vf_mac_addr;
+	rte_eth_dev_set_vf_mac_anti_spoof;
+	rte_eth_dev_set_vf_split_drop_en;
+	rte_eth_dev_set_vf_vlan_anti_spoof;
+	rte_eth_dev_set_vf_vlan_insert;
+	rte_eth_dev_set_vf_vlan_strip;
+	rte_eth_dev_vf_ping;
+} DPDK_16.07;
-- 
2.9.0

[PATCH v3 2/3] net/ixgbe: add functions for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-16 14:16:02

Add new functions to configure and manage VF's on an Intel 82559 NIC.

add ixgbe_vf_ping function.
add ixgbe_set_vf_vlan_anti_spoof function.
add ixgbe_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add ixgbe_set_vf_vlan_insert function.
add ixgbe_set_tx_loopback function.
add ixgbe_set_all_queues_drop function.
add ixgbe_set_vf_split_drop_en function.
add ixgbe_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 166 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index fb618ef..9875290 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -240,6 +240,8 @@ static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
 static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev,
 					   struct ether_addr *mac_addr);
+static int ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf,
+				struct ether_addr *mac_addr);
 static void ixgbe_dcb_init(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config);
 
 /* For Virtual Function support */
@@ -280,6 +282,17 @@ static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
 static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
 static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 		uint64_t pool_mask, uint8_t vlan_on);
+static void ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static void ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static int ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf);
+static void ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf,
+		int vlan);
+static void ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on);
+static void ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state);
+static void ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf,
+		int state);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 		struct rte_eth_mirror_conf *mirror_conf,
 		uint8_t rule_id, uint8_t on);
@@ -562,6 +575,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.mac_addr_add         = ixgbe_add_rar,
 	.mac_addr_remove      = ixgbe_remove_rar,
 	.mac_addr_set         = ixgbe_set_default_mac_addr,
+	.set_vf_mac_addr      = ixgbe_set_vf_mac_addr,
 	.uc_hash_table_set    = ixgbe_uc_hash_table_set,
 	.uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
 	.mirror_rule_set      = ixgbe_mirror_rule_set,
@@ -570,6 +584,13 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.set_vf_rx            = ixgbe_set_pool_rx,
 	.set_vf_tx            = ixgbe_set_pool_tx,
 	.set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
+	.set_vf_vlan_anti_spoof  = ixgbe_set_vf_vlan_anti_spoof,
+	.set_vf_mac_anti_spoof   = ixgbe_set_vf_mac_anti_spoof,
+	.vf_ping              = ixgbe_vf_ping,
+	.set_vf_vlan_insert   = ixgbe_set_vf_vlan_insert,
+	.set_tx_loopback      = ixgbe_set_tx_loopback,
+	.set_all_queues_drop_en = ixgbe_set_all_queues_drop_en,
+	.set_vf_split_drop_en = ixgbe_set_vf_split_drop_en,
 	.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
 	.set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
 	.reta_update          = ixgbe_dev_rss_reta_update,
@@ -4069,6 +4090,22 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
 }
 
 static int
+ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf, struct ether_addr *mac_addr)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_vf_info *vfinfo =
+		*(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+	uint8_t *new_mac = (uint8_t *)(mac_addr);
+
+	if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
+		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, ETHER_ADDR_LEN);
+		return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV);
+	}
+	return -1;
+}
+
+static int
 ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
 	uint32_t hlreg0;
@@ -4661,6 +4698,135 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 	return ret;
 }
 
+static void
+ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_vlan_anti_spoofing(hw, on, vf);
+}
+
+static void
+ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_mac_anti_spoofing(hw, on, vf);
+}
+
+static int
+ixgbe_vf_ping(struct rte_eth_dev *dev, int32_t vf)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_vf_info *vfinfo =
+		*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+
+	u32 ping;
+	int i;
+
+	for (i = 0; i < dev->pci_dev->max_vfs; i++) {
+		ping = IXGBE_PF_CONTROL_MSG;
+		if (vfinfo[i].clear_to_send)
+			ping |= IXGBE_VT_MSGTYPE_CTS;
+
+		/* ping every VF or only one specified */
+		if (vf < 0 || vf == i)
+			ixgbe_write_mbx(hw, &ping, 1, i);
+	}
+
+	return ret;
+}
+
+static void
+ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf, int vlan)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+	if (vlan) {
+		ctrl = vlan;
+		ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
+	} else {
+		ctrl = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
+}
+
+static void
+ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+	/* enable or disable VMDQ loopback */
+	if (on)
+		ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
+	else
+		ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
+}
+
+static void
+ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+	int i;
+	int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i <= num_queues; i++) {
+		reg_value = IXGBE_QDE_WRITE |
+				(i << IXGBE_QDE_IDX_SHIFT) |
+				(state & IXGBE_QDE_ENABLE);
+		IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
+	}
+}
+
+static void
+ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* only support VF's 0 to 63 */
+	if (vf > 63)
+		return;
+
+	reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
+	if (state)
+		reg_value |= IXGBE_SRRCTL_DROP_EN;
+	else
+		reg_value &= ~IXGBE_SRRCTL_DROP_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
-- 
2.9.0

[PATCH v3 3/3] app/test_pmd: add tests for new API's

From: Bernard Iremonger <hidden>
Date: 2016-09-16 14:16:03

add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf ping
add test for vf vlan strip
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit
add test for vf split drop enable bit
add test for vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
---
 app/test-pmd/cmdline.c                      | 707 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  70 ++-
 2 files changed, 774 insertions(+), 3 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f90befc..264aa90 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -10585,6 +10585,704 @@ cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
 	},
 };
 
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+	ret = rte_eth_dev_set_vf_vlan_anti_spoof(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan anti spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+	.f = cmd_set_vf_vlan_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_anti_spoof_set,
+		(void *)&cmd_vf_vlan_anti_spoof_vf,
+		(void *)&cmd_vf_vlan_anti_spoof_vlan,
+		(void *)&cmd_vf_vlan_anti_spoof_antispoof,
+		(void *)&cmd_vf_vlan_anti_spoof_port_id,
+		(void *)&cmd_vf_vlan_anti_spoof_vf_id,
+		(void *)&cmd_vf_vlan_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_anti_spoof(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan mac spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+	.f = cmd_set_vf_mac_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf mac antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_mac_anti_spoof_set,
+		(void *)&cmd_vf_mac_anti_spoof_vf,
+		(void *)&cmd_vf_mac_anti_spoof_mac,
+		(void *)&cmd_vf_mac_anti_spoof_antispoof,
+		(void *)&cmd_vf_mac_anti_spoof_port_id,
+		(void *)&cmd_vf_mac_anti_spoof_vf_id,
+		(void *)&cmd_vf_mac_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf ping configuration */
+
+/* Common result structure for vf ping */
+struct cmd_vf_ping_result {
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t ping;
+	uint8_t port_id;
+	int32_t vf_id;
+};
+
+/* Common CLI fields for ping vfs */
+cmdline_parse_token_string_t cmd_vf_ping_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_ping_ping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 ping, "ping");
+cmdline_parse_token_num_t cmd_vf_ping_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_ping_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_ping_result,
+		 vf_id, INT32);
+
+static void
+cmd_vf_ping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_ping_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_vf_ping(res->port_id, res->vf_id);
+	if (ret < 0)
+		printf("ping vfs programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_vf_ping = {
+	.f = cmd_vf_ping_parsed,
+	.data = NULL,
+	.help_str = "vf ping port_id vf_id|-1",
+	.tokens = {
+		(void *)&cmd_vf_ping_vf,
+		(void *)&cmd_vf_ping_ping,
+		(void *)&cmd_vf_ping_port_id,
+		(void *)&cmd_vf_ping_vf_id,
+		NULL,
+	},
+};
+
+/* vf vlan strip configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_strip_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t strip;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_strip_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_strip_strip =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 strip, "strip");
+cmdline_parse_token_num_t cmd_vf_vlan_strip_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_strip_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_strip_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_strip_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_strip_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_strip_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_strip(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan strip programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_strip = {
+	.f = cmd_set_vf_vlan_strip_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan strip port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_strip_set,
+		(void *)&cmd_vf_vlan_strip_vf,
+		(void *)&cmd_vf_vlan_strip_vlan,
+		(void *)&cmd_vf_vlan_strip_strip,
+		(void *)&cmd_vf_vlan_strip_port_id,
+		(void *)&cmd_vf_vlan_strip_vf_id,
+		(void *)&cmd_vf_vlan_strip_on_off,
+		NULL,
+	},
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t insert;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_insert_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_insert_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_insert(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan insert programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+	.f = cmd_set_vf_vlan_insert_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan insert port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_insert_set,
+		(void *)&cmd_vf_vlan_insert_vf,
+		(void *)&cmd_vf_vlan_insert_vlan,
+		(void *)&cmd_vf_vlan_insert_insert,
+		(void *)&cmd_vf_vlan_insert_port_id,
+		(void *)&cmd_vf_vlan_insert_vf_id,
+		(void *)&cmd_vf_vlan_insert_on_off,
+		NULL,
+	},
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t tx;
+	cmdline_fixed_string_t loopback;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_tx_loopback_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_tx_loopback_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_tx_loopback_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_tx_loopback(res->port_id, is_on);
+	if (ret < 0)
+		printf("tx loopback programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+	.f = cmd_set_tx_loopback_parsed,
+	.data = NULL,
+	.help_str = "set tx loopback port_id on|off",
+	.tokens = {
+		(void *)&cmd_tx_loopback_set,
+		(void *)&cmd_tx_loopback_tx,
+		(void *)&cmd_tx_loopback_loopback,
+		(void *)&cmd_tx_loopback_port_id,
+		(void *)&cmd_tx_loopback_on_off,
+		NULL,
+	},
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t queues;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_all_queues_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_all_queues_drop_en(res->port_id, is_on);
+	if (ret < 0)
+		printf("all queues drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+	.f = cmd_set_all_queues_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set all queues drop port_id on|off",
+	.tokens = {
+		(void *)&cmd_all_queues_drop_en_set,
+		(void *)&cmd_all_queues_drop_en_all,
+		(void *)&cmd_all_queues_drop_en_queues,
+		(void *)&cmd_all_queues_drop_en_drop,
+		(void *)&cmd_all_queues_drop_en_port_id,
+		(void *)&cmd_all_queues_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t split;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_split_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_split_drop_en(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf split drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+	.f = cmd_set_vf_split_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set vf split drop port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_split_drop_en_set,
+		(void *)&cmd_vf_split_drop_en_vf,
+		(void *)&cmd_vf_split_drop_en_split,
+		(void *)&cmd_vf_split_drop_en_drop,
+		(void *)&cmd_vf_split_drop_en_port_id,
+		(void *)&cmd_vf_split_drop_en_vf_id,
+		(void *)&cmd_vf_split_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t addr;
+	uint8_t port_id;
+	uint16_t vf_id;
+	struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+	TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+		 mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_vf_mac_addr_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_addr(res->port_id, res->vf_id, &res->mac_addr);
+	if (ret < 0)
+		printf("set vf mac addr programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+	.f = cmd_set_vf_mac_addr_parsed,
+	.data = NULL,
+	.help_str = "set vf mac addr port_id vf_id xx:xx:xx:xx:xx:xx",
+	.tokens = {
+		(void *)&cmd_set_vf_mac_addr_set,
+		(void *)&cmd_set_vf_mac_addr_vf,
+		(void *)&cmd_set_vf_mac_addr_mac,
+		(void *)&cmd_set_vf_mac_addr_addr,
+		(void *)&cmd_set_vf_mac_addr_port_id,
+		(void *)&cmd_set_vf_mac_addr_vf_id,
+		(void *)&cmd_set_vf_mac_addr_mac_addr,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10739,6 +11437,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_vf_ping,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_strip,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f87e0c2..c84d5e2 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -473,6 +473,41 @@ For example, to change the port forwarding:
    RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03
    RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02
 
+set tx loopback
+~~~~~~~~~~~~~~~
+
+Enable/disable tx loopback::
+
+   testpmd> set tx loopback (port_id) (on|off)
+
+set drop enable
+~~~~~~~~~~~~~~~
+
+set drop enable bit for all queues::
+
+   testpmd> set all queues drop (port_id) (on|off)
+
+set split drop enable (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+set split drop enable bit for VF from PF::
+
+   testpmd> set vf split drop (port_id) (vf_id) (on|off)
+
+set mac antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set mac antispoof for a VF from the PF::
+
+   testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
+
+ping VF
+~~~~~~~
+
+Ping VF or all VF's from PF::
+
+   testpmd> vf ping (port_id) (vf_id | -1)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
@@ -487,6 +522,28 @@ Set the VLAN strip for a queue on a port::
 
    testpmd> vlan set stripq (on|off) (port_id,queue_id)
 
+vlan set strip (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN strip for a VF from the PF::
+
+   testpmd> set vf vlan strip (port_id) (vf_id) (on|off)
+
+vlan set insert (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN insert for a VF from the PF::
+
+   testpmd> set vf vlan insert  (port_id) (vf_id) (on|off)
+
+vlan set antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN antispoof for a VF from the PF::
+
+   testpmd> set vf vlan antispoof  (port_id) (vf_id) (on|off)
+
+
 vlan set filter
 ~~~~~~~~~~~~~~~
 
@@ -727,13 +784,20 @@ Remove a MAC address from a port::
 
    testpmd> mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)
 
-mac_addr add(for VF)
-~~~~~~~~~~~~~~~~~~~~
+mac_addr add (for VF)
+~~~~~~~~~~~~~~~~~~~~~
 
 Add an alternative MAC address for a VF to a port::
 
    testpmd> mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX)
 
+mac_addr set (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set the MAC address for a VF from the PF::
+
+   testpmd> set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)
+
 set port-uta
 ~~~~~~~~~~~~
 
-- 
2.9.0

[PATCH v4 0/3] add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-21 10:20:12

This patchset contains new DPDK API's requested by AT&T for use
with the Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the
point where AT&T have devloped a DPDK based tool, VFD, to do this.

This patch set adds API extensions to DPDK VF configuration.

Eight new functions have been added to the eth_dev_ops structure.
Corresponding functions have been added to the ixgbe PMD for the
Intel 82559 NIC.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd changes.

Note:
Adding new functions to the eth_dev_ops structure will cause an
ABI breakage.

Changes in v4:
rebase to latest master branch.
The rte_eth_dev_vf_ping API has been dropped as it is a work around for a bug.
The rte_eth_dev_set_vf_vlan_strip API has been renamed to
rte_eth_dev_set_vf_vlan_stripq.

Changes in v3:
rebase to latest master branch.
drop patches for callback functions
revise VF id checks in new librte_ether functions
revise testpmd commands for new API's

Changes in V2:
rebase to latest master branch.
fix compile  error with clang.

Bernard Iremonger (3):
  librte_ether: add API's for VF management
  net/ixgbe: add functions for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 644 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  62 ++-
 drivers/net/ixgbe/ixgbe_ethdev.c            | 138 ++++++
 lib/librte_ether/rte_ethdev.c               | 169 ++++++++
 lib/librte_ether/rte_ethdev.h               | 195 ++++++++-
 lib/librte_ether/rte_ether_version.map      |  13 +
 6 files changed, 1217 insertions(+), 4 deletions(-)

-- 
2.9.0

[PATCH v4 1/3] librte_ether: add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-21 10:20:15

Add new API functions to configure and manage VF's on a NIC.

add rte_eth_dev_set_vf_vlan_anti_spoof function.
add rte_eth_dev_set_vf_mac_anti_spoof function.
add rte_eth_dev_set_vf_vlan_stripq function.

Signed-off-by: azelezniak <redacted>

add rte_eth_dev_set_vf_vlan_insert function.
add rte_eth_dev_set_loopback function.
add rte_eth_dev_set_all_queues_drop function.
add rte_eth_dev_set_vf_split_drop_en function
add rte_eth_dev_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 169 ++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 195 ++++++++++++++++++++++++++++++++-
 lib/librte_ether/rte_ether_version.map |  13 +++
 3 files changed, 376 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 382c959..41d25c7 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2305,6 +2305,30 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
 }
 
 int
+rte_eth_dev_set_vf_mac_addr(uint8_t port_id, uint16_t vf, struct ether_addr *addr)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF mac addr: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_addr, -ENOTSUP);
+
+	return (*dev->dev_ops->set_vf_mac_addr)(dev, vf, addr);
+}
+
+int
 rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
 				uint16_t rx_mode, uint8_t on)
 {
@@ -2489,6 +2513,151 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF VLAN anti spoof: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_vlan_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port_id,
+			       uint16_t vf, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF MAC anti spoof:invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_mac_anti_spoof, -ENOTSUP);
+	(*dev->dev_ops->set_vf_mac_anti_spoof)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint16_t queues_per_pool;
+	uint32_t q;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan stripq: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_strip_queue_set, -ENOTSUP);
+
+	queues_per_pool = dev_info.vmdq_queue_num/dev_info.max_vmdq_pools;
+
+	for (q = 0; q < queues_per_pool; q++)
+		(*dev->dev_ops->vlan_strip_queue_set)(dev, q + vf * queues_per_pool, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan insert: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_insert, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_vlan_insert)(dev, vf, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_tx_loopback(uint8_t port_id, int on)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_tx_loopback, -ENOTSUP);
+
+	(*dev->dev_ops->set_tx_loopback)(dev, on);
+	return 0;
+}
+
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port_id, int state)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_all_queues_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_all_queues_drop_en)(dev, state);
+	return 0;
+}
+
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port_id, uint16_t vf, int state)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF split drop enable: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_split_drop_en, -ENOTSUP);
+
+	(*dev->dev_ops->set_vf_split_drop_en)(dev, vf, state);
+	return 0;
+}
+
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 96575e8..4be4bc7 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1233,6 +1233,11 @@ typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr);
 /**< @internal Set a MAC address into Receive Address Address Register */
 
+typedef int (*eth_set_vf_mac_addr_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  struct ether_addr *mac_addr);
+/**< @internal Set VF address into Receive Address Address Register */
+
 typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev,
 				  struct ether_addr *mac_addr,
 				  uint8_t on);
@@ -1264,6 +1269,34 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
 				  uint8_t vlan_on);
 /**< @internal Set VF VLAN pool filter */
 
+typedef void (*eth_set_vf_vlan_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF VLAN anti spoof */
+
+typedef void (*eth_set_vf_mac_anti_spoof_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  uint8_t on);
+/**< @internal Set VF MAC anti spoof */
+
+typedef void (*eth_set_vf_vlan_insert_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int vlan);
+/**< @internal Set VF vlan insert */
+
+typedef void (*eth_set_tx_loopback_t)(struct rte_eth_dev *dev,
+				  int on);
+/**< @internal Set tx loopback */
+
+typedef void (*eth_set_all_queues_drop_en_t)(struct rte_eth_dev *dev,
+				  int state);
+/**< @internal Set all queues drop */
+
+typedef void (*eth_set_vf_split_drop_en_t)(struct rte_eth_dev *dev,
+				  uint16_t vf,
+				  int state);
+/**< @internal Set the enable drop bit in the VF split rx control register */
+
 typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
 				uint16_t queue_idx,
 				uint16_t tx_rate);
@@ -1468,6 +1501,7 @@ struct eth_dev_ops {
 	eth_mac_addr_remove_t      mac_addr_remove; /**< Remove MAC address */
 	eth_mac_addr_add_t         mac_addr_add;  /**< Add a MAC address */
 	eth_mac_addr_set_t         mac_addr_set;  /**< Set a MAC address */
+	eth_set_vf_mac_addr_t      set_vf_mac_addr;  /**< Set a VF MAC address */
 	eth_uc_hash_table_set_t    uc_hash_table_set;  /**< Set Unicast Table Array */
 	eth_uc_all_hash_table_set_t uc_all_hash_table_set;  /**< Set Unicast hash bitmap */
 	eth_mirror_rule_set_t	   mirror_rule_set;  /**< Add a traffic mirror rule.*/
@@ -1476,6 +1510,12 @@ struct eth_dev_ops {
 	eth_set_vf_rx_t            set_vf_rx;  /**< enable/disable a VF receive */
 	eth_set_vf_tx_t            set_vf_tx;  /**< enable/disable a VF transmit */
 	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
+	eth_set_vf_vlan_anti_spoof_t  set_vf_vlan_anti_spoof; /**< Set VF VLAN anti spoof */
+	eth_set_vf_mac_anti_spoof_t   set_vf_mac_anti_spoof;  /**< Set VF MAC anti spoof */
+	eth_set_vf_vlan_insert_t   set_vf_vlan_insert; /** <Set VF VLAN insert */
+	eth_set_tx_loopback_t      set_tx_loopback; /** <Set tx loopback */
+	eth_set_all_queues_drop_en_t set_all_queues_drop_en; /** <Set queue drop enable bit */
+	eth_set_vf_split_drop_en_t  set_vf_split_drop_en; /** <Set split drop enable bit.*/
 	/** Add UDP tunnel port. */
 	eth_udp_tunnel_port_add_t udp_tunnel_port_add;
 	/** Del UDP tunnel port. */
@@ -3332,7 +3372,23 @@ int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr);
  */
 int rte_eth_dev_default_mac_addr_set(uint8_t port, struct ether_addr *mac_addr);
 
-
+/**
+ * Set the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful, or *mac_addr* didn't exist.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if MAC address is invalid.
+ */
+int rte_eth_dev_set_vf_mac_addr(uint8_t port, uint16_t vf,
+				struct ether_addr *mac_addr);
 /**
  * Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device.
  *
@@ -3499,6 +3555,143 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
 				uint8_t vlan_on);
 
 /**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param vlan_on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_mac_anti_spoof(uint8_t port,
+				uint16_t vf,
+				uint8_t on);
+
+/**
+ * Enable/Disable vf vlan strip for all queues in a pool
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan strip on RX queues.
+ *    0 - Disable VF's vlan strip on RX queues.
+ * @param queues_per_pool
+ *    The number of queues per pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable vf vlan insert
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan insert.
+ *    0 - Disable VF's vlan insert
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_insert(uint8_t port, uint16_t vf, int on);
+
+/**
+ * Enable/Disable tx loopback
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable tx loopback.
+ *    0 - Disable tx loopback.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_tx_loopback(uint8_t port, int on);
+/**
+ * set all queues drop enable bit
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param state
+ *    1 - set the queue drop enable bit for all pools.
+ *    0 - reset the queue drop enable bit for all pools.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_all_queues_drop_en(uint8_t port, int state);
+/**
+ * set drop enable bit in the VF split rx control register
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param state
+ *    1 - set the drop enable bit in the split rx control register.
+ *    0 - reset the drop enable bit in the split rx control register.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_split_drop_en(uint8_t port, uint16_t vf, int state);
+/**
  * Set a traffic mirroring rule on an Ethernet device
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 45ddf44..4a1c1c7 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,16 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	rte_eth_dev_set_all_queues_drop_en;
+	rte_eth_dev_set_tx_loopback;
+	rte_eth_dev_set_vf_mac_addr;
+	rte_eth_dev_set_vf_mac_anti_spoof;
+	rte_eth_dev_set_vf_split_drop_en;
+	rte_eth_dev_set_vf_vlan_anti_spoof;
+	rte_eth_dev_set_vf_vlan_insert;
+	rte_eth_dev_set_vf_vlan_stripq;
+} DPDK_16.07;
-- 
2.9.0

[PATCH v4 2/3] net/ixgbe: add functions for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-21 10:20:19

Add new functions to configure and manage VF's on an Intel 82559 NIC.

add ixgbe_set_vf_vlan_anti_spoof function.
add ixgbe_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add ixgbe_set_vf_vlan_insert function.
add ixgbe_set_tx_loopback function.
add ixgbe_set_all_queues_drop function.
add ixgbe_set_vf_split_drop_en function.
add ixgbe_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 138 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 138 insertions(+)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 73a406b..38bb52c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -240,6 +240,8 @@ static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
 static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
 static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev,
 					   struct ether_addr *mac_addr);
+static int ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf,
+				  struct ether_addr *mac_addr);
 static void ixgbe_dcb_init(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config);
 
 /* For Virtual Function support */
@@ -280,6 +282,16 @@ static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
 static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
 static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 		uint64_t pool_mask, uint8_t vlan_on);
+static void ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static void ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+		uint16_t vf, uint8_t on);
+static void ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf,
+		int vlan);
+static void ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on);
+static void ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state);
+static void ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf,
+		int state);
 static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 		struct rte_eth_mirror_conf *mirror_conf,
 		uint8_t rule_id, uint8_t on);
@@ -562,6 +574,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.mac_addr_add         = ixgbe_add_rar,
 	.mac_addr_remove      = ixgbe_remove_rar,
 	.mac_addr_set         = ixgbe_set_default_mac_addr,
+	.set_vf_mac_addr      = ixgbe_set_vf_mac_addr,
 	.uc_hash_table_set    = ixgbe_uc_hash_table_set,
 	.uc_all_hash_table_set  = ixgbe_uc_all_hash_table_set,
 	.mirror_rule_set      = ixgbe_mirror_rule_set,
@@ -570,6 +583,12 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.set_vf_rx            = ixgbe_set_pool_rx,
 	.set_vf_tx            = ixgbe_set_pool_tx,
 	.set_vf_vlan_filter   = ixgbe_set_pool_vlan_filter,
+	.set_vf_vlan_anti_spoof  = ixgbe_set_vf_vlan_anti_spoof,
+	.set_vf_mac_anti_spoof   = ixgbe_set_vf_mac_anti_spoof,
+	.set_vf_vlan_insert   = ixgbe_set_vf_vlan_insert,
+	.set_tx_loopback      = ixgbe_set_tx_loopback,
+	.set_all_queues_drop_en = ixgbe_set_all_queues_drop_en,
+	.set_vf_split_drop_en = ixgbe_set_vf_split_drop_en,
 	.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
 	.set_vf_rate_limit    = ixgbe_set_vf_rate_limit,
 	.reta_update          = ixgbe_dev_rss_reta_update,
@@ -4069,6 +4088,22 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
 }
 
 static int
+ixgbe_set_vf_mac_addr(struct rte_eth_dev *dev, uint16_t vf, struct ether_addr *mac_addr)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_vf_info *vfinfo =
+		*(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+	uint8_t *new_mac = (uint8_t *)(mac_addr);
+
+	if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
+		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, ETHER_ADDR_LEN);
+		return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV);
+	}
+	return -1;
+}
+
+static int
 ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
 	uint32_t hlreg0;
@@ -4661,6 +4696,109 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 	return ret;
 }
 
+static void
+ixgbe_set_vf_vlan_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_vlan_anti_spoofing(hw, on, vf);
+}
+
+static void
+ixgbe_set_vf_mac_anti_spoof(struct rte_eth_dev *dev,
+			uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	mac->ops.set_mac_anti_spoofing(hw, on, vf);
+}
+
+static void
+ixgbe_set_vf_vlan_insert(struct rte_eth_dev *dev, uint16_t vf, int vlan)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+	if (vlan) {
+		ctrl = vlan;
+		ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
+	} else {
+		ctrl = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
+}
+
+static void
+ixgbe_set_tx_loopback(struct rte_eth_dev *dev, int on)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ctrl;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+	/* enable or disable VMDQ loopback */
+	if (on)
+		ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
+	else
+		ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
+}
+
+static void
+ixgbe_set_all_queues_drop_en(struct rte_eth_dev *dev, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+	int i;
+	int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i <= num_queues; i++) {
+		reg_value = IXGBE_QDE_WRITE |
+				(i << IXGBE_QDE_IDX_SHIFT) |
+				(state & IXGBE_QDE_ENABLE);
+		IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
+	}
+}
+
+static void
+ixgbe_set_vf_split_drop_en(struct rte_eth_dev *dev, uint16_t vf, int state)
+{
+	struct ixgbe_hw *hw =
+		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t reg_value;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* only support VF's 0 to 63 */
+	if (vf > 63)
+		return;
+
+	reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
+	if (state)
+		reg_value |= IXGBE_SRRCTL_DROP_EN;
+	else
+		reg_value &= ~IXGBE_SRRCTL_DROP_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
-- 
2.9.0

[PATCH v4 3/3] app/test_pmd: add tests for new API's

From: Bernard Iremonger <hidden>
Date: 2016-09-21 10:20:22

add test for vf vlan anti spoof
add test for vf mac anti spoof
add test for vf vlan stripq
add test for vf vlan insert
add test for tx loopback
add test for all queues drop enable bit
add test for vf split drop enable bit
add test for vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
---
 app/test-pmd/cmdline.c                      | 644 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  62 ++-
 2 files changed, 703 insertions(+), 3 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f90befc..982bf88 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -10585,6 +10585,642 @@ cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
 	},
 };
 
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+	ret = rte_eth_dev_set_vf_vlan_anti_spoof(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan anti spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+	.f = cmd_set_vf_vlan_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_anti_spoof_set,
+		(void *)&cmd_vf_vlan_anti_spoof_vf,
+		(void *)&cmd_vf_vlan_anti_spoof_vlan,
+		(void *)&cmd_vf_vlan_anti_spoof_antispoof,
+		(void *)&cmd_vf_vlan_anti_spoof_port_id,
+		(void *)&cmd_vf_vlan_anti_spoof_vf_id,
+		(void *)&cmd_vf_vlan_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_anti_spoof(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan mac spoofing programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+	.f = cmd_set_vf_mac_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf mac antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_mac_anti_spoof_set,
+		(void *)&cmd_vf_mac_anti_spoof_vf,
+		(void *)&cmd_vf_mac_anti_spoof_mac,
+		(void *)&cmd_vf_mac_anti_spoof_antispoof,
+		(void *)&cmd_vf_mac_anti_spoof_port_id,
+		(void *)&cmd_vf_mac_anti_spoof_vf_id,
+		(void *)&cmd_vf_mac_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+
+
+/* vf vlan strip queue configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_stripq_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t stripq;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_stripq =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 stripq, "stripq");
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_stripq_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_stripq_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_stripq(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan strip programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_stripq = {
+	.f = cmd_set_vf_vlan_stripq_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan stripq port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_stripq_set,
+		(void *)&cmd_vf_vlan_stripq_vf,
+		(void *)&cmd_vf_vlan_stripq_vlan,
+		(void *)&cmd_vf_vlan_stripq_stripq,
+		(void *)&cmd_vf_vlan_stripq_port_id,
+		(void *)&cmd_vf_vlan_stripq_vf_id,
+		(void *)&cmd_vf_vlan_stripq_on_off,
+		NULL,
+	},
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t insert;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_insert_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_insert_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_vlan_insert(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf vlan insert programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+	.f = cmd_set_vf_vlan_insert_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan insert port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_insert_set,
+		(void *)&cmd_vf_vlan_insert_vf,
+		(void *)&cmd_vf_vlan_insert_vlan,
+		(void *)&cmd_vf_vlan_insert_insert,
+		(void *)&cmd_vf_vlan_insert_port_id,
+		(void *)&cmd_vf_vlan_insert_vf_id,
+		(void *)&cmd_vf_vlan_insert_on_off,
+		NULL,
+	},
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t tx;
+	cmdline_fixed_string_t loopback;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_tx_loopback_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_tx_loopback_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_tx_loopback_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_tx_loopback(res->port_id, is_on);
+	if (ret < 0)
+		printf("tx loopback programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+	.f = cmd_set_tx_loopback_parsed,
+	.data = NULL,
+	.help_str = "set tx loopback port_id on|off",
+	.tokens = {
+		(void *)&cmd_tx_loopback_set,
+		(void *)&cmd_tx_loopback_tx,
+		(void *)&cmd_tx_loopback_loopback,
+		(void *)&cmd_tx_loopback_port_id,
+		(void *)&cmd_tx_loopback_on_off,
+		NULL,
+	},
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t queues;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_all_queues_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_eth_dev_set_all_queues_drop_en(res->port_id, is_on);
+	if (ret < 0)
+		printf("all queues drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+	.f = cmd_set_all_queues_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set all queues drop port_id on|off",
+	.tokens = {
+		(void *)&cmd_all_queues_drop_en_set,
+		(void *)&cmd_all_queues_drop_en_all,
+		(void *)&cmd_all_queues_drop_en_queues,
+		(void *)&cmd_all_queues_drop_en_drop,
+		(void *)&cmd_all_queues_drop_en_port_id,
+		(void *)&cmd_all_queues_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t split;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_split_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_split_drop_en(res->port_id, res->vf_id, is_on);
+	if (ret < 0)
+		printf("vf split drop enable programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+	.f = cmd_set_vf_split_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set vf split drop port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_split_drop_en_set,
+		(void *)&cmd_vf_split_drop_en_vf,
+		(void *)&cmd_vf_split_drop_en_split,
+		(void *)&cmd_vf_split_drop_en_drop,
+		(void *)&cmd_vf_split_drop_en_port_id,
+		(void *)&cmd_vf_split_drop_en_vf_id,
+		(void *)&cmd_vf_split_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t addr;
+	uint8_t port_id;
+	uint16_t vf_id;
+	struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+	TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+		 mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_vf_mac_addr_result *res = parsed_result;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->vf_id > 63) {
+		printf("vf_id must be less than 64.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_set_vf_mac_addr(res->port_id, res->vf_id, &res->mac_addr);
+	if (ret < 0)
+		printf("set vf mac addr programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+	.f = cmd_set_vf_mac_addr_parsed,
+	.data = NULL,
+	.help_str = "set vf mac addr port_id vf_id xx:xx:xx:xx:xx:xx",
+	.tokens = {
+		(void *)&cmd_set_vf_mac_addr_set,
+		(void *)&cmd_set_vf_mac_addr_vf,
+		(void *)&cmd_set_vf_mac_addr_mac,
+		(void *)&cmd_set_vf_mac_addr_addr,
+		(void *)&cmd_set_vf_mac_addr_port_id,
+		(void *)&cmd_set_vf_mac_addr_vf_id,
+		(void *)&cmd_set_vf_mac_addr_mac_addr,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10739,6 +11375,14 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_stripq,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f87e0c2..145c425 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -473,6 +473,34 @@ For example, to change the port forwarding:
    RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03
    RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02
 
+set tx loopback
+~~~~~~~~~~~~~~~
+
+Enable/disable tx loopback::
+
+   testpmd> set tx loopback (port_id) (on|off)
+
+set drop enable
+~~~~~~~~~~~~~~~
+
+set drop enable bit for all queues::
+
+   testpmd> set all queues drop (port_id) (on|off)
+
+set split drop enable (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+set split drop enable bit for VF from PF::
+
+   testpmd> set vf split drop (port_id) (vf_id) (on|off)
+
+set mac antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set mac antispoof for a VF from the PF::
+
+   testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
@@ -487,6 +515,27 @@ Set the VLAN strip for a queue on a port::
 
    testpmd> vlan set stripq (on|off) (port_id,queue_id)
 
+vlan set stripq (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN strip for all queues in a pool for a VF from the PF::
+
+   testpmd> set vf vlan stripq (port_id) (vf_id) (on|off)
+
+vlan set insert (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN insert for a VF from the PF::
+
+   testpmd> set vf vlan insert (port_id) (vf_id) (on|off)
+
+vlan set antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN antispoof for a VF from the PF::
+
+   testpmd> set vf vlan antispoof (port_id) (vf_id) (on|off)
+
 vlan set filter
 ~~~~~~~~~~~~~~~
 
@@ -727,13 +776,20 @@ Remove a MAC address from a port::
 
    testpmd> mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)
 
-mac_addr add(for VF)
-~~~~~~~~~~~~~~~~~~~~
+mac_addr add (for VF)
+~~~~~~~~~~~~~~~~~~~~~
 
 Add an alternative MAC address for a VF to a port::
 
    testpmd> mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX)
 
+mac_addr set (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set the MAC address for a VF from the PF::
+
+   testpmd> set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)
+
 set port-uta
 ~~~~~~~~~~~~
 
-- 
2.9.0

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-22 17:04:39

2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id,
uint8_t on)) For instance, In Thunderx PMD, We are not exposing a
separate port_id for PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t
rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t
tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to the PF.
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF from the
host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Bruce Richardson <hidden>
Date: 2016-09-23 09:20:52

On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id,
uint8_t on)) For instance, In Thunderx PMD, We are not exposing a
separate port_id for PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t
rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t
tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to the PF.
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF from the
host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have a port id
IMHO. DPDK can't actually do anything with it.

The PCI device for the VF is likely passed through to a different VM and being
used there. Unfortunately, the VF still needs certain things done for it by the
PF, so if the PF is under DPDK control, it needs to provide the functionality
to assist the VF.

/Bruce

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-23 09:36:23

2016-09-23 10:20, Bruce Richardson:
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id,
uint8_t on)) For instance, In Thunderx PMD, We are not exposing a
separate port_id for PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t
rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t
tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to the PF.
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF from the
host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have a port id
IMHO. DPDK can't actually do anything with it.
You say the contrary below.
The PCI device for the VF is likely passed through to a different VM and being
used there. Unfortunately, the VF still needs certain things done for it by the
PF, so if the PF is under DPDK control, it needs to provide the functionality
to assist the VF.
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Richardson, Bruce <hidden>
Date: 2016-09-23 09:53:53

-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
Sent: Friday, September 23, 2016 10:36 AM
To: Richardson, Bruce <redacted>
Cc: Iremonger, Bernard <redacted>; dev@dpdk.org; Jerin
Jacob [off-list ref]; Shah, Rahul R
[off-list ref]; Lu, Wenzhuo [off-list ref]; azelezniak
[off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx PMD, We are
not exposing a separate port_id for PF. We only enumerate
0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf,
uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF from
the host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have a
port id IMHO. DPDK can't actually do anything with it.
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF, but DPDK doesn't actually have a device that corresponds to the VF. There are no PCI bar mappings for it, DPDK can't do RX and TX with it etc.?
quoted
The PCI device for the VF is likely passed through to a different VM
and being used there. Unfortunately, the VF still needs certain things
done for it by the PF, so if the PF is under DPDK control, it needs to
provide the functionality to assist the VF.
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be sure that we are ok with the results of that. Suppose we do create ethdevs for the VFs controlled by the PF. Does the new VF get counted in the rte_eth_dev_count() value (I assume yes)? How are apps meant to use the port? Do they have to put in a special case when iterating through all the port ids to check that it's not a pseudo port that can't do anything. None of the standard ethdev calls from an app will work on it, you can't configure nb rx/tx queues on it, you can't start or stop it, you can't do rx or tx on it, etc, etc.

/Bruce

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Bruce Richardson <hidden>
Date: 2016-09-23 10:34:16

On Fri, Sep 23, 2016 at 11:36:21AM +0200, Thomas Monjalon wrote:
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through port_id.
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t port_id,
uint8_t on)) For instance, In Thunderx PMD, We are not exposing a
separate port_id for PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar way:

rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf, uint16_t
rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t
tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to the PF.
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF from the
host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have a port id
IMHO. DPDK can't actually do anything with it.
You say the contrary below.
quoted
The PCI device for the VF is likely passed through to a different VM and being
used there. Unfortunately, the VF still needs certain things done for it by the
PF, so if the PF is under DPDK control, it needs to provide the functionality
to assist the VF.
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
Just to confirm I am understanding your suggestion correctly:

* for a normal app, eg. testpmd or l2fwd, things stay exactly as they are
* for an app that wants to control VFs from PFs, then we provide a new 
  ethdev driver, and a call in the PF to create an new instance of it 
  e.g. rte_eth_vf_from_pf(pf_port_id, vf_number)
* then to control the VF, you make regular rte_ethdev calls using the new
  ethdev port id you got from the vf_from_pf call.
* it's up to that app to know what ports are regular ports that can do IO,
  and what ports are VF control ports, though we may add in an ethdev flag value
  somewhere to assist in this.

Is that basically it?

/Bruce

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-23 13:15:28

2016-09-23 09:53, Richardson, Bruce:
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx PMD, We are
not exposing a separate port_id for PF. We only enumerate
0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf,
uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF from
the host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have a
port id IMHO. DPDK can't actually do anything with it.
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF, but DPDK doesn't actually have a device that corresponds to the VF. There are no PCI bar mappings for it, DPDK can't do RX and TX with it etc.?
Very good point.
There are only few ethdev functions which are supported by every drivers,
like Rx/Tx and would not be available for VF from PF interface.
quoted
quoted
The PCI device for the VF is likely passed through to a different VM
and being used there. Unfortunately, the VF still needs certain things
done for it by the PF, so if the PF is under DPDK control, it needs to
provide the functionality to assist the VF.
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be sure that we are ok with the results of that. Suppose we do create ethdevs for the VFs controlled by the PF. Does the new VF get counted in the rte_eth_dev_count() value (I assume yes)? How are apps meant to use the port? Do they have to put in a special case when iterating through all the port ids to check that it's not a pseudo port that can't do anything. None of the standard ethdev calls from an app will work on it, you can't configure nb rx/tx queues on it, you can't start or stop it, you can't do rx or tx on it, etc, etc.
Yes these devices would be special because their supported API would be
quite different. I was thinking that in the future you could add most
of the configuration functions through the VF mailbox.
But the Intel mailbox currently support only some special configurations
which are not supported by other devices even its own VF device (except
setting MAC address).
And when I read "set drop enable bit in the VF split rx control register",
it becomes clear it is really specific and has nothing to do in the
generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are aware of the
underlying device and driver. So we can directly include a header from
the driver. I suggest to retrieve a handler for the device which is not
a port id and will allow to call ixgbe functions directly.
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-23 17:02:20

Hi Thoms
-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
Sent: Friday, September 23, 2016 2:15 PM
To: Richardson, Bruce <redacted>; Iremonger, Bernard
[off-list ref]
Cc: dev@dpdk.org; Jerin Jacob <redacted>; Shah,
Rahul R [off-list ref]; Lu, Wenzhuo [off-list ref];
azelezniak [off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx PMD, We
are not exposing a separate port_id for PF. We only
enumerate 0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a
similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf,
uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf,
uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t
vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not
visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF
from the host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have
a port id IMHO. DPDK can't actually do anything with it.
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF, but DPDK
doesn't actually have a device that corresponds to the VF. There are no PCI
bar mappings for it, DPDK can't do RX and TX with it etc.?

Very good point.
There are only few ethdev functions which are supported by every drivers,
like Rx/Tx and would not be available for VF from PF interface.
quoted
quoted
quoted
The PCI device for the VF is likely passed through to a different
VM and being used there. Unfortunately, the VF still needs certain
things done for it by the PF, so if the PF is under DPDK control,
it needs to provide the functionality to assist the VF.
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be sure that we are
ok with the results of that. Suppose we do create ethdevs for the VFs
controlled by the PF. Does the new VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant to use the
port? Do they have to put in a special case when iterating through all the port
ids to check that it's not a pseudo port that can't do anything. None of the
standard ethdev calls from an app will work on it, you can't configure nb rx/tx
queues on it, you can't start or stop it, you can't do rx or tx on it, etc, etc.

Yes these devices would be special because their supported API would be
quite different. I was thinking that in the future you could add most of the
configuration functions through the VF mailbox.
But the Intel mailbox currently support only some special configurations
which are not supported by other devices even its own VF device (except
setting MAC address).
And when I read "set drop enable bit in the VF split rx control register", it
becomes clear it is really specific and has nothing to do in the generic ethdev
API.
That's why it is a NACK.

When we want to use these very specific features we are aware of the
underlying device and driver. So we can directly include a header from the
driver. I suggest to retrieve a handler for the device which is not a port id and
will allow to call ixgbe functions directly.
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html
I have been reading the net/vhost mail thread above. The following quote is from this thread.

"It means I would be in favor of introducing API in drivers for very specific features."

At present all the PMD functions are accessed through the eth_dev_ops structure, there are no PMD API's.

Is your proposal to add API(s) to the DPDK ixgbe PMD (similar to a driver ioctl API) which can be accessed through a generic API in the ethdev?

What will this generic API look like?

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-23 17:18:45

2016-09-23 17:02, Iremonger, Bernard:
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx PMD, We
are not exposing a separate port_id for PF. We only
enumerate 0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a
similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t vf,
uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf,
uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf,
uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t
vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from PF.
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not
visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the VF
from the host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't have
a port id IMHO. DPDK can't actually do anything with it.
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF, but DPDK
doesn't actually have a device that corresponds to the VF. There are no PCI
bar mappings for it, DPDK can't do RX and TX with it etc.?

Very good point.
There are only few ethdev functions which are supported by every drivers,
like Rx/Tx and would not be available for VF from PF interface.
quoted
quoted
quoted
The PCI device for the VF is likely passed through to a different
VM and being used there. Unfortunately, the VF still needs certain
things done for it by the PF, so if the PF is under DPDK control,
it needs to provide the functionality to assist the VF.
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be sure that we are
ok with the results of that. Suppose we do create ethdevs for the VFs
controlled by the PF. Does the new VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant to use the
port? Do they have to put in a special case when iterating through all the port
ids to check that it's not a pseudo port that can't do anything. None of the
standard ethdev calls from an app will work on it, you can't configure nb rx/tx
queues on it, you can't start or stop it, you can't do rx or tx on it, etc, etc.

Yes these devices would be special because their supported API would be
quite different. I was thinking that in the future you could add most of the
configuration functions through the VF mailbox.
But the Intel mailbox currently support only some special configurations
which are not supported by other devices even its own VF device (except
setting MAC address).
And when I read "set drop enable bit in the VF split rx control register", it
becomes clear it is really specific and has nothing to do in the generic ethdev
API.
That's why it is a NACK.

When we want to use these very specific features we are aware of the
underlying device and driver. So we can directly include a header from the
driver. I suggest to retrieve a handler for the device which is not a port id and
will allow to call ixgbe functions directly.
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html
I have been reading the net/vhost mail thread above. The following quote is from this thread.

"It means I would be in favor of introducing API in drivers for very specific features."

At present all the PMD functions are accessed through the eth_dev_ops structure, there are no PMD API's.

Is your proposal to add API(s) to the DPDK ixgbe PMD (similar to a driver ioctl API) which can be accessed through a generic API in the ethdev?
Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a handler
(an opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the specific ixgbe
function, passing the device handler.
How does it sound?

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-26 15:37:22

Hi Thomas, Bruce,

<snip>
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only
through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx PMD,
We are not exposing a separate port_id for PF. We
only enumerate 0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a
similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t
vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf,
uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf,
uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id,
uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not
visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the
VF from the host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't
have a port id IMHO. DPDK can't actually do anything with it.
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF, but
DPDK
doesn't actually have a device that corresponds to the VF. There are
no PCI bar mappings for it, DPDK can't do RX and TX with it etc.?

Very good point.
There are only few ethdev functions which are supported by every
drivers, like Rx/Tx and would not be available for VF from PF interface.
quoted
quoted
quoted
The PCI device for the VF is likely passed through to a
different VM and being used there. Unfortunately, the VF still
needs certain things done for it by the PF, so if the PF is
under DPDK control, it needs to provide the functionality to assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be sure
that we are
ok with the results of that. Suppose we do create ethdevs for the
VFs controlled by the PF. Does the new VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant to use
the port? Do they have to put in a special case when iterating
through all the port ids to check that it's not a pseudo port that
can't do anything. None of the standard ethdev calls from an app
will work on it, you can't configure nb rx/tx queues on it, you can't start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their supported API would
be quite different. I was thinking that in the future you could add
most of the configuration functions through the VF mailbox.
But the Intel mailbox currently support only some special
configurations which are not supported by other devices even its own
VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx control
register", it becomes clear it is really specific and has nothing to
do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are aware of the
underlying device and driver. So we can directly include a header
from the driver. I suggest to retrieve a handler for the device
which is not a port id and will allow to call ixgbe functions directly.
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html
I have been reading the net/vhost mail thread above. The following quote
is from this thread.
quoted
"It means I would be in favor of introducing API in drivers for very specific
features."
quoted
At present all the PMD functions are accessed through the eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD (similar to a driver
ioctl API) which can be accessed through a generic API in the ethdev?

Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a handler (an
opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the specific ixgbe function,
passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void** pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing driver specific functions.

Using the pmd_handle the driver specific functions can be called (without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the following patch?

[PATCH] net/vhost: Add function to retreive the 'vid' for a given port id

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-26 16:59:28

2016-09-26 15:37, Iremonger, Bernard:
Hi Thomas, Bruce,

<snip>
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon wrote:
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions here?
It can be generic(PF/VF) function indexed only
through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx PMD,
We are not exposing a separate port_id for PF. We
only enumerate 0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control the VF from the PF.

The following librte_ether functions already work in a
similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,  uint16_t
vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf,
uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf,
uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id,
uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is not
visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to the
VF from the host instead of having the couple PF port id / VF id.
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array rte_eth_devices?
Hi Thomas,

The VF is not a port visible to DPDK, though, so it shouldn't
have a port id IMHO. DPDK can't actually do anything with it.
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF, but
DPDK
doesn't actually have a device that corresponds to the VF. There are
no PCI bar mappings for it, DPDK can't do RX and TX with it etc.?

Very good point.
There are only few ethdev functions which are supported by every
drivers, like Rx/Tx and would not be available for VF from PF interface.
quoted
quoted
quoted
The PCI device for the VF is likely passed through to a
different VM and being used there. Unfortunately, the VF still
needs certain things done for it by the PF, so if the PF is
under DPDK control, it needs to provide the functionality to assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the mailbox things?
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be sure
that we are
ok with the results of that. Suppose we do create ethdevs for the
VFs controlled by the PF. Does the new VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant to use
the port? Do they have to put in a special case when iterating
through all the port ids to check that it's not a pseudo port that
can't do anything. None of the standard ethdev calls from an app
will work on it, you can't configure nb rx/tx queues on it, you can't start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their supported API would
be quite different. I was thinking that in the future you could add
most of the configuration functions through the VF mailbox.
But the Intel mailbox currently support only some special
configurations which are not supported by other devices even its own
VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx control
register", it becomes clear it is really specific and has nothing to
do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are aware of the
underlying device and driver. So we can directly include a header
from the driver. I suggest to retrieve a handler for the device
which is not a port id and will allow to call ixgbe functions directly.
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html
I have been reading the net/vhost mail thread above. The following quote
is from this thread.
quoted
"It means I would be in favor of introducing API in drivers for very specific
features."
quoted
At present all the PMD functions are accessed through the eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD (similar to a driver
ioctl API) which can be accessed through a generic API in the ethdev?

Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a handler (an
opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the specific ixgbe function,
passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void** pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing driver specific functions.

Using the pmd_handle the driver specific functions can be called (without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the following patch?

[PATCH] net/vhost: Add function to retreive the 'vid' for a given port id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving the
structs from the driver via rte_eth_devices?

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-27 10:31:10

Hi Thomas, Bruce,

<snip>
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-26 15:37, Iremonger, Bernard:
quoted
Hi Thomas, Bruce,

<snip>
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's
for VF management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions
here?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It can be generic(PF/VF) function indexed only
through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as
rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx
PMD, We are not exposing a separate port_id for
PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The following librte_ether functions already work
in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,
uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t
vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t
vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id,
uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated
to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is
not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to
the VF from the host instead of having the couple PF port id /
VF id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array
rte_eth_devices?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Hi Thomas,

The VF is not a port visible to DPDK, though, so it
shouldn't have a port id IMHO. DPDK can't actually do anything
with it.
quoted
quoted
quoted
quoted
quoted
quoted
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF,
but DPDK
doesn't actually have a device that corresponds to the VF. There
are no PCI bar mappings for it, DPDK can't do RX and TX with it etc.?

Very good point.
There are only few ethdev functions which are supported by every
drivers, like Rx/Tx and would not be available for VF from PF
interface.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The PCI device for the VF is likely passed through to a
different VM and being used there. Unfortunately, the VF
still needs certain things done for it by the PF, so if
the PF is under DPDK control, it needs to provide the
functionality to assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the mailbox
things?
quoted
quoted
quoted
quoted
quoted
quoted
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be
sure that we are
ok with the results of that. Suppose we do create ethdevs for
the VFs controlled by the PF. Does the new VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant to
use the port? Do they have to put in a special case when
iterating through all the port ids to check that it's not a
pseudo port that can't do anything. None of the standard ethdev
calls from an app will work on it, you can't configure nb rx/tx
queues on it, you can't start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their supported API
would be quite different. I was thinking that in the future you
could add most of the configuration functions through the VF
mailbox.
quoted
quoted
quoted
quoted
But the Intel mailbox currently support only some special
configurations which are not supported by other devices even its
own VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx control
register", it becomes clear it is really specific and has
nothing to do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are aware of
the underlying device and driver. So we can directly include a
header from the driver. I suggest to retrieve a handler for the
device which is not a port id and will allow to call ixgbe functions
directly.
quoted
quoted
quoted
quoted
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html
I have been reading the net/vhost mail thread above. The following
quote
is from this thread.
quoted
"It means I would be in favor of introducing API in drivers for
very specific
features."
quoted
At present all the PMD functions are accessed through the
eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD (similar to a
driver
ioctl API) which can be accessed through a generic API in the ethdev?

Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a
handler (an opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the specific
ixgbe function, passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void** pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing driver
specific functions.
quoted
Using the pmd_handle the driver specific functions can be called
(without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the following
patch?
quoted
[PATCH] net/vhost: Add function to retreive the 'vid' for a given port
id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving the structs
from the driver via rte_eth_devices?
Looking at the code in rte_eth_devices[]

struct rte_eth_dev  rte_eth_devices[RTE_MAX_ETHPORTS];

struct rte_eth_dev {

...

const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */ 

...

 void *pmd_ops;  /** < exported PMD specific functions */ 
  
}

The PMD functions are only accessible at present if they are in struct eth_dev_ops.

Adding a pmd_ops field to struct rte_eth_dev {} makes the PMD functions accessible and is a simpler solution than using rte_eth_dev_get_pmd_handle() to get access to the PMD functions.

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Bruce Richardson <hidden>
Date: 2016-09-27 13:01:35

On Tue, Sep 27, 2016 at 11:31:06AM +0100, Iremonger, Bernard wrote:
Hi Thomas, Bruce,

<snip>
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-26 15:37, Iremonger, Bernard:
quoted
Hi Thomas, Bruce,

<snip>
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's
for VF management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas Monjalon
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific functions
here?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It can be generic(PF/VF) function indexed only
through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as
rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In Thunderx
PMD, We are not exposing a separate port_id for
PF. We only enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to control the VF from the
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The following librte_ether functions already work
in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,
uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t
vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t
vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id,
uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions dedicated
to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF is
not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id to
the VF from the host instead of having the couple PF port id /
VF id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array
rte_eth_devices?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Hi Thomas,

The VF is not a port visible to DPDK, though, so it
shouldn't have a port id IMHO. DPDK can't actually do anything
with it.
quoted
quoted
quoted
quoted
quoted
quoted
You say the contrary below.
Well, yes and no. The driver can manipulate things for the VF,
but DPDK
doesn't actually have a device that corresponds to the VF. There
are no PCI bar mappings for it, DPDK can't do RX and TX with it etc.?

Very good point.
There are only few ethdev functions which are supported by every
drivers, like Rx/Tx and would not be available for VF from PF
interface.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The PCI device for the VF is likely passed through to a
different VM and being used there. Unfortunately, the VF
still needs certain things done for it by the PF, so if
the PF is under DPDK control, it needs to provide the
functionality to assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the mailbox
things?
quoted
quoted
quoted
quoted
quoted
quoted
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to be
sure that we are
ok with the results of that. Suppose we do create ethdevs for
the VFs controlled by the PF. Does the new VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant to
use the port? Do they have to put in a special case when
iterating through all the port ids to check that it's not a
pseudo port that can't do anything. None of the standard ethdev
calls from an app will work on it, you can't configure nb rx/tx
queues on it, you can't start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their supported API
would be quite different. I was thinking that in the future you
could add most of the configuration functions through the VF
mailbox.
quoted
quoted
quoted
quoted
But the Intel mailbox currently support only some special
configurations which are not supported by other devices even its
own VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx control
register", it becomes clear it is really specific and has
nothing to do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are aware of
the underlying device and driver. So we can directly include a
header from the driver. I suggest to retrieve a handler for the
device which is not a port id and will allow to call ixgbe functions
directly.
quoted
quoted
quoted
quoted
It could be achieved by adding an ethdev function like discussed here:
	http://dpdk.org/ml/archives/dev/2016-September/047392.html
I have been reading the net/vhost mail thread above. The following
quote
is from this thread.
quoted
"It means I would be in favor of introducing API in drivers for
very specific
features."
quoted
At present all the PMD functions are accessed through the
eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD (similar to a
driver
ioctl API) which can be accessed through a generic API in the ethdev?

Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a
handler (an opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the specific
ixgbe function, passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void** pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing driver
specific functions.
quoted
Using the pmd_handle the driver specific functions can be called
(without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the following
patch?
quoted
[PATCH] net/vhost: Add function to retreive the 'vid' for a given port
id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving the structs
from the driver via rte_eth_devices?
Looking at the code in rte_eth_devices[]

struct rte_eth_dev  rte_eth_devices[RTE_MAX_ETHPORTS];

struct rte_eth_dev {

...

const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */ 

...

 void *pmd_ops;  /** < exported PMD specific functions */ 
  
}

The PMD functions are only accessible at present if they are in struct eth_dev_ops.

Adding a pmd_ops field to struct rte_eth_dev {} makes the PMD functions accessible and is a simpler solution than using rte_eth_dev_get_pmd_handle() to get access to the PMD functions.

Regards,
Why would an ops structure be needed? If it's a private API for a driver, there
should be no need for function pointers, and instead the driver can define
regular functions in it's header file, no?

/Bruce

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-27 14:13:25

Hi Bruce,

<snip>
quoted
quoted
quoted
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add
API's for VF management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas
Monjalon
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific
functions
here?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It can be generic(PF/VF) function indexed
only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as
rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In
Thunderx PMD, We are not exposing a separate
port_id for PF. We only enumerate 0..N VFs
as 0..N ethdev port_id
Our intention with this patch is to control
the VF from the
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The following librte_ether functions already
work in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,
uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id,
uint16_t vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id,
uint16_t vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t port_id,
uint16_t vf, uint16_t tx_rate, uint64_t q_msk)
I have a bad feeling with these functions
dedicated to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the VF
is not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port id
to the VF from the host instead of having the couple
PF port id /
VF id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array
rte_eth_devices?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Hi Thomas,

The VF is not a port visible to DPDK, though, so it
shouldn't have a port id IMHO. DPDK can't actually do
anything
with it.
quoted
quoted
quoted
quoted
quoted
quoted
You say the contrary below.
Well, yes and no. The driver can manipulate things for the
VF, but DPDK
doesn't actually have a device that corresponds to the VF.
There are no PCI bar mappings for it, DPDK can't do RX and TX with
it etc.?
quoted
quoted
quoted
quoted
quoted
quoted
Very good point.
There are only few ethdev functions which are supported by
every drivers, like Rx/Tx and would not be available for VF
from PF
interface.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The PCI device for the VF is likely passed through to
a different VM and being used there. Unfortunately,
the VF still needs certain things done for it by the
PF, so if the PF is under DPDK control, it needs to
provide the functionality to assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the mailbox
things?
quoted
quoted
quoted
quoted
quoted
quoted
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want to
be sure that we are
ok with the results of that. Suppose we do create ethdevs
for the VFs controlled by the PF. Does the new VF get
counted in the
rte_eth_dev_count() value (I assume yes)? How are apps meant
to use the port? Do they have to put in a special case when
iterating through all the port ids to check that it's not a
pseudo port that can't do anything. None of the standard
ethdev calls from an app will work on it, you can't
configure nb rx/tx queues on it, you can't start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their supported
API would be quite different. I was thinking that in the
future you could add most of the configuration functions
through the VF
mailbox.
quoted
quoted
quoted
quoted
But the Intel mailbox currently support only some special
configurations which are not supported by other devices even
its own VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx
control register", it becomes clear it is really specific
and has nothing to do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are
aware of the underlying device and driver. So we can
directly include a header from the driver. I suggest to
retrieve a handler for the device which is not a port id and
will allow to call ixgbe functions
directly.
quoted
quoted
quoted
quoted
It could be achieved by adding an ethdev function like discussed
here:
quoted
quoted
quoted
quoted
quoted
quoted
	http://dpdk.org/ml/archives/dev/2016-
September/047392.html
quoted
quoted
quoted
quoted
quoted
quoted
I have been reading the net/vhost mail thread above. The
following quote
is from this thread.
quoted
"It means I would be in favor of introducing API in drivers
for very specific
features."
quoted
At present all the PMD functions are accessed through the
eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD (similar
to a driver
ioctl API) which can be accessed through a generic API in the ethdev?

Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a
handler (an opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the specific
ixgbe function, passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void**
pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing
driver
specific functions.
quoted
Using the pmd_handle the driver specific functions can be called
(without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the
following
patch?
quoted
[PATCH] net/vhost: Add function to retreive the 'vid' for a given
port id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving the
structs from the driver via rte_eth_devices?
Looking at the code in rte_eth_devices[]

struct rte_eth_dev  rte_eth_devices[RTE_MAX_ETHPORTS];

struct rte_eth_dev {

...

const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */

...

 void *pmd_ops;  /** < exported PMD specific functions */

}

The PMD functions are only accessible at present if they are in struct
eth_dev_ops.
quoted
Adding a pmd_ops field to struct rte_eth_dev {} makes the PMD functions
accessible and is a simpler solution than using
rte_eth_dev_get_pmd_handle() to get access to the PMD functions.
quoted
Regards,
Why would an ops structure be needed? If it's a private API for a driver,
there should be no need for function pointers, and instead the driver can
define regular functions in it's header file, no?

/Bruce
The driver functions were static, I have made them public and added them to the rte_pmd_ixgbe.h file, and it works.  These functions will also need to be added to the rte_pmd_ixgbe_version.map file, previously there were no public functions.

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Ananyev, Konstantin <hidden>
Date: 2016-09-28 11:23:42

Hi lads,
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Iremonger, Bernard
Sent: Tuesday, September 27, 2016 3:13 PM
To: Richardson, Bruce <redacted>
Cc: Thomas Monjalon <redacted>; dev@dpdk.org; Jerin Jacob <redacted>; Shah, Rahul
R [off-list ref]; Lu, Wenzhuo [off-list ref]; azelezniak [off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF management

Hi Bruce,

<snip>
quoted
quoted
quoted
quoted
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add
API's for VF management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas
Monjalon
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific
functions
here?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It can be generic(PF/VF) function indexed
only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as
rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In
Thunderx PMD, We are not exposing a
separate port_id for PF. We only enumerate
0..N VFs as 0..N ethdev port_id
Our intention with this patch is to control
the VF from the
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The following librte_ether functions already
work in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,
uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id,
uint16_t vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id,
uint16_t vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t
port_id, uint16_t vf, uint16_t tx_rate,
uint64_t q_msk)
I have a bad feeling with these functions
dedicated to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the
VF is not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a port
id to the VF from the host instead of having the
couple PF port id /
VF id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array
rte_eth_devices?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Hi Thomas,

The VF is not a port visible to DPDK, though, so it
shouldn't have a port id IMHO. DPDK can't actually
do anything
with it.
quoted
quoted
quoted
quoted
quoted
quoted
You say the contrary below.
Well, yes and no. The driver can manipulate things for
the VF, but DPDK
doesn't actually have a device that corresponds to the VF.
There are no PCI bar mappings for it, DPDK can't do RX and
TX with
it etc.?
quoted
quoted
quoted
quoted
quoted
quoted
Very good point.
There are only few ethdev functions which are supported by
every drivers, like Rx/Tx and would not be available for
VF from PF
interface.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The PCI device for the VF is likely passed through
to a different VM and being used there.
Unfortunately, the VF still needs certain things
done for it by the PF, so if the PF is under DPDK
control, it needs to provide the functionality to
assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the
mailbox
things?
quoted
quoted
quoted
quoted
quoted
quoted
So you can manage the VF from the PF with a simple port id.
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want
to be sure that we are
ok with the results of that. Suppose we do create ethdevs
for the VFs controlled by the PF. Does the new VF get
counted in the
rte_eth_dev_count() value (I assume yes)? How are apps
meant to use the port? Do they have to put in a special
case when iterating through all the port ids to check that
it's not a pseudo port that can't do anything. None of the
standard ethdev calls from an app will work on it, you
can't configure nb rx/tx queues on it, you can't start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their supported
API would be quite different. I was thinking that in the
future you could add most of the configuration functions
through the VF
mailbox.
quoted
quoted
quoted
quoted
But the Intel mailbox currently support only some special
configurations which are not supported by other devices
even its own VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx
control register", it becomes clear it is really specific
and has nothing to do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are
aware of the underlying device and driver. So we can
directly include a header from the driver. I suggest to
retrieve a handler for the device which is not a port id
and will allow to call ixgbe functions
directly.
quoted
quoted
quoted
quoted
It could be achieved by adding an ethdev function like
discussed
here:
quoted
quoted
quoted
quoted
quoted
quoted
	http://dpdk.org/ml/archives/dev/2016-
September/047392.html
quoted
quoted
quoted
quoted
quoted
quoted
I have been reading the net/vhost mail thread above. The
following quote
is from this thread.
quoted
"It means I would be in favor of introducing API in drivers
for very specific
features."
quoted
At present all the PMD functions are accessed through the
eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD
(similar to a driver
ioctl API) which can be accessed through a generic API in the ethdev?

Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve a
handler (an opaque pointer on the device struct) from the port id.
Then you can include rte_ixgbe.h and directly call the
specific ixgbe function, passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void**
pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing
driver
specific functions.
quoted
Using the pmd_handle the driver specific functions can be called
(without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the
following
patch?
quoted
[PATCH] net/vhost: Add function to retreive the 'vid' for a
given port id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving
the structs from the driver via rte_eth_devices?
Looking at the code in rte_eth_devices[]

struct rte_eth_dev  rte_eth_devices[RTE_MAX_ETHPORTS];

struct rte_eth_dev {

...

const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */

...

 void *pmd_ops;  /** < exported PMD specific functions */

}

The PMD functions are only accessible at present if they are in
struct
eth_dev_ops.
quoted
Adding a pmd_ops field to struct rte_eth_dev {} makes the PMD
functions
accessible and is a simpler solution than using
rte_eth_dev_get_pmd_handle() to get access to the PMD functions.
quoted
Regards,
Why would an ops structure be needed? If it's a private API for a
driver, there should be no need for function pointers, and instead the
driver can define regular functions in it's header file, no?

/Bruce
The driver functions were static, I have made them public and added them to the rte_pmd_ixgbe.h file, and it works.  These functions
will also need to be added to the rte_pmd_ixgbe_version.map file, previously there were no public functions.
Sorry for being late in the discussion, but I have a question:
If we  this way (force user to include driver specific headers and call driver specific functions),
how you guys plan to make this functionality available for multiple driver types.
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?

Konstantin
Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-28 12:31:54

Hi Bruce, Konstantin,

<snip>
Subject: RE: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

Hi lads,
quoted
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Iremonger,
Bernard
Sent: Tuesday, September 27, 2016 3:13 PM
To: Richardson, Bruce <redacted>
Cc: Thomas Monjalon <redacted>; dev@dpdk.org;
Jerin
quoted
Jacob [off-list ref]; Shah, Rahul R
[off-list ref]; Lu, Wenzhuo [off-list ref];
azelezniak [off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for
VF management

Hi Bruce,

<snip>
quoted
quoted
quoted
quoted
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add
API's for VF management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon
[mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas
Monjalon
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific
functions
here?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It can be generic(PF/VF) function
indexed only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as
rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In
Thunderx PMD, We are not exposing a
separate port_id for PF. We only
enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to
control the VF from the
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The following librte_ether functions
already work in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,
uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id,
uint16_t vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id,
uint16_t vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t
port_id, uint16_t vf, uint16_t tx_rate,
uint64_t q_msk)
I have a bad feeling with these functions
dedicated to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port ID.
When the VF is used in a VM the port ID of the
VF is not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a
port id to the VF from the host instead of
having the couple PF port id /
VF id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array
rte_eth_devices?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Hi Thomas,

The VF is not a port visible to DPDK, though, so
it shouldn't have a port id IMHO. DPDK can't
actually do anything
with it.
quoted
quoted
quoted
quoted
quoted
quoted
You say the contrary below.
Well, yes and no. The driver can manipulate things for
the VF, but DPDK
doesn't actually have a device that corresponds to the VF.
There are no PCI bar mappings for it, DPDK can't do RX
and TX with
it etc.?
quoted
quoted
quoted
quoted
quoted
quoted
Very good point.
There are only few ethdev functions which are supported
by every drivers, like Rx/Tx and would not be available
for VF from PF
interface.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The PCI device for the VF is likely passed through
to a different VM and being used there.
Unfortunately, the VF still needs certain things
done for it by the PF, so if the PF is under DPDK
control, it needs to provide the functionality to
assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the
mailbox
things?
quoted
quoted
quoted
quoted
quoted
quoted
So you can manage the VF from the PF with a simple port
id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want
to be sure that we are
ok with the results of that. Suppose we do create
ethdevs for the VFs controlled by the PF. Does the new
VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps
meant to use the port? Do they have to put in a special
case when iterating through all the port ids to check
that it's not a pseudo port that can't do anything. None
of the standard ethdev calls from an app will work on
it, you can't configure nb rx/tx queues on it, you can't
start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their
supported API would be quite different. I was thinking
that in the future you could add most of the
configuration functions through the VF
mailbox.
quoted
quoted
quoted
quoted
But the Intel mailbox currently support only some
special configurations which are not supported by other
devices even its own VF device (except setting MAC address).
And when I read "set drop enable bit in the VF split rx
control register", it becomes clear it is really
specific and has nothing to do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are
aware of the underlying device and driver. So we can
directly include a header from the driver. I suggest to
retrieve a handler for the device which is not a port id
and will allow to call ixgbe functions
directly.
quoted
quoted
quoted
quoted
It could be achieved by adding an ethdev function like
discussed
here:
quoted
quoted
quoted
quoted
quoted
quoted
	http://dpdk.org/ml/archives/dev/2016-
September/047392.html
quoted
quoted
quoted
quoted
quoted
quoted
I have been reading the net/vhost mail thread above. The
following quote
is from this thread.
quoted
"It means I would be in favor of introducing API in
drivers for very specific
features."
quoted
At present all the PMD functions are accessed through the
eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD
(similar to a driver
ioctl API) which can be accessed through a generic API in the
ethdev?
quoted
quoted
quoted
quoted
quoted
quoted
Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve
a handler (an opaque pointer on the device struct) from the port
id.
quoted
quoted
quoted
quoted
quoted
quoted
Then you can include rte_ixgbe.h and directly call the
specific ixgbe function, passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to work.

I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void**
pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing
driver
specific functions.
quoted
Using the pmd_handle the driver specific functions can be
called (without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the
following
patch?
quoted
[PATCH] net/vhost: Add function to retreive the 'vid' for a
given port id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving
the structs from the driver via rte_eth_devices?
Looking at the code in rte_eth_devices[]

struct rte_eth_dev  rte_eth_devices[RTE_MAX_ETHPORTS];

struct rte_eth_dev {

...

const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD
*/

...

 void *pmd_ops;  /** < exported PMD specific functions */

}

The PMD functions are only accessible at present if they are in
struct
eth_dev_ops.
quoted
Adding a pmd_ops field to struct rte_eth_dev {} makes the PMD
functions
accessible and is a simpler solution than using
rte_eth_dev_get_pmd_handle() to get access to the PMD functions.
quoted
Regards,
Why would an ops structure be needed? If it's a private API for a
driver, there should be no need for function pointers, and instead
the driver can define regular functions in it's header file, no?

/Bruce
The driver functions were static, I have made them public and added
them to the rte_pmd_ixgbe.h file, and it works.  These functions will also
need to be added to the rte_pmd_ixgbe_version.map file, previously there
were no public functions.

Sorry for being late in the discussion, but I have a question:
If we  this way (force user to include driver specific headers and call driver
specific functions), how you guys plan to make this functionality available for
multiple driver types.
From discussion with Bernard  understand that customers would need similar
functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would
provide some s of abstraction?
Basically their own version of rte_ethdev?

Konstantin
Adding the pmd_ops field to struct eth_devops {} discussed previously in this email thread will allow driver specific functions for multiple drivers and will get rid of the driver specific header file rte_pmd_driver.h. 

Regards,

Bernard.


 

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Richardson, Bruce <hidden>
Date: 2016-09-28 13:01:08

-----Original Message-----
From: Ananyev, Konstantin
Sent: Wednesday, September 28, 2016 12:24 PM
To: Iremonger, Bernard <redacted>; Richardson, Bruce
[off-list ref]
Cc: Thomas Monjalon <redacted>; dev@dpdk.org; Jerin Jacob
[off-list ref]; Shah, Rahul R [off-list ref];
Lu, Wenzhuo [off-list ref]; azelezniak [off-list ref]
Subject: RE: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

Hi lads,
quoted
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Iremonger,
Bernard
Sent: Tuesday, September 27, 2016 3:13 PM
To: Richardson, Bruce <redacted>
Cc: Thomas Monjalon <redacted>; dev@dpdk.org; Jerin
Jacob [off-list ref]; Shah, Rahul R
[off-list ref]; Lu, Wenzhuo [off-list ref];
azelezniak [off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for
VF management

Hi Bruce,

<snip>
quoted
quoted
quoted
quoted
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add
API's for VF management

2016-09-23 17:02, Iremonger, Bernard:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 09:53, Richardson, Bruce:
quoted
From: Thomas Monjalon
[mailto:thomas.monjalon@6wind.com]
quoted
2016-09-23 10:20, Bruce Richardson:
quoted
On Thu, Sep 22, 2016 at 07:04:37PM +0200, Thomas
Monjalon
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
2016-09-15 16:46, Iremonger, Bernard:
quoted
quoted
quoted
quoted
Do we really need to expose VF specific
functions
here?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It can be generic(PF/VF) function
indexed only through
port_id.
quoted
quoted
quoted
quoted
quoted
quoted
(example: as
rte_eth_dev_set_vlan_anti_spoof(uint8_t
port_id, uint8_t on)) For instance, In
Thunderx PMD, We are not exposing a
separate port_id for PF. We only
enumerate 0..N VFs as 0..N ethdev
port_id
Our intention with this patch is to
control the VF from the
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The following librte_ether functions
already work in a similar
way:
quoted
quoted
quoted
quoted
quoted
rte_eth_dev_set_vf_rxmode(uint8_t port_id,
uint16_t vf, uint16_t rx_mode, uint8_t on)

rte_eth_dev_set_vf_rx(uint8_t port_id,
uint16_t vf, uint8_t
on)

rte_eth_dev_set_vf_tx(uint8_t port_id,
uint16_t vf, uint8_t
on)

int rte_eth_set_vf_rate_limit(uint8_t
port_id, uint16_t vf, uint16_t tx_rate,
uint64_t q_msk)
I have a bad feeling with these functions
dedicated to VF from
PF.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Are we sure there is no other way?
I mean we just need to know the VF with a port
ID.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
When the VF is used in a VM the port ID of the
VF is not visible to
the PF.
quoted
quoted
quoted
I don't think there is another way to do this.
I don't understand why we could not assign a
port id to the VF from the host instead of
having the couple PF port id /
VF id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Can we enumerate all the VFs associated to a PF?
Then can we allocate them a port id in the array
rte_eth_devices?
quoted
quoted
quoted
quoted
quoted
quoted
quoted
Hi Thomas,

The VF is not a port visible to DPDK, though, so
it shouldn't have a port id IMHO. DPDK can't
actually do anything
with it.
quoted
quoted
quoted
quoted
quoted
quoted
You say the contrary below.
Well, yes and no. The driver can manipulate things for
the VF, but DPDK
doesn't actually have a device that corresponds to the VF.
There are no PCI bar mappings for it, DPDK can't do RX
and TX with
it etc.?
quoted
quoted
quoted
quoted
quoted
quoted
Very good point.
There are only few ethdev functions which are supported
by every drivers, like Rx/Tx and would not be available
for VF from PF
interface.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
The PCI device for the VF is likely passed through
to a different VM and being used there.
Unfortunately, the VF still needs certain things
done for it by the PF, so if the PF is under DPDK
control, it needs to provide the functionality to
assist
the VF.
quoted
quoted
quoted
quoted
Why not have a VF_from_PF driver which does the
mailbox
things?
quoted
quoted
quoted
quoted
quoted
quoted
So you can manage the VF from the PF with a simple
port id.
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
It really seems to be the cleanest design to me.
While I see your point, and it could work, I just want
to be sure that we are
ok with the results of that. Suppose we do create
ethdevs for the VFs controlled by the PF. Does the new
VF get counted in the
rte_eth_dev_count() value (I assume yes)? How are apps
meant to use the port? Do they have to put in a special
case when iterating through all the port ids to check
that it's not a pseudo port that can't do anything. None
of the standard ethdev calls from an app will work on
it, you can't configure nb rx/tx queues on it, you can't
start or
stop it, you can't do rx or tx on it, etc, etc.
quoted
quoted
Yes these devices would be special because their
supported API would be quite different. I was thinking
that in the future you could add most of the
configuration functions through the VF
mailbox.
quoted
quoted
quoted
quoted
But the Intel mailbox currently support only some
special configurations which are not supported by other
devices even its own VF device (except setting MAC
address).
quoted
quoted
quoted
quoted
quoted
quoted
quoted
quoted
And when I read "set drop enable bit in the VF split rx
control register", it becomes clear it is really
specific and has nothing to do in the generic ethdev API.
That's why it is a NACK.

When we want to use these very specific features we are
aware of the underlying device and driver. So we can
directly include a header from the driver. I suggest to
retrieve a handler for the device which is not a port id
and will allow to call ixgbe functions
directly.
quoted
quoted
quoted
quoted
It could be achieved by adding an ethdev function like
discussed
here:
quoted
quoted
quoted
quoted
quoted
quoted
	http://dpdk.org/ml/archives/dev/2016-
September/047392.html
quoted
quoted
quoted
quoted
quoted
quoted
I have been reading the net/vhost mail thread above. The
following quote
is from this thread.
quoted
"It means I would be in favor of introducing API in
drivers for very specific
features."
quoted
At present all the PMD functions are accessed through the
eth_dev_ops
structure, there are no PMD API's.
quoted
Is your proposal to add API(s) to the DPDK ixgbe PMD
(similar to a driver
ioctl API) which can be accessed through a generic API in the
ethdev?
quoted
quoted
quoted
quoted
quoted
quoted
Not exactly. I'm thinking about a PMD specific API.
The only ethdev API you need would be a function to retrieve
a handler (an opaque pointer on the device struct) from the
port id.
quoted
quoted
quoted
quoted
quoted
quoted
Then you can include rte_ixgbe.h and directly call the
specific ixgbe function, passing the device handler.
How does it sound?
I have been prototyping this proposed solution, it appears to
work.
quoted
quoted
quoted
quoted
quoted
I have added the following function:

int  rte_eth_dev_get_pmd_handle(uint8_t port_id, void**
pmd_handle);

The pmd_handle is a pointer to a dev_ops structure containing
driver
specific functions.
quoted
Using the pmd_handle the driver specific functions can be
called (without having them in struct eth_dev_ops)

Has this proposal been superseded by the discussion on the
following
patch?
quoted
[PATCH] net/vhost: Add function to retreive the 'vid' for a
given port id
Maybe, it can be superseded by this discussion, yes.
Bruce thinks we do not need rte_eth_dev_get_pmd_handle().
What is your opinion about using port_id directly and retrieving
the structs from the driver via rte_eth_devices?
Looking at the code in rte_eth_devices[]

struct rte_eth_dev  rte_eth_devices[RTE_MAX_ETHPORTS];

struct rte_eth_dev {

...

const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD
*/

...

 void *pmd_ops;  /** < exported PMD specific functions */

}

The PMD functions are only accessible at present if they are in
struct
eth_dev_ops.
quoted
Adding a pmd_ops field to struct rte_eth_dev {} makes the PMD
functions
accessible and is a simpler solution than using
rte_eth_dev_get_pmd_handle() to get access to the PMD functions.
quoted
Regards,
Why would an ops structure be needed? If it's a private API for a
driver, there should be no need for function pointers, and instead
the driver can define regular functions in it's header file, no?

/Bruce
The driver functions were static, I have made them public and added
them to the rte_pmd_ixgbe.h file, and it works.  These functions will
also need to be added to the rte_pmd_ixgbe_version.map file, previously
there were no public functions.

Sorry for being late in the discussion, but I have a question:
If we  this way (force user to include driver specific headers and call
driver specific functions), how you guys plan to make this functionality
available for multiple driver types.
From discussion with Bernard  understand that customers would need similar
functionality for i40e.
Does it mean that they'll have to re-implement this part of their code
again?
Or would have to create (and maintain) their own shim layer that would
provide some s of abstraction?
Basically their own version of rte_ethdev?

Konstantin
Yes, it's a problem. However, the concern right now is that this functionality is not generic across NICs, and will only be implemented for ixgbe and i40e. If it turns out to be implemented for a significant subset of DPDK PMDs, e.g. 4 or 5 drivers from at least two vendors, then I would expect the case to be made to "promote" this functionality to ethdev.

Does this sound reasonable. Any other thoughts?

/Bruce

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-28 13:03:21

2016-09-28 11:23, Ananyev, Konstantin:
If we  this way (force user to include driver specific headers and call driver specific functions),
how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which is implemented
only in 1 or 2 drivers? If the application tries to use it, we can imagine
that a specific range of hardware is expected.

I think it is an important question.
Previously we had the issue of having some API which are too specific
and need a rework to be used with other NICs. In order to avoid such
rework and API break, we can try to make them available in a driver-specific
or vendor-specific staging area, waiting for a later generalization.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Ananyev, Konstantin <hidden>
Date: 2016-09-28 13:26:39

-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
Sent: Wednesday, September 28, 2016 2:03 PM
To: Ananyev, Konstantin <redacted>
Cc: Iremonger, Bernard <redacted>; Richardson, Bruce <redacted>; dev@dpdk.org; Jerin
Jacob [off-list ref]; Shah, Rahul R [off-list ref]; Lu, Wenzhuo [off-list ref];
azelezniak [off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF management

2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers and
call driver specific functions), how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which is implemented only in 1 or 2 drivers? If the application tries to use
it, we can imagine that a specific range of hardware is expected.
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs for now, but different models/drivers).
Obviously users would like to have an ability to run their app on all HW from this subset without rebuilding/implementing the app.
I think it is an important question.
Previously we had the issue of having some API which are too specific and need a rework to be used with other NICs. In order to avoid
such rework and API break, we can try to make them available in a driver-specific or vendor-specific staging area, waiting for a later
generalization.
Could you remind me why you guys were that opposed to ioctl style approach?
It is not my favorite thing either, but it seems pretty generic way to handle such situations.

Konstantin
 

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-28 14:24:08

2016-09-28 13:26, Ananyev, Konstantin:
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers and
call driver specific functions), how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which is implemented only in 1 or 2 drivers? If the application tries to use
it, we can imagine that a specific range of hardware is expected.
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs for now, but different models/drivers).
Obviously users would like to have an ability to run their app on all HW from this subset without rebuilding/implementing the app.
quoted
I think it is an important question.
Previously we had the issue of having some API which are too specific and need a rework to be used with other NICs. In order to avoid
such rework and API break, we can try to make them available in a driver-specific or vendor-specific staging area, waiting for a later
generalization.
Could you remind me why you guys were that opposed to ioctl style approach?
It is not my favorite thing either, but it seems pretty generic way to handle such situations.
We prefer having well-defined functions instead of opaque ioctl-style encoding.
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for
features available on 2 drivers. Right? Example (trying to read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF id>);
instead of
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id);
Please confirm I understand what you are thinking about.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Ananyev, Konstantin <hidden>
Date: 2016-09-28 14:31:09

-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
Sent: Wednesday, September 28, 2016 3:24 PM
To: Ananyev, Konstantin <redacted>
Cc: Iremonger, Bernard <redacted>; Richardson, Bruce <redacted>; dev@dpdk.org; Jerin
Jacob [off-list ref]; Shah, Rahul R [off-list ref]; Lu, Wenzhuo [off-list ref];
azelezniak [off-list ref]
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF management

2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers and
call driver specific functions), how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which is
implemented only in 1 or 2 drivers? If the application tries to use it, we can imagine that a specific range of hardware is expected.
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs for now, but different models/drivers).
Obviously users would like to have an ability to run their app on all HW from this subset without rebuilding/implementing the app.
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In order to
avoid such rework and API break, we can try to make them available in a driver-specific or vendor-specific staging area, waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl style approach?
It is not my favorite thing either, but it seems pretty generic way to handle such situations.
We prefer having well-defined functions instead of opaque ioctl-style encoding.
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for features available on 2 drivers. Right?
Yes.
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF id>); instead of
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id);
Please confirm I understand what you are thinking about.
Yep, you read my mind correctly :)
Konstantin

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-28 14:48:34

<snip>
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for
VF management

2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers
and call driver specific functions), how you guys plan to make this
functionality available for multiple driver types.
quoted
quoted
quoted
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would
need similar functionality for i40e.
quoted
quoted
quoted
quoted
Does it mean that they'll have to re-implement this part of their code
again?
quoted
quoted
quoted
quoted
Or would have to create (and maintain) their own shim layer that
would provide some s of abstraction?
quoted
quoted
quoted
quoted
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which
is implemented only in 1 or 2 drivers? If the application tries to use it,
we can imagine that a specific range of hardware is expected.
quoted
quoted
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs
for now, but different models/drivers).
quoted
quoted
Obviously users would like to have an ability to run their app on all HW
from this subset without rebuilding/implementing the app.
quoted
quoted
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In order to
avoid such rework and API break, we can try to make them available
in a driver-specific or vendor-specific staging area, waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl style
approach?
quoted
quoted
It is not my favorite thing either, but it seems pretty generic way to
handle such situations.
quoted
We prefer having well-defined functions instead of opaque ioctl-style
encoding.
quoted
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for
features available on 2 drivers. Right?

Yes.
quoted
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF
id>); instead of
quoted
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id); Please confirm I understand
what you are thinking about.
Yep, you read my mind correctly :)
Konstantin
Adding the pmd_ops field to struct eth_devops {} discussed previously in this email thread will allow driver specific functions for multiple drivers and will get rid of the driver specific header file rte_pmd_driver.h.
Would this be an acceptable solution?

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-28 14:59:05

2016-09-28 14:30, Ananyev, Konstantin:
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers and
call driver specific functions), how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which is
implemented only in 1 or 2 drivers? If the application tries to use it, we can imagine that a specific range of hardware is expected.
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs for now, but different models/drivers).
Obviously users would like to have an ability to run their app on all HW from this subset without rebuilding/implementing the app.
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In order to
avoid such rework and API break, we can try to make them available in a driver-specific or vendor-specific staging area, waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl style approach?
It is not my favorite thing either, but it seems pretty generic way to handle such situations.
We prefer having well-defined functions instead of opaque ioctl-style encoding.
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for features available on 2 drivers. Right?
Yes.
quoted
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF id>); instead of
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id);
Please confirm I understand what you are thinking about.
Yep, you read my mind correctly :)
Both could coexist (if ioctl was accepted by community).
What about starting to implement the PMD functions and postpone
ioctl to later with a dedicated thread?

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-28 15:00:21

2016-09-28 14:48, Iremonger, Bernard:
<snip>
quoted
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for
VF management

2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers
and call driver specific functions), how you guys plan to make this
functionality available for multiple driver types.
quoted
quoted
quoted
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would
need similar functionality for i40e.
quoted
quoted
quoted
quoted
Does it mean that they'll have to re-implement this part of their code
again?
quoted
quoted
quoted
quoted
Or would have to create (and maintain) their own shim layer that
would provide some s of abstraction?
quoted
quoted
quoted
quoted
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which
is implemented only in 1 or 2 drivers? If the application tries to use it,
we can imagine that a specific range of hardware is expected.
quoted
quoted
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs
for now, but different models/drivers).
quoted
quoted
Obviously users would like to have an ability to run their app on all HW
from this subset without rebuilding/implementing the app.
quoted
quoted
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In order to
avoid such rework and API break, we can try to make them available
in a driver-specific or vendor-specific staging area, waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl style
approach?
quoted
quoted
It is not my favorite thing either, but it seems pretty generic way to
handle such situations.
quoted
We prefer having well-defined functions instead of opaque ioctl-style
encoding.
quoted
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for
features available on 2 drivers. Right?

Yes.
quoted
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF
id>); instead of
quoted
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id); Please confirm I understand
what you are thinking about.
Yep, you read my mind correctly :)
Konstantin
Adding the pmd_ops field to struct eth_devops {} discussed previously in this email thread will allow driver specific functions for multiple drivers and will get rid of the driver specific header file rte_pmd_driver.h.
Would this be an acceptable solution?
How pmd_ops would be different of eth_devops?

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-28 15:24:40

Hi Thomas,

<snip>
-----Original Message-----
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's for VF
management

2016-09-28 14:48, Iremonger, Bernard:
quoted
<snip>
quoted
quoted
Subject: Re: [dpdk-dev] [RFC PATCH v2 3/5] librte_ether: add API's
for VF management

2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific
headers and call driver specific functions), how you guys
plan to make this
functionality available for multiple driver types.
quoted
quoted
quoted
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers
would
need similar functionality for i40e.
quoted
quoted
quoted
quoted
Does it mean that they'll have to re-implement this part of
their code
again?
quoted
quoted
quoted
quoted
Or would have to create (and maintain) their own shim layer
that
would provide some s of abstraction?
quoted
quoted
quoted
quoted
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API
which is implemented only in 1 or 2 drivers? If the
application tries to use it,
we can imagine that a specific range of hardware is expected.
quoted
quoted
Yes, as I understand, it is a specific subset of supported HW
(just Inel NICs
for now, but different models/drivers).
quoted
quoted
Obviously users would like to have an ability to run their app
on all HW
from this subset without rebuilding/implementing the app.
quoted
quoted
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In
order to avoid such rework and API break, we can try to make
them available in a driver-specific or vendor-specific staging
area, waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl
style
approach?
quoted
quoted
It is not my favorite thing either, but it seems pretty generic
way to
handle such situations.
quoted
We prefer having well-defined functions instead of opaque
ioctl-style
encoding.
quoted
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl
service for
features available on 2 drivers. Right?

Yes.
quoted
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF
id>); instead of
quoted
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id); Please confirm I understand
what you are thinking about.
Yep, you read my mind correctly :)
Konstantin
Adding the pmd_ops field to struct eth_devops {} discussed previously in
this email thread will allow driver specific functions for multiple drivers and
will get rid of the driver specific header file rte_pmd_driver.h.
quoted
Would this be an acceptable solution?
How pmd_ops would be different of eth_devops?
There is not a lot of difference, however it would separate generic ethdev functions from driver specific functions.

Regards,

Bernard.

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Ananyev, Konstantin <hidden>
Date: 2016-09-28 16:52:43

2016-09-28 14:30, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers
and call driver specific functions), how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which
is implemented only in 1 or 2 drivers? If the application tries to use it, we can imagine that a specific range of hardware is
expected.
quoted
quoted
quoted
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs for now, but different models/drivers).
Obviously users would like to have an ability to run their app on all HW from this subset without rebuilding/implementing the
app.
quoted
quoted
quoted
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In order
to avoid such rework and API break, we can try to make them
available in a driver-specific or vendor-specific staging area,
waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl style approach?
It is not my favorite thing either, but it seems pretty generic way to handle such situations.
We prefer having well-defined functions instead of opaque ioctl-style encoding.
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for features available on 2 drivers. Right?
Yes.
quoted
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF id>); instead of
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id); Please confirm I understand
what you are thinking about.
Yep, you read my mind correctly :)
Both could coexist (if ioctl was accepted by community).
True.
What about starting to implement the PMD functions and postpone ioctl to later with a dedicated thread?
You mean something like:
- 16.11: implement rte_pmd_ixgbe_vf_ping()
- 17.02:
	a) implement rte_pmd_i40e_vf_ping()
	b) introduce ioctl PMD API
	c) make possible to vf_ping via ioctl API
?
If so, then it sounds like reasonable approach to me.
Though would be inserting to hear what other guys think.
Konstantin

Re: [RFC PATCH v2 3/5] librte_ether: add API's for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-28 18:02:24

2016-09-28 16:52, Ananyev, Konstantin:
quoted
2016-09-28 14:30, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 13:26, Ananyev, Konstantin:
quoted
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
quoted
2016-09-28 11:23, Ananyev, Konstantin:
quoted
If we  this way (force user to include driver specific headers
and call driver specific functions), how you guys plan to make this functionality available for multiple driver types.
Multiple drivers won't have exactly the same specific features.
But yes, there are some things common to several Intel NICs.
quoted
From discussion with Bernard  understand that customers would need similar functionality for i40e.
Does it mean that they'll have to re-implement this part of their code again?
Or would have to create (and maintain) their own shim layer that would provide some s of abstraction?
Basically their own version of rte_ethdev?
No definitive answer.
But we can argue the contrary: how to handle a generic API which
is implemented only in 1 or 2 drivers? If the application tries to use it, we can imagine that a specific range of hardware is
expected.
quoted
quoted
quoted
Yes, as I understand, it is a specific subset of supported HW (just Inel NICs for now, but different models/drivers).
Obviously users would like to have an ability to run their app on all HW from this subset without rebuilding/implementing the
app.
quoted
quoted
quoted
quoted
I think it is an important question.
Previously we had the issue of having some API which are too
specific and need a rework to be used with other NICs. In order
to avoid such rework and API break, we can try to make them
available in a driver-specific or vendor-specific staging area,
waiting for
a later generalization.
quoted
Could you remind me why you guys were that opposed to ioctl style approach?
It is not my favorite thing either, but it seems pretty generic way to handle such situations.
We prefer having well-defined functions instead of opaque ioctl-style encoding.
And it was not clear what is the benefit of ioctl.
Now I think I understand you would like to have a common ioctl service for features available on 2 drivers. Right?
Yes.
quoted
Example (trying to  read your mind):
	rte_ethdev_ioctl(port_id, <TLV encoding VF_PING service and VF id>); instead of
	rte_pmd_ixgbe_vf_ping(port_id, vf_id);
	rte_pmd_i40e_vf_ping(port_id, vf_id); Please confirm I understand
what you are thinking about.
Yep, you read my mind correctly :)
Both could coexist (if ioctl was accepted by community).
True.
quoted
What about starting to implement the PMD functions and postpone ioctl to later with a dedicated thread?
You mean something like:
- 16.11: implement rte_pmd_ixgbe_vf_ping()
- 17.02:
	a) implement rte_pmd_i40e_vf_ping()
	b) introduce ioctl PMD API
	c) make possible to vf_ping via ioctl API
?
If so, then it sounds like reasonable approach to me.
Though would be inserting to hear what other guys think.
Yes.
I would just add that we have to start a discussion thread to decide
wether we'll add an ioctl call in 17.02 or not.

[PATCH v5 1/3] librte_ether: add API for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-29 14:16:43

Add new API function to configure and manage VF's on a NIC.

add rte_eth_dev_set_vf_vlan_stripq function.

Signed-off-by: azelezniak <redacted>
Signed-off-by: Bernard Iremonger <redacted>
---
 lib/librte_ether/rte_ethdev.c          | 27 +++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 23 ++++++++++++++++++++++-
 lib/librte_ether/rte_ether_version.map |  6 ++++++
 3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 382c959..15e21ca 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2489,6 +2489,33 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
 						   vf_mask, vlan_on);
 }
 
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port_id, uint16_t vf, int on)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	uint16_t queues_per_pool;
+	uint32_t q;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	if (vf >= dev_info.max_vfs) {
+		RTE_PMD_DEBUG_TRACE("set VF vlan stripq: invalid VF %d\n", vf);
+		return -EINVAL;
+	}
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_strip_queue_set, -ENOTSUP);
+
+	queues_per_pool = dev_info.vmdq_queue_num/dev_info.max_vmdq_pools;
+
+	for (q = 0; q < queues_per_pool; q++)
+		(*dev->dev_ops->vlan_strip_queue_set)(dev, q + vf * queues_per_pool, on);
+	return 0;
+}
+
 int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
 					uint16_t tx_rate)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 96575e8..fb2be45 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3499,7 +3499,28 @@ rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
 				uint8_t vlan_on);
 
 /**
- * Set a traffic mirroring rule on an Ethernet device
+ * Enable/Disable vf vlan strip for all queues in a pool
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan strip on RX queues.
+ *    0 - Disable VF's vlan strip on RX queues.
+ * @param queues_per_pool
+ *    The number of queues per pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port, uint16_t vf, int on);
+
+/** Set a traffic mirroring rule on an Ethernet device
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 45ddf44..ae44074 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,9 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	rte_eth_dev_set_vf_vlan_stripq;
+} DPDK_16.07;
-- 
2.9.0

[PATCH v5 0/3] add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-29 14:16:44

This patchset contains new DPDK API's requested by AT&T for use
with the Virtual Function Daemon (VFD).

The need to configure and manage VF's on a NIC has grown to the
point where AT&T have devloped a DPDK based tool, VFD, to do this.

This patch set adds API extensions to DPDK VF configuration.

Eight new API's have been added for the Intel 82559 NIC.

Changes have been made to testpmd to facilitate testing of the new API's.
The testpmd documentation has been updated to document the testpmd changes.

Changes in v5:
rebase to latest master branch.
remove new API's from eth_dev_ops structure.
add public API's to ixgbe PMD.
revise testpmd commands for new API's

Changes in v4:
The rte_eth_dev_vf_ping API has been dropped as it is a work around for a bug.
The rte_eth_dev_set_vf_vlan_strip API has been renamed to
rte_eth_dev_set_vf_vlan_stripq.

Changes in v3:
rebase to latest master branch.
drop patches for callback functions
revise VF id checks in new librte_ether functions
revise testpmd commands for new API's

Changes in V2:
rebase to latest master branch.
fix compile  error with clang.

Bernard Iremonger (3):
  librte_ether: add API for VF management
  net/ixgbe: add API's for VF management
  app/test_pmd: add tests for new API's

 app/test-pmd/cmdline.c                      | 675 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  62 ++-
 drivers/net/ixgbe/Makefile                  |   2 +
 drivers/net/ixgbe/ixgbe_ethdev.c            | 200 +++++++++
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 162 +++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  12 +
 lib/librte_ether/rte_ethdev.c               |  27 ++
 lib/librte_ether/rte_ethdev.h               |  23 +-
 lib/librte_ether/rte_ether_version.map      |   6 +
 9 files changed, 1165 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/ixgbe/rte_pmd_ixgbe.h

-- 
2.9.0

[PATCH v5 2/3] net/ixgbe: add API's for VF management

From: Bernard Iremonger <hidden>
Date: 2016-09-29 14:16:46

Add API's to configure and manage VF's on an Intel 82559 NIC.

add rte_pmd_ixgbe_set_vf_vlan_anti_spoof function.
add rte_pmd_ixgbe_set_vf_mac_anti_spoof function.

Signed-off-by: azelezniak <redacted>

add rte_pmd_ixgbe_set_vf_vlan_insert function.
add rte_pmd_ixgbe_set_tx_loopback function.
add rte_pmd_ixgbe_set_all_queues_drop function.
add rte_pmd_ixgbe_set_vf_split_drop_en function.
add rte_pmd_ixgbe_set_vf_mac_addr function.

Signed-off-by: Bernard Iremonger <redacted>
---
 drivers/net/ixgbe/Makefile                  |   2 +
 drivers/net/ixgbe/ixgbe_ethdev.c            | 200 ++++++++++++++++++++++++++++
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 162 ++++++++++++++++++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  12 ++
 4 files changed, 376 insertions(+)
 create mode 100644 drivers/net/ixgbe/rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index a6c71f3..7493b8d 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -119,6 +119,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_bypass.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c
 endif
 
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include := rte_pmd_ixgbe.h
 
 # this lib depends upon:
 DEPDIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += lib/librte_eal lib/librte_ether
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 73a406b..beaebe1 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -72,6 +72,8 @@
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
 
+#include "rte_pmd_ixgbe.h"
+
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
  * least 8 bytes less than receive packet buffer size. This value is in units
@@ -4068,6 +4070,35 @@ ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
 	ixgbe_add_rar(dev, addr, 0, 0);
 }
 
+int
+rte_pmd_ixgbe_set_vf_mac_addr(uint8_t port, uint16_t vf, struct ether_addr *mac_addr)
+{
+	struct ixgbe_hw *hw;
+	struct ixgbe_vf_info *vfinfo;
+	int rar_entry;
+	uint8_t *new_mac = (uint8_t *)(mac_addr);
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+	rar_entry = hw->mac.num_rar_entries - (vf + 1);
+
+	if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
+		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, ETHER_ADDR_LEN);
+		return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV);
+	}
+	return -EINVAL;
+}
+
 static int
 ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
@@ -4661,6 +4692,175 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
 	return ret;
 }
 
+int
+rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw;
+	struct ixgbe_mac_info *mac;
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	mac = &hw->mac;
+
+	mac->ops.set_vlan_anti_spoofing(hw, on, vf);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw;
+	struct ixgbe_mac_info *mac;
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	mac = &hw->mac;
+	mac->ops.set_mac_anti_spoofing(hw, on, vf);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_vlan_insert(uint8_t port, uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw;
+	uint32_t ctrl;
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	if (vf >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+	if (on) {
+		ctrl = on;
+		ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
+	} else {
+		ctrl = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_tx_loopback(uint8_t port, uint8_t on)
+{
+	struct ixgbe_hw *hw;
+	uint32_t ctrl;
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+	/* enable or disable VMDQ loopback */
+	if (on)
+		ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
+	else
+		ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_all_queues_drop_en(uint8_t port, uint8_t on)
+{
+	struct ixgbe_hw *hw;
+	uint32_t reg_value;
+	int i;
+	int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	for (i = 0; i <= num_queues; i++) {
+		reg_value = IXGBE_QDE_WRITE |
+				(i << IXGBE_QDE_IDX_SHIFT) |
+				(on & IXGBE_QDE_ENABLE);
+		IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
+	}
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_set_vf_split_drop_en(uint8_t port, uint16_t vf, uint8_t on)
+{
+	struct ixgbe_hw *hw;
+	uint32_t reg_value;
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+
+	/* only support VF's 0 to 63 */
+	if ((vf >= dev_info.max_vfs) || (vf > 63))
+		return -EINVAL;
+
+	if (on > 1)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
+	if (on)
+		reg_value |= IXGBE_SRRCTL_DROP_EN;
+	else
+		reg_value &= ~IXGBE_SRRCTL_DROP_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
+
+	return 0;
+}
+
 #define IXGBE_MRCTL_VPME  0x01 /* Virtual Pool Mirroring. */
 #define IXGBE_MRCTL_UPME  0x02 /* Uplink Port Mirroring. */
 #define IXGBE_MRCTL_DPME  0x04 /* Downlink Port Mirroring. */
diff --git a/drivers/net/ixgbe/rte_pmd_ixgbe.h b/drivers/net/ixgbe/rte_pmd_ixgbe.h
new file mode 100644
index 0000000..918540b
--- /dev/null
+++ b/drivers/net/ixgbe/rte_pmd_ixgbe.h
@@ -0,0 +1,162 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file rte_pmd_ixgbe.h
+ * ixgbe PMD specific functions.
+ *
+ **/
+
+#ifndef _PMD_IXGBE_H_
+#define _PMD_IXGBE_H_
+
+#include <rte_ethdev.h>
+
+/**
+ * Set the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   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_ixgbe_set_vf_mac_addr(uint8_t port, uint16_t vf, struct ether_addr *mac_addr);
+
+/**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on);
+
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf, uint8_t on);
+
+/**
+ * Enable/Disable vf vlan insert
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - Enable VF's vlan insert.
+ *    0 - Disable VF's vlan insert
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_set_vf_vlan_insert(uint8_t port, uint16_t vf,	uint8_t on);
+
+/**
+ * Enable/Disable tx loopback
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable tx loopback.
+ *    0 - Disable tx loopback.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_set_tx_loopback(uint8_t port, uint8_t on);
+
+/**
+ * set all queues drop enable bit
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - set the queue drop enable bit for all pools.
+ *    0 - reset the queue drop enable bit for all pools.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_set_all_queues_drop_en(uint8_t port, uint8_t on);
+
+/**
+ * set drop enable bit in the VF split rx control register
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    ID specifying VF.
+ * @param on
+ *    1 - set the drop enable bit in the split rx control register.
+ *    0 - reset the drop enable bit in the split rx control register.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+
+int rte_pmd_ixgbe_set_vf_split_drop_en(uint8_t port, uint16_t vf, uint8_t on);
+#endif /* _PMD_IXGBE_H_ */
diff --git a/drivers/net/ixgbe/rte_pmd_ixgbe_version.map b/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
index ef35398..7677885 100644
--- a/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
+++ b/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
@@ -2,3 +2,15 @@ DPDK_2.0 {
 
 	local: *;
 };
+
+DPDK_16.11 {
+	global:
+
+	rte_pmd_ixgbe_set_all_queues_drop_en;
+	rte_pmd_ixgbe_set_tx_loopback;
+	rte_pmd_ixgbe_set_vf_mac_addr;
+	rte_pmd_ixgbe_set_vf_mac_anti_spoof;
+	rte_pmd_ixgbe_set_vf_split_drop_en;
+	rte_pmd_ixgbe_set_vf_vlan_anti_spoof;
+	rte_pmd_ixgbe_set_vf_vlan_insert;
+} DPDK_2.0;
-- 
2.9.0

[PATCH v5 3/3] app/test_pmd: add tests for new API's

From: Bernard Iremonger <hidden>
Date: 2016-09-29 14:16:49

add test for set vf vlan anti spoof
add test for set vf mac anti spoof
add test for set vf vlan stripq
add test for set vf vlan insert
add test for set tx loopback
add test for set all queues drop enable bit
add test for set vf split drop enable bit
add test for set vf mac address
add new API's to the testpmd guide

Signed-off-by: Bernard Iremonger <redacted>
---
 app/test-pmd/cmdline.c                      | 675 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  62 ++-
 2 files changed, 734 insertions(+), 3 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 17d238f..2847f94 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -87,6 +87,7 @@
 #ifdef RTE_LIBRTE_PMD_BOND
 #include <rte_eth_bond.h>
 #endif
+#include <rte_pmd_ixgbe.h>
 
 #include "testpmd.h"
 
@@ -10585,6 +10586,672 @@ cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
 	},
 };
 
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d\n", res->vf_id);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+	.f = cmd_set_vf_vlan_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_anti_spoof_set,
+		(void *)&cmd_vf_vlan_anti_spoof_vf,
+		(void *)&cmd_vf_vlan_anti_spoof_vlan,
+		(void *)&cmd_vf_vlan_anti_spoof_antispoof,
+		(void *)&cmd_vf_vlan_anti_spoof_port_id,
+		(void *)&cmd_vf_vlan_anti_spoof_vf_id,
+		(void *)&cmd_vf_vlan_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t antispoof;
+	uint8_t port_id;
+	uint32_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_mac_anti_spoof_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+	int ret;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+	.f = cmd_set_vf_mac_anti_spoof_parsed,
+	.data = NULL,
+	.help_str = "set vf mac antispoof port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_mac_anti_spoof_set,
+		(void *)&cmd_vf_mac_anti_spoof_vf,
+		(void *)&cmd_vf_mac_anti_spoof_mac,
+		(void *)&cmd_vf_mac_anti_spoof_antispoof,
+		(void *)&cmd_vf_mac_anti_spoof_port_id,
+		(void *)&cmd_vf_mac_anti_spoof_vf_id,
+		(void *)&cmd_vf_mac_anti_spoof_on_off,
+		NULL,
+	},
+};
+
+/* vf vlan strip queue configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_stripq_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t stripq;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_stripq =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 stripq, "stripq");
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_stripq_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_stripq_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_stripq_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_eth_dev_set_vf_vlan_stripq(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_stripq = {
+	.f = cmd_set_vf_vlan_stripq_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan stripq port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_stripq_set,
+		(void *)&cmd_vf_vlan_stripq_vf,
+		(void *)&cmd_vf_vlan_stripq_vlan,
+		(void *)&cmd_vf_vlan_stripq_stripq,
+		(void *)&cmd_vf_vlan_stripq_port_id,
+		(void *)&cmd_vf_vlan_stripq_vf_id,
+		(void *)&cmd_vf_vlan_stripq_on_off,
+		NULL,
+	},
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t vlan;
+	cmdline_fixed_string_t insert;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_insert_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_vlan_insert_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_vlan_insert_result *res = parsed_result;
+	int ret;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+	.f = cmd_set_vf_vlan_insert_parsed,
+	.data = NULL,
+	.help_str = "set vf vlan insert port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_vlan_insert_set,
+		(void *)&cmd_vf_vlan_insert_vf,
+		(void *)&cmd_vf_vlan_insert_vlan,
+		(void *)&cmd_vf_vlan_insert_insert,
+		(void *)&cmd_vf_vlan_insert_port_id,
+		(void *)&cmd_vf_vlan_insert_vf_id,
+		(void *)&cmd_vf_vlan_insert_on_off,
+		NULL,
+	},
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t tx;
+	cmdline_fixed_string_t loopback;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_tx_loopback_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_tx_loopback_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_tx_loopback_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_tx_loopback_result *res = parsed_result;
+	int ret;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid is_on %d\n", is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+	.f = cmd_set_tx_loopback_parsed,
+	.data = NULL,
+	.help_str = "set tx loopback port_id on|off",
+	.tokens = {
+		(void *)&cmd_tx_loopback_set,
+		(void *)&cmd_tx_loopback_tx,
+		(void *)&cmd_tx_loopback_loopback,
+		(void *)&cmd_tx_loopback_port_id,
+		(void *)&cmd_tx_loopback_on_off,
+		NULL,
+	},
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t queues;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_all_queues_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_all_queues_drop_en_result *res = parsed_result;
+	int ret = 0;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_all_queues_drop_en(res->port_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid is_on %d\n", is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+	.f = cmd_set_all_queues_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set all queues drop port_id on|off",
+	.tokens = {
+		(void *)&cmd_all_queues_drop_en_set,
+		(void *)&cmd_all_queues_drop_en_all,
+		(void *)&cmd_all_queues_drop_en_queues,
+		(void *)&cmd_all_queues_drop_en_drop,
+		(void *)&cmd_all_queues_drop_en_port_id,
+		(void *)&cmd_all_queues_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t split;
+	cmdline_fixed_string_t drop;
+	uint8_t port_id;
+	uint16_t vf_id;
+	cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_vf_split_drop_en_result,
+		 on_off, "on#off");
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_vf_split_drop_en_result *res = parsed_result;
+	int ret;
+	int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+	ret = rte_pmd_ixgbe_set_vf_split_drop_en(res->port_id, res->vf_id, is_on);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+	.f = cmd_set_vf_split_drop_en_parsed,
+	.data = NULL,
+	.help_str = "set vf split drop port_id vf_id on|off",
+	.tokens = {
+		(void *)&cmd_vf_split_drop_en_set,
+		(void *)&cmd_vf_split_drop_en_vf,
+		(void *)&cmd_vf_split_drop_en_split,
+		(void *)&cmd_vf_split_drop_en_drop,
+		(void *)&cmd_vf_split_drop_en_port_id,
+		(void *)&cmd_vf_split_drop_en_vf_id,
+		(void *)&cmd_vf_split_drop_en_on_off,
+		NULL,
+	},
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t vf;
+	cmdline_fixed_string_t mac;
+	cmdline_fixed_string_t addr;
+	uint8_t port_id;
+	uint16_t vf_id;
+	struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_set_vf_mac_addr_result,
+		 vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+	TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+		 mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_vf_mac_addr_result *res = parsed_result;
+	int ret;
+
+	ret = rte_pmd_ixgbe_set_vf_mac_addr(res->port_id, res->vf_id, &res->mac_addr);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid vf_id %d or mac_addr\n", res->vf_id);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+	.f = cmd_set_vf_mac_addr_parsed,
+	.data = NULL,
+	.help_str = "set vf mac addr port_id vf_id xx:xx:xx:xx:xx:xx",
+	.tokens = {
+		(void *)&cmd_set_vf_mac_addr_set,
+		(void *)&cmd_set_vf_mac_addr_vf,
+		(void *)&cmd_set_vf_mac_addr_mac,
+		(void *)&cmd_set_vf_mac_addr_addr,
+		(void *)&cmd_set_vf_mac_addr_port_id,
+		(void *)&cmd_set_vf_mac_addr_vf_id,
+		(void *)&cmd_set_vf_mac_addr_mac_addr,
+		NULL,
+	},
+};
+
+
+/* get PMD dev_ops handle */
+
+/* Common result structure for vf mac address */
+struct cmd_get_pmd_handle_result {
+	cmdline_fixed_string_t get;
+	cmdline_fixed_string_t pmd;
+	cmdline_fixed_string_t handle;
+	uint8_t port_id;
+};
+
+
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10739,6 +11406,14 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
 	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_stripq,
+	(cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+	(cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f87e0c2..145c425 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -473,6 +473,34 @@ For example, to change the port forwarding:
    RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03
    RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02
 
+set tx loopback
+~~~~~~~~~~~~~~~
+
+Enable/disable tx loopback::
+
+   testpmd> set tx loopback (port_id) (on|off)
+
+set drop enable
+~~~~~~~~~~~~~~~
+
+set drop enable bit for all queues::
+
+   testpmd> set all queues drop (port_id) (on|off)
+
+set split drop enable (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+set split drop enable bit for VF from PF::
+
+   testpmd> set vf split drop (port_id) (vf_id) (on|off)
+
+set mac antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set mac antispoof for a VF from the PF::
+
+   testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
@@ -487,6 +515,27 @@ Set the VLAN strip for a queue on a port::
 
    testpmd> vlan set stripq (on|off) (port_id,queue_id)
 
+vlan set stripq (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN strip for all queues in a pool for a VF from the PF::
+
+   testpmd> set vf vlan stripq (port_id) (vf_id) (on|off)
+
+vlan set insert (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN insert for a VF from the PF::
+
+   testpmd> set vf vlan insert (port_id) (vf_id) (on|off)
+
+vlan set antispoof (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN antispoof for a VF from the PF::
+
+   testpmd> set vf vlan antispoof (port_id) (vf_id) (on|off)
+
 vlan set filter
 ~~~~~~~~~~~~~~~
 
@@ -727,13 +776,20 @@ Remove a MAC address from a port::
 
    testpmd> mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)
 
-mac_addr add(for VF)
-~~~~~~~~~~~~~~~~~~~~
+mac_addr add (for VF)
+~~~~~~~~~~~~~~~~~~~~~
 
 Add an alternative MAC address for a VF to a port::
 
    testpmd> mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX)
 
+mac_addr set (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set the MAC address for a VF from the PF::
+
+   testpmd> set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)
+
 set port-uta
 ~~~~~~~~~~~~
 
-- 
2.9.0

Re: [PATCH v5 1/3] librte_ether: add API for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-29 14:30:08

2016-09-29 15:16, Bernard Iremonger:
Add new API function to configure and manage VF's on a NIC.

add rte_eth_dev_set_vf_vlan_stripq function.

Signed-off-by: azelezniak <redacted>
We need the full name of azelezniak.
Signed-off-by: Bernard Iremonger <redacted>
[...]
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port, uint16_t vf, int on);
Why keeping this function in ethdev?

I think it would be more consistent to have also existing VF functions
moving from ethdev to rte_pmd_ixgbe.h.
You cannot remove them, but you can create their ixgbe-specific version
and announce that the ethdev ones are deprecated.

Re: [PATCH v5 1/3] librte_ether: add API for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-29 15:16:51

Hi Thomas,

<snip>
Subject: Re: [dpdk-dev] [PATCH v5 1/3] librte_ether: add API for VF
management

2016-09-29 15:16, Bernard Iremonger:
quoted
Add new API function to configure and manage VF's on a NIC.

add rte_eth_dev_set_vf_vlan_stripq function.

Signed-off-by: azelezniak <redacted>
We need the full name of azelezniak.
It is Alex Zelezniak, I will update the commit messages.
quoted
Signed-off-by: Bernard Iremonger <redacted>
[...]
quoted
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port, uint16_t vf, int on);
Why keeping this function in ethdev?
This function is using an existing API in the eth_dev_ops structure.

dev->dev_ops->vlan_strip_queue_set

The vlan_strip_queue_set API is used by  the i40e, ixgbe and mlx5 PMD's.
I think it would be more consistent to have also existing VF functions moving
from ethdev to rte_pmd_ixgbe.h.
You cannot remove them, but you can create their ixgbe-specific version and
announce that the ethdev ones are deprecated.
There are 5 existing VF functions which are only used by ixgbe PMD at present.
It would make sense to create ixgbe-specific versions, however I think this should be done in a separate patchset.

Regards,

Bernard

 

Re: [PATCH v5 2/3] net/ixgbe: add API's for VF management

From: Reshma Pattan <hidden>
Date: 2016-09-29 16:11:33

Hi,


On 9/29/2016 3:16 PM, Bernard Iremonger wrote:
quoted hunk
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index a6c71f3..7493b8d 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -119,6 +119,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_bypass.c
  SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c
  endif
  
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include := rte_pmd_ixgbe.h
  
In correct config flag  CONFIG_RTE_LIBRTE_ACL , should be 
CONFIG_RTE_LIBRTE_IXGBE_PMD

Thanks,
Reshma

Re: [PATCH v5 2/3] net/ixgbe: add API's for VF management

From: Pattan, Reshma <hidden>
Date: 2016-09-29 16:16:15

Hi,
quoted hunk
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard Iremonger
Sent: Thursday, September 29, 2016 3:17 PM
To: dev@dpdk.org; Shah, Rahul R <redacted>; Lu, Wenzhuo
[off-list ref]; az5157@att.com
Cc: Iremonger, Bernard <redacted>; azelezniak
[off-list ref]
Subject: [dpdk-dev] [PATCH v5 2/3] net/ixgbe: add API's for VF management
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index
a6c71f3..7493b8d 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -119,6 +119,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) +=
ixgbe_bypass.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c  endif

+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include := rte_pmd_ixgbe.h
Config flag should be CONFIG_RTE_LIBRTE_IXGBE_PMD .

Thanks,
Reshma

Re: [PATCH v5 1/3] librte_ether: add API for VF management

From: Thomas Monjalon <hidden>
Date: 2016-09-29 16:19:25

2016-09-29 15:16, Iremonger, Bernard:
quoted
2016-09-29 15:16, Bernard Iremonger:
quoted
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port, uint16_t vf, int on);
Why keeping this function in ethdev?
This function is using an existing API in the eth_dev_ops structure.

dev->dev_ops->vlan_strip_queue_set

The vlan_strip_queue_set API is used by  the i40e, ixgbe and mlx5 PMD's.
OK but it was not used to control VF from PF.
This line:
	(*dev->dev_ops->vlan_strip_queue_set)(dev, q + vf * queues_per_pool, on);
seems Intel specific.
Please keep "VF from PF" outside of ethdev for 16.11.
quoted
I think it would be more consistent to have also existing VF functions moving
from ethdev to rte_pmd_ixgbe.h.
You cannot remove them, but you can create their ixgbe-specific version and
announce that the ethdev ones are deprecated.
There are 5 existing VF functions which are only used by ixgbe PMD at present.
It would make sense to create ixgbe-specific versions, however I think this should be done in a separate patchset.
Yes it can be a separate patchset for RC2 of course.

Re: [PATCH v5 2/3] net/ixgbe: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-29 16:30:32

Hi Reshma,
-----Original Message-----
From: Pattan, Reshma
Sent: Thursday, September 29, 2016 5:16 PM
To: Iremonger, Bernard <redacted>; dev@dpdk.org;
Shah, Rahul R [off-list ref]; Lu, Wenzhuo
[off-list ref]; az5157@att.com
Cc: Iremonger, Bernard <redacted>; azelezniak
[off-list ref]
Subject: RE: [dpdk-dev] [PATCH v5 2/3] net/ixgbe: add API's for VF
management

Hi,
quoted
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
Iremonger
quoted
Sent: Thursday, September 29, 2016 3:17 PM
To: dev@dpdk.org; Shah, Rahul R <redacted>; Lu, Wenzhuo
[off-list ref]; az5157@att.com
Cc: Iremonger, Bernard <redacted>; azelezniak
[off-list ref]
Subject: [dpdk-dev] [PATCH v5 2/3] net/ixgbe: add API's for VF
management
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index a6c71f3..7493b8d 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -119,6 +119,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) +=
ixgbe_bypass.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c
endif
quoted
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include := rte_pmd_ixgbe.h
Config flag should be CONFIG_RTE_LIBRTE_IXGBE_PMD .

Thanks,
Reshma
I will correct this in v6 patchset.

Regards,

Bernard.

Re: [PATCH v5 2/3] net/ixgbe: add API's for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-29 16:32:33

Hi Reshma,
-----Original Message-----
From: Pattan, Reshma
Sent: Thursday, September 29, 2016 5:11 PM
To: Iremonger, Bernard <redacted>; dev@dpdk.org;
Shah, Rahul R [off-list ref]; Lu, Wenzhuo
[off-list ref]; az5157@att.com
Cc: azelezniak <redacted>
Subject: Re: [dpdk-dev] [PATCH v5 2/3] net/ixgbe: add API's for VF
management

Hi,


On 9/29/2016 3:16 PM, Bernard Iremonger wrote:
quoted
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index a6c71f3..7493b8d 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -119,6 +119,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) +=
ixgbe_bypass.c
quoted
  SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c
  endif

+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include := rte_pmd_ixgbe.h
In correct config flag  CONFIG_RTE_LIBRTE_ACL , should be
CONFIG_RTE_LIBRTE_IXGBE_PMD

Thanks,
Reshma
I will correct this in v6 patchset.

Regards,

Bernard.

Re: [PATCH v5 1/3] librte_ether: add API for VF management

From: Iremonger, Bernard <hidden>
Date: 2016-09-29 16:38:13

Hi Thomas,
Subject: Re: [dpdk-dev] [PATCH v5 1/3] librte_ether: add API for VF
management

2016-09-29 15:16, Iremonger, Bernard:
quoted
quoted
2016-09-29 15:16, Bernard Iremonger:
quoted
+int
+rte_eth_dev_set_vf_vlan_stripq(uint8_t port, uint16_t vf, int
+on);
Why keeping this function in ethdev?
This function is using an existing API in the eth_dev_ops structure.

dev->dev_ops->vlan_strip_queue_set

The vlan_strip_queue_set API is used by  the i40e, ixgbe and mlx5 PMD's.
OK but it was not used to control VF from PF.
This line:
	(*dev->dev_ops->vlan_strip_queue_set)(dev, q + vf *
queues_per_pool, on); seems Intel specific.
Please keep "VF from PF" outside of ethdev for 16.11.
I will try calling  (*dev->dev_ops->vlan_strip_queue_set) from an ixgbe-specific function.
Will this be acceptable? 

Regards,

Bernard.
Next 15 of 15 remaining
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help