Discussion:
[dpdk-dev] [PATCH 00/31] Support VFD and DPDK PF + kernel VF on i40e
Wenzhuo Lu
2016-12-02 00:11:42 UTC
Permalink
1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK follows the interface
between kernel PF + kernel VF. We don't want to introduce too many new messages
between PF and VF. So this patch set adds some new APIs to control VFs directly
from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
12) set VF VLAN tag
13) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP. When PF receives mailbox
messages from VF, PF should call the callback provided by APP to know if they're
permitted to be processed.

2, Implement VF MAC address setting on VF.

3, Support the scenario DPDK PF + kernel VF.

Bernard Iremonger (8):
net/i40e: add set VF VLAN insert function
net/i40e: set VF broadcast mode from PF
net/i40e: set VF VLAN tag from PF
net/i40e: set VF VLAN filter from PF
app/testpmd: add command to test VF broadcast mode on i40e
app/testpmd: add command to test VF VLAN tag on i40e
app/testpmd: handle i40e in VF VLAN filter command
app/testpmd: initialize receive mode for VMDq

Chen Jing D(Mark) (6):
net/i40e: add VF vlan strip func
net/i40e: change version number to support Linux VF
net/i40e: return correct vsi_id
net/i40e: parse more VF parameter and configure
net/i40e: support Linux VF to configure IRQ link list
i40e: enhance in sanity check of mac

Ferruh Yigit (3):
net/i40e: set VF MAC from PF support
net/i40e: set VF MAC from VF support
net/i40e: fix VF MAC address assignment

Qi Zhang (4):
net/i40e: enable VF MTU change
rte: add APIs for VF stats get/reset
net/i40e: implement ops for VF stats get/reset
net/i40e: fix VF reset flow

Wenzhuo Lu (10):
net/i40e: support link status notification
net/i40e: add callback to user on VF to PF mbox msg
net/i40e: set VF MAC anti-spoofing from PF
net/i40e: set VF VLAN anti-spoofing from PF
net/i40e: set TX loopback from PF
net/i40e: set VF unicast promisc mode from PF
net/i40e: set VF multicast promisc mode from PF
app/testpmd: use VFD APIs on i40e
app/testpmd: use unicast promiscuous mode on i40e
app/testpmd: use multicast promiscuous mode on i40e

app/test-pmd/cmdline.c | 438 ++++++++++++++-
app/test-pmd/config.c | 17 +-
app/test-pmd/testpmd.c | 5 +-
app/test/Makefile | 8 +
app/test/test_pmd_i40e.c | 96 ++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 30 +
drivers/net/i40e/Makefile | 4 +-
drivers/net/i40e/i40e_ethdev.c | 835 +++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 5 +-
drivers/net/i40e/i40e_ethdev_vf.c | 81 ++-
drivers/net/i40e/i40e_pf.c | 415 ++++++++++++--
drivers/net/i40e/i40e_pf.h | 9 +-
drivers/net/i40e/rte_pmd_i40e.h | 287 ++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 17 +
lib/librte_ether/rte_ethdev.c | 47 ++
lib/librte_ether/rte_ethdev.h | 47 ++
16 files changed, 2255 insertions(+), 86 deletions(-)
create mode 100644 app/test/test_pmd_i40e.c
create mode 100644 drivers/net/i40e/rte_pmd_i40e.h
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:43 UTC
Permalink
Add an API to expose the ability, that PF can notify VF
when link status changes, to APP.
So if PF APP doesn't want to enable interruption but check
link status by itself, PF APP can let VF know link status
changed.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/Makefile | 4 ++-
drivers/net/i40e/i40e_ethdev.c | 28 +++++++++++++++
drivers/net/i40e/i40e_pf.c | 4 +--
drivers/net/i40e/i40e_pf.h | 4 ++-
drivers/net/i40e/rte_pmd_i40e.h | 58 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 6 ++++
6 files changed, 100 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/i40e/rte_pmd_i40e.h

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 13085fb..de7f384 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -1,6 +1,6 @@
# 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
@@ -111,6 +111,8 @@ ifeq ($(findstring RTE_MACHINE_CPUFLAG_SSE4_1,$(CFLAGS)),)
CFLAGS_i40e_rxtx_vec_sse.o += -msse4.1
endif

+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h

# this lib depends upon:
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..fda1454 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -62,6 +62,7 @@
#include "i40e_rxtx.h"
#include "i40e_pf.h"
#include "i40e_regs.h"
+#include "rte_pmd_i40e.h"

#define ETH_I40E_FLOATING_VEB_ARG "enable_floating_veb"
#define ETH_I40E_FLOATING_VEB_LIST_ARG "floating_veb_list"
@@ -9735,3 +9736,30 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+
+ 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;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
+
+ return 0;
+}
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index ddfc140..f70712b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -1,7 +1,7 @@
/*-
* 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
@@ -897,7 +897,7 @@
return ret;
}

-static void
+void
i40e_notify_vf_link_status(struct rte_eth_dev *dev, struct i40e_pf_vf *vf)
{
struct i40e_virtchnl_pf_event event;
diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index cddc45c..59bf2ee 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -1,7 +1,7 @@
/*-
* 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
@@ -123,5 +123,7 @@ void i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
uint8_t *msg, uint16_t msglen);
int i40e_pf_host_init(struct rte_eth_dev *dev);
int i40e_pf_host_uninit(struct rte_eth_dev *dev);
+void i40e_notify_vf_link_status(struct rte_eth_dev *dev,
+ struct i40e_pf_vf *vf);

#endif /* _I40E_PF_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
new file mode 100644
index 0000000..14852f2
--- /dev/null
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -0,0 +1,58 @@
+/*-
+ * 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_i40e.h
+ * i40e PMD specific functions.
+ *
+ **/
+
+#ifndef _PMD_I40E_H_
+#define _PMD_I40E_H_
+
+#include <rte_ethdev.h>
+
+/**
+ * Notify VF when PF link status changes.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * VF id.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if *vf* invalid.
+ */
+int rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf);
+
+#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef35398..4555446 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -2,3 +2,9 @@ DPDK_2.0 {

local: *;
};
+
+DPDK_17.02 {
+ global:
+
+ rte_pmd_i40e_ping_vfs;
+} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:44 UTC
Permalink
The callback asks the user application if it is allowed to
perform the mailbox messages.

If the return value from user is RTE_PMD_I40E_MB_EVENT_PROCEED
then continue. If ACK or NACK, do nothing and send
not_supported to VF.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 230 ++++++++++++++++++++++++++++++++++------
drivers/net/i40e/rte_pmd_i40e.h | 21 ++++
2 files changed, 216 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index f70712b..8b8a14f 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -55,6 +55,7 @@
#include "i40e_ethdev.h"
#include "i40e_rxtx.h"
#include "i40e_pf.h"
+#include "rte_pmd_i40e.h"

#define I40E_CFG_CRCSTRIP_DEFAULT 1

@@ -272,14 +273,23 @@
}

static void
-i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf, bool b_op)
{
struct i40e_virtchnl_version_info info;

info.major = I40E_DPDK_VERSION_MAJOR;
info.minor = I40E_DPDK_VERSION_MINOR;
- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
- I40E_SUCCESS, (uint8_t *)&info, sizeof(info));
+
+ if (b_op)
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+ I40E_SUCCESS,
+ (uint8_t *)&info,
+ sizeof(info));
+ else
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+ I40E_NOT_SUPPORTED,
+ (uint8_t *)&info,
+ sizeof(info));
}

static int
@@ -292,13 +302,20 @@
}

static int
-i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf, bool b_op)
{
struct i40e_virtchnl_vf_resource *vf_res = NULL;
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
uint32_t len = 0;
int ret = I40E_SUCCESS;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(vf,
+ I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
/* only have 1 VSI by default */
len = sizeof(struct i40e_virtchnl_vf_resource) +
I40E_DEFAULT_VF_VSI_NUM *
@@ -423,7 +440,8 @@
static int
i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_vsi *vsi = vf->vsi;
@@ -432,6 +450,13 @@
struct i40e_virtchnl_queue_pair_info *vc_qpi;
int i, ret = I40E_SUCCESS;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(vf,
+ I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP ||
msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci,
@@ -482,7 +507,8 @@
static int
i40e_pf_host_process_cmd_config_vsi_queues_ext(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_vsi *vsi = vf->vsi;
@@ -491,6 +517,14 @@
struct i40e_virtchnl_queue_pair_ext_info *vc_qpei;
int i, ret = I40E_SUCCESS;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (!msg || vc_vqcei->num_queue_pairs > vsi->nb_qps ||
vc_vqcei->num_queue_pairs > I40E_MAX_VSI_QP ||
msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei,
@@ -539,12 +573,21 @@

static int
i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
- uint8_t *msg, uint16_t msglen)
+ uint8_t *msg, uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_irq_map_info *irqmap =
(struct i40e_virtchnl_irq_map_info *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen < sizeof(struct i40e_virtchnl_irq_map_info)) {
PMD_DRV_LOG(ERR, "buffer too short");
ret = I40E_ERR_PARAM;
@@ -646,12 +689,21 @@
static int
i40e_pf_host_process_cmd_disable_queues(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_queue_select *q_sel =
(struct i40e_virtchnl_queue_select *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*q_sel)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -669,7 +721,8 @@
static int
i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -678,6 +731,14 @@
int i;
struct ether_addr *mac;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
memset(&filter, 0 , sizeof(struct i40e_mac_filter_info));

if (msg == NULL || msglen <= sizeof(*addr_list)) {
@@ -707,7 +768,8 @@
static int
i40e_pf_host_process_cmd_del_ether_address(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -715,6 +777,14 @@
int i;
struct ether_addr *mac;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*addr_list)) {
PMD_DRV_LOG(ERR, "delete_ether_address argument too short");
ret = I40E_ERR_PARAM;
@@ -739,7 +809,8 @@

static int
i40e_pf_host_process_cmd_add_vlan(struct i40e_pf_vf *vf,
- uint8_t *msg, uint16_t msglen)
+ uint8_t *msg, uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -747,6 +818,14 @@
int i;
uint16_t *vid;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_ADD_VLAN,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
PMD_DRV_LOG(ERR, "add_vlan argument too short");
ret = I40E_ERR_PARAM;
@@ -771,7 +850,8 @@
static int
i40e_pf_host_process_cmd_del_vlan(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -779,6 +859,14 @@
int i;
uint16_t *vid;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DEL_VLAN,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
PMD_DRV_LOG(ERR, "delete_vlan argument too short");
ret = I40E_ERR_PARAM;
@@ -803,7 +891,8 @@
i40e_pf_host_process_cmd_config_promisc_mode(
struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_promisc_info *promisc =
@@ -811,6 +900,14 @@
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
bool unicast = FALSE, multicast = FALSE;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*promisc)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -836,13 +933,20 @@
}

static int
-i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf, bool b_op)
{
i40e_update_vsi_stats(vf->vsi);

- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
- I40E_SUCCESS, (uint8_t *)&vf->vsi->eth_stats,
- sizeof(vf->vsi->eth_stats));
+ if (b_op)
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+ I40E_SUCCESS,
+ (uint8_t *)&vf->vsi->eth_stats,
+ sizeof(vf->vsi->eth_stats));
+ else
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+ I40E_NOT_SUPPORTED,
+ (uint8_t *)&vf->vsi->eth_stats,
+ sizeof(vf->vsi->eth_stats));

return I40E_SUCCESS;
}
@@ -851,12 +955,21 @@
i40e_pf_host_process_cmd_cfg_vlan_offload(
struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_offload_info *offload =
(struct i40e_virtchnl_vlan_offload_info *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*offload)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -877,12 +990,21 @@
static int
i40e_pf_host_process_cmd_cfg_pvid(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_pvid_info *tpid_info =
(struct i40e_virtchnl_pvid_info *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CFG_VLAN_PVID,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*tpid_info)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -923,6 +1045,8 @@
struct i40e_pf_vf *vf;
/* AdminQ will pass absolute VF id, transfer to internal vf id */
uint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id;
+ struct rte_pmd_i40e_mb_event_param cb_param;
+ bool b_op = TRUE;

if (vf_id > pf->vf_num - 1 || !pf->vfs) {
PMD_DRV_LOG(ERR, "invalid argument");
@@ -937,10 +1061,35 @@
return;
}

+ /**
+ * initialise structure to send to user application
+ * will return response from user in retval field
+ */
+ cb_param.retval = RTE_PMD_I40E_MB_EVENT_PROCEED;
+ cb_param.vfid = vf_id;
+ cb_param.msg_type = opcode;
+ cb_param.msg = (void *)msg;
+ cb_param.msglen = msglen;
+
+ /**
+ * Ask user application if we're allowed to perform those functions.
+ * If we get cb_param.retval == RTE_PMD_I40E_MB_EVENT_PROCEED,
+ * then business as usual.
+ * If RTE_PMD_I40E_MB_EVENT_NOOP_ACK or RTE_PMD_I40E_MB_EVENT_NOOP_NACK,
+ * do nothing and send not_supported to VF. As PF must send a response
+ * to VF and ACK/NACK is not defined.
+ */
+ _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
+ if (cb_param.retval != RTE_PMD_I40E_MB_EVENT_PROCEED) {
+ PMD_DRV_LOG(WARNING, "VF to PF message(%d) is not permitted!",
+ opcode);
+ b_op = FALSE;
+ }
+
switch (opcode) {
case I40E_VIRTCHNL_OP_VERSION :
PMD_DRV_LOG(INFO, "OP_VERSION received");
- i40e_pf_host_process_cmd_version(vf);
+ i40e_pf_host_process_cmd_version(vf, b_op);
break;
case I40E_VIRTCHNL_OP_RESET_VF :
PMD_DRV_LOG(INFO, "OP_RESET_VF received");
@@ -948,61 +1097,72 @@
break;
case I40E_VIRTCHNL_OP_GET_VF_RESOURCES:
PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received");
- i40e_pf_host_process_cmd_get_vf_resource(vf);
+ i40e_pf_host_process_cmd_get_vf_resource(vf, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received");
- i40e_pf_host_process_cmd_config_vsi_queues(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT:
PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES_EXT received");
i40e_pf_host_process_cmd_config_vsi_queues_ext(vf, msg,
- msglen);
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP:
PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received");
- i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
- i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
- i40e_notify_vf_link_status(dev, vf);
+ if (b_op) {
+ i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
+ i40e_notify_vf_link_status(dev, vf);
+ } else {
+ i40e_pf_host_send_msg_to_vf(
+ vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ }
break;
case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
- i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen);
+ i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS:
PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received");
- i40e_pf_host_process_cmd_add_ether_address(vf, msg, msglen);
+ i40e_pf_host_process_cmd_add_ether_address(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS:
PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received");
- i40e_pf_host_process_cmd_del_ether_address(vf, msg, msglen);
+ i40e_pf_host_process_cmd_del_ether_address(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_ADD_VLAN:
PMD_DRV_LOG(INFO, "OP_ADD_VLAN received");
- i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen);
+ i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_DEL_VLAN:
PMD_DRV_LOG(INFO, "OP_DEL_VLAN received");
- i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen);
+ i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received");
- i40e_pf_host_process_cmd_config_promisc_mode(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_GET_STATS:
PMD_DRV_LOG(INFO, "OP_GET_STATS received");
- i40e_pf_host_process_cmd_get_stats(vf);
+ i40e_pf_host_process_cmd_get_stats(vf, b_op);
break;
case I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD:
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received");
- i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen);
+ i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CFG_VLAN_PVID:
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_PVID received");
- i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen);
+ i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen, b_op);
break;
/* Don't add command supported below, which will
* return an error code.
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 14852f2..eb7a72b 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -42,6 +42,27 @@
#include <rte_ethdev.h>

/**
+ * Response sent back to i40e driver from user app after callback
+ */
+enum rte_pmd_i40e_mb_event_rsp {
+ RTE_PMD_I40E_MB_EVENT_NOOP_ACK, /**< skip mbox request and ACK */
+ RTE_PMD_I40E_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+ RTE_PMD_I40E_MB_EVENT_PROCEED, /**< proceed with mbox request */
+ RTE_PMD_I40E_MB_EVENT_MAX /**< max value of this enum */
+};
+
+/**
+ * Data sent to the user application when the callback is executed.
+ */
+struct rte_pmd_i40e_mb_event_param {
+ uint16_t vfid; /**< Virtual Function number */
+ uint16_t msg_type; /**< VF to PF message type, see i40e_virtchnl_ops */
+ uint16_t retval; /**< return value */
+ void *msg; /**< pointer to message */
+ uint16_t msglen; /**< length of the message */
+};
+
+/**
* Notify VF when PF link status changes.
*
* @param port
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:45 UTC
Permalink
Support enabling/disabling VF MAC anti-spoofing from
PF.
User can call the API on PF to enable/disable a specific
VF's MAC anti-spoofing.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 63 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 83 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index fda1454..0821734 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -9763,3 +9763,66 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return 0;
}
+
+int
+rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ struct i40e_hw *hw;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ /* Check if it has been already on or off */
+ if (vsi->info.valid_sections &
+ rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SECURITY_VALID)) {
+ if (on) {
+ if ((vsi->info.sec_flags &
+ I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
+ I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
+ return 0; /* already on */
+ } else {
+ if ((vsi->info.sec_flags &
+ I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
+ return 0; /* already off */
+ }
+ }
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+ if (on)
+ vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+ else
+ vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index eb7a72b..52319cf 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -76,4 +76,23 @@ struct rte_pmd_i40e_mb_event_param {
*/
int rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf);

+/**
+ * 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_i40e_set_vf_mac_anti_spoof(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 4555446..30efb08 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -7,4 +7,5 @@ DPDK_17.02 {
global:

rte_pmd_i40e_ping_vfs;
+ rte_pmd_i40e_set_vf_mac_anti_spoof;
} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:46 UTC
Permalink
Support enabling/disabling VF VLAN anti-spoofing from
PF.
User can call the API on PF to enable/disable a specific
VF's VLAN anti-spoofing.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 116 +++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/rte_pmd_i40e.h | 19 +++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
4 files changed, 135 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 0821734..ec863b9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -4418,6 +4418,7 @@ struct i40e_vsi *
vsi->max_macaddrs = I40E_NUM_MACADDR_MAX;
vsi->parent_vsi = uplink_vsi ? uplink_vsi : pf->main_vsi;
vsi->user_param = user_param;
+ vsi->vlan_anti_spoof_on = 0;
/* Allocate queues */
switch (vsi->type) {
case I40E_VSI_MAIN :
@@ -5761,17 +5762,35 @@ struct i40e_vsi *
uint16_t vlan_id, bool on)
{
uint32_t vid_idx, vid_bit;
+ struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+ struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+ int ret;

if (vlan_id > ETH_VLAN_ID_MAX)
return;

vid_idx = I40E_VFTA_IDX(vlan_id);
vid_bit = I40E_VFTA_BIT(vlan_id);
+ vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);

- if (on)
+ if (on) {
+ if (vsi->vlan_anti_spoof_on) {
+ ret = i40e_aq_add_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to add vlan filter");
+ }
vsi->vfta[vid_idx] |= vid_bit;
- else
+ } else {
+ if (vsi->vlan_anti_spoof_on) {
+ ret = i40e_aq_remove_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR,
+ "Failed to remove vlan filter");
+ }
vsi->vfta[vid_idx] &= ~vid_bit;
+ }
}

/**
@@ -9826,3 +9845,96 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+static int
+i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
+{
+ uint32_t j, k;
+ uint16_t vlan_id;
+ struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+ struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+ int ret;
+
+ for (j = 0; j < I40E_VFTA_SIZE; j++) {
+ if (!vsi->vfta[j])
+ continue;
+
+ for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
+ if (!(vsi->vfta[j] & (1 << k)))
+ continue;
+
+ vlan_id = j * I40E_UINT32_BIT_SIZE + k;
+ vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
+ if (add)
+ ret = i40e_aq_add_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ else
+ ret = i40e_aq_remove_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ if (ret != I40E_SUCCESS) {
+ PMD_DRV_LOG(ERR,
+ "Failed to add/rm vlan filter");
+ return ret;
+ }
+ }
+ }
+
+ return I40E_SUCCESS;
+}
+
+int
+rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ struct i40e_hw *hw;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ /* Check if it has been already on or off */
+ if (vsi->vlan_anti_spoof_on == on)
+ return 0; /* already on or off */
+
+ vsi->vlan_anti_spoof_on = on;
+ ret = i40e_add_rm_all_vlan_filter(vsi, on);
+ if (ret)
+ return ret;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+ if (on)
+ vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+ else
+ vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 298cef4..0db140b 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -300,6 +300,7 @@ struct i40e_vsi {
uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
uint16_t nb_msix; /* The max number of msix vector */
uint8_t enabled_tc; /* The traffic class enabled */
+ uint8_t vlan_anti_spoof_on; /* The VLAN anti-spoofing enabled */
struct i40e_bw_info bw_info; /* VSI bandwidth information */
};

diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 52319cf..c8736c8 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -95,4 +95,23 @@ int rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port,
uint16_t vf_id,
uint8_t 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 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_i40e_set_vf_vlan_anti_spoof(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 30efb08..fff6cf9 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -8,4 +8,5 @@ DPDK_17.02 {

rte_pmd_i40e_ping_vfs;
rte_pmd_i40e_set_vf_mac_anti_spoof;
+ rte_pmd_i40e_set_vf_vlan_anti_spoof;
} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:47 UTC
Permalink
Support enabling/disabling TX loopback from PF.
User can call the API on PF to enable/disable TX loopback
for all the PF and VFs.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 219 ++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 16 +++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 236 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index ec863b9..9fe9672 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -9938,3 +9938,222 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+static int
+i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
+{
+ struct i40e_mac_filter *f;
+ struct i40e_macvlan_filter *mv_f;
+ int i, vlan_num;
+ enum rte_mac_filter_type filter_type;
+ int ret = I40E_SUCCESS;
+
+ /* remove all the MACs */
+ TAILQ_FOREACH(f, &vsi->mac_list, next) {
+ vlan_num = vsi->vlan_num;
+ filter_type = f->mac_info.filter_type;
+ if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+ filter_type == RTE_MACVLAN_HASH_MATCH) {
+ if (vlan_num == 0) {
+ PMD_DRV_LOG(ERR,
+ "VLAN number shouldn't be 0\n");
+ return I40E_ERR_PARAM;
+ }
+ } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
+ filter_type == RTE_MAC_HASH_MATCH)
+ vlan_num = 1;
+
+ mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+ if (!mv_f) {
+ PMD_DRV_LOG(ERR, "failed to allocate memory");
+ return I40E_ERR_NO_MEMORY;
+ }
+
+ for (i = 0; i < vlan_num; i++) {
+ mv_f[i].filter_type = filter_type;
+ (void)rte_memcpy(&mv_f[i].macaddr,
+ &f->mac_info.mac_addr,
+ ETH_ADDR_LEN);
+ }
+ if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+ filter_type == RTE_MACVLAN_HASH_MATCH) {
+ ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+ &f->mac_info.mac_addr);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+ }
+
+ ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+
+ rte_free(mv_f);
+ ret = I40E_SUCCESS;
+ }
+
+ return ret;
+}
+
+static int
+i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
+{
+ struct i40e_mac_filter *f;
+ struct i40e_macvlan_filter *mv_f;
+ int i, vlan_num = 0;
+ int ret = I40E_SUCCESS;
+
+ /* restore all the MACs */
+ TAILQ_FOREACH(f, &vsi->mac_list, next) {
+ if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
+ (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
+ /**
+ * If vlan_num is 0, that's the first time to add mac,
+ * set mask for vlan_id 0.
+ */
+ if (vsi->vlan_num == 0) {
+ i40e_set_vlan_filter(vsi, 0, 1);
+ vsi->vlan_num = 1;
+ }
+ vlan_num = vsi->vlan_num;
+ } else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
+ (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
+ vlan_num = 1;
+
+ mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+ if (!mv_f) {
+ PMD_DRV_LOG(ERR, "failed to allocate memory");
+ return I40E_ERR_NO_MEMORY;
+ }
+
+ for (i = 0; i < vlan_num; i++) {
+ mv_f[i].filter_type = f->mac_info.filter_type;
+ (void)rte_memcpy(&mv_f[i].macaddr,
+ &f->mac_info.mac_addr,
+ ETH_ADDR_LEN);
+ }
+
+ if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+ f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
+ ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+ &f->mac_info.mac_addr);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+ }
+
+ ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+
+ rte_free(mv_f);
+ ret = I40E_SUCCESS;
+ }
+
+ return ret;
+}
+
+static int
+i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+{
+ struct i40e_vsi_context ctxt;
+ struct i40e_hw *hw;
+ int ret;
+
+ hw = I40E_VSI_TO_HW(vsi);
+
+ /* Use the FW API if FW >= v5.0 */
+ if (hw->aq.fw_maj_ver < 5) {
+ PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
+ return -ENOSYS;
+ }
+
+ /* Check if it has been already on or off */
+ if (vsi->info.valid_sections &
+ rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
+ if (on) {
+ if ((vsi->info.switch_id &
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
+ return 0; /* already on */
+ } else {
+ if ((vsi->info.switch_id &
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
+ return 0; /* already off */
+ }
+ }
+
+ /* remove all the MACs first */
+ ret = i40e_vsi_rm_mac_filter(vsi);
+ if (ret)
+ return ret;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+ if (on)
+ vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+ else
+ vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS) {
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+ return ret;
+ }
+
+ /* add all the MACs back */
+ ret = i40e_vsi_restore_mac_filter(vsi);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+int
+rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ uint16_t vf_id;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ /* setup PF TX loopback */
+ vsi = pf->main_vsi;
+ ret = i40e_vsi_set_tx_loopback(vsi, on);
+ if (ret)
+ return ret;
+
+ /* setup TX loopback for all the VFs */
+ if (!pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ ret = i40e_vsi_set_tx_loopback(vsi, on);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index c8736c8..3c65be4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -114,4 +114,20 @@ int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
uint16_t vf_id,
uint8_t on);

+/**
+ * Enable/Disable TX loopback on all the PF and VFs.
+ *
+ * @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_i40e_set_tx_loopback(uint8_t port,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index fff6cf9..3da04d3 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -9,4 +9,5 @@ DPDK_17.02 {
rte_pmd_i40e_ping_vfs;
rte_pmd_i40e_set_vf_mac_anti_spoof;
rte_pmd_i40e_set_vf_vlan_anti_spoof;
+ rte_pmd_i40e_set_tx_loopback;
} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-02 11:22:58 UTC
Permalink
Post by Wenzhuo Lu
Support enabling/disabling TX loopback from PF.
User can call the API on PF to enable/disable TX loopback
for all the PF and VFs.
---
drivers/net/i40e/i40e_ethdev.c | 219 ++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 16 +++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 236 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index ec863b9..9fe9672 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -9938,3 +9938,222 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
<...>
Post by Wenzhuo Lu
+static int
+i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+{
+ struct i40e_vsi_context ctxt;
+ struct i40e_hw *hw;
+ int ret;
+
+ hw = I40E_VSI_TO_HW(vsi);
+
+ /* Use the FW API if FW >= v5.0 */
+ if (hw->aq.fw_maj_ver < 5) {
+ PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
+ return -ENOSYS;
Checkpatch complains about ENOSYS usage:
WARNING:ENOSYS: ENOSYS means 'invalid syscall nr' and nothing else

What is intended error code here?
Wenzhuo Lu
2016-12-02 00:11:48 UTC
Permalink
Support enabling/disabling VF unicast promicscuous mode from
PF.
User can call the API on PF to enable/disable a specific
VF's unicast promiscuous mode.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 36 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 56 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 9fe9672..3aaa07d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10157,3 +10157,39 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ hw = I40E_VSI_TO_HW(vf->vsi);
+
+ ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vf->vsi->seid,
+ on, NULL, true);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set unicast promiscuous mode");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 3c65be4..4c98136 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -130,4 +130,23 @@ int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
int rte_pmd_i40e_set_tx_loopback(uint8_t port,
uint8_t on);

+/**
+ * Enable/Disable VF unicast promiscuous mode.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * VF on which to set.
+ * @param on
+ * 1 - Enable.
+ * 0 - Disable.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 3da04d3..24b78ce 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -10,4 +10,5 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_mac_anti_spoof;
rte_pmd_i40e_set_vf_vlan_anti_spoof;
rte_pmd_i40e_set_tx_loopback;
+ rte_pmd_i40e_set_vf_unicast_promisc;
} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-02 11:24:36 UTC
Permalink
Post by Wenzhuo Lu
Support enabling/disabling VF unicast promicscuous mode from
s/promicscuous/promiscuous
Post by Wenzhuo Lu
PF.
User can call the API on PF to enable/disable a specific
VF's unicast promiscuous mode.
<...>
Wenzhuo Lu
2016-12-02 00:11:49 UTC
Permalink
Support enabling/disabling VF multicast promicscuous mode from
PF.
User can call the API on PF to enable/disable a specific
VF's multicast promiscuous mode.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 36 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 56 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3aaa07d..728061d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10193,3 +10193,39 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ hw = I40E_VSI_TO_HW(vf->vsi);
+
+ ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid,
+ on, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set multicast promiscuous mode");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 4c98136..9091520 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -149,4 +149,23 @@ int rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port,
uint16_t vf_id,
uint8_t on);

+/**
+ * Enable/Disable VF multicast promiscuous mode.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * VF on which to set.
+ * @param on
+ * 1 - Enable.
+ * 0 - Disable.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 24b78ce..08d3028 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -11,4 +11,5 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_vlan_anti_spoof;
rte_pmd_i40e_set_tx_loopback;
rte_pmd_i40e_set_vf_unicast_promisc;
+ rte_pmd_i40e_set_vf_multicast_promisc;
} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-02 11:24:22 UTC
Permalink
Post by Wenzhuo Lu
Support enabling/disabling VF multicast promicscuous mode from
s/promicscuous/promiscuous
Post by Wenzhuo Lu
PF.
User can call the API on PF to enable/disable a specific
VF's multicast promiscuous mode.
---
<...>
Wenzhuo Lu
2016-12-02 00:11:50 UTC
Permalink
This patch implement mtu_set ops for i40e VF.

Signed-off-by: Qi Zhang <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index aa306d6..262c4c1 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -151,6 +151,7 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
+static int i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
static int
i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
static int
@@ -225,6 +226,7 @@ struct rte_i40evf_xstats_name_off {
.reta_query = i40evf_dev_rss_reta_query,
.rss_hash_update = i40evf_dev_rss_hash_update,
.rss_hash_conf_get = i40evf_dev_rss_hash_conf_get,
+ .mtu_set = i40evf_dev_mtu_set,
};

/*
@@ -2635,3 +2637,34 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,

return 0;
}
+
+static int
+i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct rte_eth_dev_data *dev_data = vf->dev_data;
+ uint32_t frame_size = mtu + ETHER_HDR_LEN
+ + ETHER_CRC_LEN + I40E_VLAN_TAG_SIZE;
+ int ret = 0;
+
+ /* check if mtu is within the allowed range */
+ if ((mtu < ETHER_MIN_MTU) || (frame_size > I40E_FRAME_SIZE_MAX))
+ return -EINVAL;
+
+ /* mtu setting is forbidden if port is start */
+ if (dev_data->dev_started) {
+ PMD_DRV_LOG(ERR,
+ "port %d must be stopped before configuration\n",
+ dev_data->port_id);
+ return -EBUSY;
+ }
+
+ if (frame_size > ETHER_MAX_LEN)
+ dev_data->dev_conf.rxmode.jumbo_frame = 1;
+ else
+ dev_data->dev_conf.rxmode.jumbo_frame = 0;
+
+ dev_data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+
+ return ret;
+}
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:51 UTC
Permalink
This patch add below two APIs so that VF statistics
can be get/clear from PF side.
rte_eth_vf_stats_get.
rte_eth_vf_stats_reset.

Signed-off-by: Qi Zhang <***@intel.com>
---
lib/librte_ether/rte_ethdev.c | 47 +++++++++++++++++++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 47 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index fde8112..03b4edf 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3270,3 +3270,50 @@ int rte_eth_dev_bypass_init(uint8_t port_id)
-ENOTSUP);
return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
}
+
+int
+rte_eth_vf_stats_get(uint8_t port_id,
+ uint16_t vf,
+ struct rte_eth_stats *stats)
+{
+ 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);
+
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_stats_get, -ENOTSUP);
+
+ if (vf >= dev_info.max_vfs) {
+ RTE_PMD_DEBUG_TRACE("Get VF Stats:port %d: "
+ "invalid vf id=%d\n", port_id, vf);
+ return -EINVAL;
+ }
+
+ return (*dev->dev_ops->vf_stats_get)(dev, vf, stats);
+}
+
+int
+rte_eth_vf_stats_reset(uint8_t port_id,
+ uint16_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);
+
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_stats_reset, -ENOTSUP);
+
+ if (vf >= dev_info.max_vfs) {
+ RTE_PMD_DEBUG_TRACE("Reset VF Stats:port %d: "
+ "invalid vf id=%d\n", port_id, vf);
+ return -EINVAL;
+ }
+
+ return (*dev->dev_ops->vf_stats_reset)(dev, vf);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..8b564ee 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1271,6 +1271,15 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
uint8_t vlan_on);
/**< @internal Set VF VLAN pool filter */

+typedef int (*eth_vf_stats_get)(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+/**< @internal Get VF statistics */
+
+typedef int (*eth_vf_stats_reset)(struct rte_eth_dev *dev,
+ uint16_t vf);
+/**< @internal Clear VF statistics */
+
typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t tx_rate);
@@ -1483,6 +1492,8 @@ 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_vf_stats_get vf_stats_get; /**< Get VF's statistics */
+ eth_vf_stats_reset vf_stats_reset; /**< Reset VF's statistics */
/** Add UDP tunnel port. */
eth_udp_tunnel_port_add_t udp_tunnel_port_add;
/** Del UDP tunnel port. */
@@ -4379,6 +4390,42 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);

+/**
+ * Get VF's statistics
+ *
+ * @param port_id
+ * pointer to port identifier of the device
+ * @param vf
+ * VF id
+ * @param stats
+ * A pointer to a structure of type *rte_eth_stats* to be filled with
+ * the values of device counters for the following set of statistics:
+ * - *ipackets* with the total of successfully received packets.
+ * - *opackets* with the total of successfully transmitted packets.
+ * - *ibytes* with the total of successfully received bytes.
+ * - *obytes* with the total of successfully transmitted bytes.
+ * - *ierrors* with the total of erroneous received packets.
+ * - *oerrors* with the total of failed transmitted packets.
+ * @return
+ * Zero if successful. Non-zero otherwise.
+ */
+int rte_eth_vf_stats_get(uint8_t port_id,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+
+/**
+ * Clear VF's statistics
+ *
+ * @param port_id
+ * pointer to port identifier of the device
+ * @param vf
+ * vf id
+ * @return
+ * Zero if successful. Non-zero otherwise.
+ */
+int rte_eth_vf_stats_reset(uint8_t port_id,
+ uint16_t vf);
+
#ifdef __cplusplus
}
#endif
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:52 UTC
Permalink
This patch implement vf_stats_get and vf_stats_reset ops for i40e.

Signed-off-by: Qi Zhang <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 64 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 728061d..319080e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -462,6 +462,13 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);

+static int i40e_vf_stats_get(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+
+static int i40e_vf_stats_reset(struct rte_eth_dev *dev,
+ uint16_t vf);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -554,6 +561,8 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
.get_eeprom = i40e_get_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set = i40e_dev_mtu_set,
+ .vf_stats_get = i40e_vf_stats_get,
+ .vf_stats_reset = i40e_vf_stats_reset,
};

/* store statistics names and its offset in stats structure */
@@ -10229,3 +10238,58 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+static int
+i40e_vf_stats_get(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_vsi *vsi;
+
+ int ret = 0;
+
+ if (pf->vf_num <= vf) {
+ PMD_DRV_LOG(ERR, "Invalid VF id %d\n", vf);
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf].vsi;
+
+ i40e_update_vsi_stats(vsi);
+
+ stats->ipackets = vsi->eth_stats.rx_unicast +
+ vsi->eth_stats.rx_multicast +
+ vsi->eth_stats.rx_broadcast;
+ stats->opackets = vsi->eth_stats.tx_unicast +
+ vsi->eth_stats.tx_multicast +
+ vsi->eth_stats.tx_broadcast;
+ stats->ibytes = vsi->eth_stats.rx_bytes;
+ stats->obytes = vsi->eth_stats.tx_bytes;
+ stats->ierrors = vsi->eth_stats.rx_discards;
+ stats->oerrors = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
+
+ return ret;
+}
+
+static int
+i40e_vf_stats_reset(struct rte_eth_dev *dev,
+ uint16_t vf)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_vsi *vsi;
+
+ int ret = 0;
+
+ if (pf->vf_num <= vf) {
+ PMD_DRV_LOG(ERR, "Invalid VF id %d\n", vf);
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf].vsi;
+
+ vsi->offset_loaded = false;
+ i40e_update_vsi_stats(vsi);
+
+ return ret;
+}
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:53 UTC
Permalink
Add missing step during VF reset: PF should
set I40E_VFGEN_RSTAT to ACTIVE at end of the
VF reset operation or VF driver may not able
to detect that reset is already completed.
This patch also remove the uneccessary enum
for vfr state.

Fixes: 4861cde46116 ("i40e: new poll mode driver")

Signed-off-by: Qi Zhang <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 6 ++++--
drivers/net/i40e/i40e_pf.h | 5 -----
2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 8b8a14f..2bc3355 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -139,7 +139,7 @@
abs_vf_id = vf_id + hw->func_caps.vf_base_id;

/* Notify VF that we are in VFR progress */
- I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_INPROGRESS);
+ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_INPROGRESS);

/*
* If require a SW VF reset, a VFLR interrupt will be generated,
@@ -220,7 +220,7 @@
}

/* Reset done, Set COMPLETE flag and clear reset bit */
- I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_COMPLETED);
+ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_COMPLETED);
val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
val &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
@@ -248,6 +248,8 @@
return -EFAULT;
}

+ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_VFACTIVE);
+
return ret;
}

diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index 59bf2ee..ada398b 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -48,11 +48,6 @@

#define I40E_DPDK_OFFSET 0x100

-enum i40e_pf_vfr_state {
- I40E_PF_VFR_INPROGRESS = 0,
- I40E_PF_VFR_COMPLETED = 1,
-};
-
/* DPDK pf driver specific command to VF */
enum i40e_virtchnl_ops_dpdk {
/*
--
1.9.3
Ferruh Yigit
2016-12-02 11:24:03 UTC
Permalink
Post by Wenzhuo Lu
Add missing step during VF reset: PF should
set I40E_VFGEN_RSTAT to ACTIVE at end of the
VF reset operation or VF driver may not able
to detect that reset is already completed.
This patch also remove the uneccessary enum
s/uneccessary/unnecessary
Post by Wenzhuo Lu
for vfr state.
Fixes: 4861cde46116 ("i40e: new poll mode driver")
missing cc, yes this is very new J
<...>
Wenzhuo Lu
2016-12-02 00:11:54 UTC
Permalink
Support setting VF MAC address from PF.
User can call the API on PF to set a speific VF's
MAC address.

Signed-off-by: Ferruh Yigit <***@intel.com>
---
app/test/Makefile | 8 +++
app/test/test_pmd_i40e.c | 96 +++++++++++++++++++++++++++++++
drivers/net/i40e/i40e_ethdev.c | 42 ++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 2 +
5 files changed, 167 insertions(+)
create mode 100644 app/test/test_pmd_i40e.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..b3f6ecb 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -199,6 +199,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev.c

SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c

+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += test_pmd_i40e.c
+
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)

@@ -228,6 +230,12 @@ endif
endif
endif

+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+ifeq ($(CONFIG_RTE_LIBRTE_I40E_PMD),y)
+LDLIBS += -lrte_pmd_i40e
+endif
+endif
+
ifeq ($(CONFIG_RTE_APP_TEST_RESOURCE_TAR),y)
LDLIBS += -larchive
endif
diff --git a/app/test/test_pmd_i40e.c b/app/test/test_pmd_i40e.c
new file mode 100644
index 0000000..c901e89
--- /dev/null
+++ b/app/test/test_pmd_i40e.c
@@ -0,0 +1,96 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_pmd_i40e.h>
+#include <rte_ethdev.h>
+
+#include "test.h"
+
+#define I40E_DRV_NAME "net_i40e"
+
+static struct ether_addr mac_addr = {
+ { 0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x00 }
+};
+
+static const int max_vfs = 3;
+
+static int
+test_i40e(void)
+{
+ struct rte_eth_dev_info dev_info;
+ struct ether_addr current_mac_addr;
+ uint8_t nb_ports;
+ uint8_t port;
+ int ret = 0;
+ int i;
+
+ nb_ports = rte_eth_dev_count();
+ printf("nb_ports=%d\n", nb_ports);
+
+ for (port = 0; port < nb_ports; port++) {
+ rte_eth_dev_info_get(port, &dev_info);
+
+ printf("%d: %s\n", port, dev_info.driver_name);
+
+ if (strcmp(dev_info.driver_name, I40E_DRV_NAME))
+ continue;
+
+ rte_eth_macaddr_get(port, &current_mac_addr);
+
+ printf("%d: mac address:", port);
+ for (i = 0; i < ETHER_ADDR_LEN - 1; i++)
+ printf("%x:", current_mac_addr.addr_bytes[i]);
+ printf("%x\n", current_mac_addr.addr_bytes[ETHER_ADDR_LEN - 1]);
+
+ for (i = 0; i < max_vfs; i++) {
+ if (i >= dev_info.max_vfs)
+ break;
+
+ mac_addr.addr_bytes[ETHER_ADDR_LEN - 2] = port + 1;
+ mac_addr.addr_bytes[ETHER_ADDR_LEN - 1] = i + 1;
+
+ ret = rte_pmd_i40e_set_vf_mac_addr(port, i, &mac_addr);
+ printf("port:%d vf:%d set mac %s\n",
+ port, i, ret ? "failed" : "succeed");
+ }
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(i40e_autotest, test_i40e);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 319080e..bfc9169 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10293,3 +10293,45 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
+ struct ether_addr *mac_addr)
+{
+ struct rte_eth_dev_info dev_info;
+ struct i40e_mac_filter *f;
+ struct rte_eth_dev *dev;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ struct i40e_pf *pf;
+ void *temp;
+
+ if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+ return -EINVAL;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs)
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ ether_addr_copy(mac_addr, &vf->mac_addr);
+
+ /* Remove all existing mac */
+ TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
+ i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
+
+ i40e_pf_host_vf_reset(vf, 1);
+
+ return 0;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 9091520..ca5e05a 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -168,4 +168,23 @@ int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
uint16_t vf_id,
uint8_t on);

+/**
+ * Set the VF MAC address.
+ *
+ * This will reset the vf.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf_id
+ * VF id.
+ * @param mac_addr
+ * VF MAC address.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
+ struct ether_addr *mac_addr);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 08d3028..64ba93a 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -12,4 +12,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_tx_loopback;
rte_pmd_i40e_set_vf_unicast_promisc;
rte_pmd_i40e_set_vf_multicast_promisc;
+ rte_pmd_i40e_set_vf_mac_addr;
+
} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-02 11:23:42 UTC
Permalink
Post by Wenzhuo Lu
Support setting VF MAC address from PF.
User can call the API on PF to set a speific VF's
s/speific/specific
Post by Wenzhuo Lu
MAC address.
<..>
Wenzhuo Lu
2016-12-02 00:11:55 UTC
Permalink
Support changing VF default MAC address.

Signed-off-by: Ferruh Yigit <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.h | 4 +++-
drivers/net/i40e/i40e_ethdev_vf.c | 48 +++++++++++++++++++++++++++++++++------
2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 0db140b..b687b0c 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -126,6 +126,7 @@ enum i40e_flxpld_layer_idx {
#define I40E_FLAG_FDIR (1ULL << 6)
#define I40E_FLAG_VXLAN (1ULL << 7)
#define I40E_FLAG_RSS_AQ_CAPABLE (1ULL << 8)
+#define I40E_FLAG_VF_MAC_BY_PF (1ULL << 9)
#define I40E_FLAG_ALL (I40E_FLAG_RSS | \
I40E_FLAG_DCB | \
I40E_FLAG_VMDQ | \
@@ -134,7 +135,8 @@ enum i40e_flxpld_layer_idx {
I40E_FLAG_HEADER_SPLIT_ENABLED | \
I40E_FLAG_FDIR | \
I40E_FLAG_VXLAN | \
- I40E_FLAG_RSS_AQ_CAPABLE)
+ I40E_FLAG_RSS_AQ_CAPABLE | \
+ I40E_FLAG_VF_MAC_BY_PF)

#define I40E_RSS_OFFLOAD_ALL ( \
ETH_RSS_FRAG_IPV4 | \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 262c4c1..cc2d03c 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -152,6 +152,8 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
static int i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+static void i40evf_set_default_mac_addr(struct rte_eth_dev *dev,
+ struct ether_addr *mac_addr);
static int
i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
static int
@@ -227,6 +229,7 @@ struct rte_i40evf_xstats_name_off {
.rss_hash_update = i40evf_dev_rss_hash_update,
.rss_hash_conf_get = i40evf_dev_rss_hash_conf_get,
.mtu_set = i40evf_dev_mtu_set,
+ .mac_addr_set = i40evf_set_default_mac_addr,
};

/*
@@ -888,19 +891,15 @@ struct rte_i40evf_xstats_name_off {
}

static void
-i40evf_del_mac_addr(struct rte_eth_dev *dev, uint32_t index)
+i40evf_del_mac_addr_by_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
{
struct i40e_virtchnl_ether_addr_list *list;
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
- struct rte_eth_dev_data *data = dev->data;
- struct ether_addr *addr;
uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_ether_addr_list) + \
sizeof(struct i40e_virtchnl_ether_addr)];
int err;
struct vf_cmd_info args;

- addr = &(data->mac_addrs[index]);
-
if (i40e_validate_mac_addr(addr->addr_bytes) != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Invalid mac:%x-%x-%x-%x-%x-%x",
addr->addr_bytes[0], addr->addr_bytes[1],
@@ -927,6 +926,17 @@ struct rte_i40evf_xstats_name_off {
return;
}

+static void
+i40evf_del_mac_addr(struct rte_eth_dev *dev, uint32_t index)
+{
+ struct rte_eth_dev_data *data = dev->data;
+ struct ether_addr *addr;
+
+ addr = &data->mac_addrs[index];
+
+ i40evf_del_mac_addr_by_addr(dev, addr);
+}
+
static int
i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
@@ -1261,10 +1271,12 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,

/* Store the MAC address configured by host, or generate random one */
p_mac_addr = (struct ether_addr *)(vf->vsi_res->default_mac_addr);
- if (is_valid_assigned_ether_addr(p_mac_addr)) /* Configured by host */
+ if (is_valid_assigned_ether_addr(p_mac_addr)) { /* Configured by host */
ether_addr_copy(p_mac_addr, (struct ether_addr *)hw->mac.addr);
- else
+ vf->flags |= I40E_FLAG_VF_MAC_BY_PF;
+ } else {
eth_random_addr(hw->mac.addr); /* Generate a random one */
+ }

/* If the PF host is not DPDK, set the interval of ITR0 to max*/
if (vf->version_major != I40E_DPDK_VERSION_MAJOR) {
@@ -2668,3 +2680,25 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,

return ret;
}
+
+static void
+i40evf_set_default_mac_addr(struct rte_eth_dev *dev,
+ struct ether_addr *mac_addr)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+ if (!is_valid_assigned_ether_addr(mac_addr)) {
+ PMD_DRV_LOG(ERR, "Tried to set invalid MAC address.");
+ return;
+ }
+
+ if (is_same_ether_addr(mac_addr, dev->data->mac_addrs))
+ return;
+
+ if (vf->flags & I40E_FLAG_VF_MAC_BY_PF)
+ return;
+
+ i40evf_del_mac_addr_by_addr(dev, dev->data->mac_addrs);
+
+ i40evf_add_mac_addr(dev, mac_addr, 0, 0);
+}
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:56 UTC
Permalink
Signed-off-by: Ferruh Yigit <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index cc2d03c..3b9a673 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1193,7 +1193,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
int i, err, bufsz;
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
- struct ether_addr *p_mac_addr;
uint16_t interval =
i40e_calc_itr_interval(I40E_QUEUE_ITR_INTERVAL_MAX);

@@ -1270,13 +1269,10 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
vf->vsi.adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);

/* Store the MAC address configured by host, or generate random one */
- p_mac_addr = (struct ether_addr *)(vf->vsi_res->default_mac_addr);
- if (is_valid_assigned_ether_addr(p_mac_addr)) { /* Configured by host */
- ether_addr_copy(p_mac_addr, (struct ether_addr *)hw->mac.addr);
+ if (is_valid_assigned_ether_addr((struct ether_addr *)hw->mac.addr))
vf->flags |= I40E_FLAG_VF_MAC_BY_PF;
- } else {
+ else
eth_random_addr(hw->mac.addr); /* Generate a random one */
- }

/* If the PF host is not DPDK, set the interval of ITR0 to max*/
if (vf->version_major != I40E_DPDK_VERSION_MAJOR) {
--
1.9.3
Ferruh Yigit
2016-12-02 11:24:53 UTC
Permalink
On 12/2/2016 12:11 AM, Wenzhuo Lu wrote:

Missing both Fixes and CC to stable.
---
<...>
Wenzhuo Lu
2016-12-02 00:11:57 UTC
Permalink
Add a function to configure vlan strip enable/disable for specific
SRIOV VF device.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 26 ++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 20 ++++++++++++++++++++
2 files changed, 46 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index bfc9169..b1d483b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10335,3 +10335,29 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return 0;
}
+
+/* Set vlan strip on/off for specific VF from host */
+int
+rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct i40e_pf *pf;
+ struct i40e_vsi *vsi;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf_id].vsi;
+
+ if (vsi)
+ return i40e_vsi_config_vlan_stripping(vsi, !!on);
+ else
+ return -EINVAL;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index ca5e05a..043ae62 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -187,4 +187,24 @@ int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
struct ether_addr *mac_addr);

+/**
+ * Enable/Disable vf vlan strip for all queues in a pool
+ *
+ * @param port
+ * 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.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENOTSUP) if hardware doesn't support this feature.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int
+rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
--
1.9.3
Ferruh Yigit
2016-12-02 11:25:14 UTC
Permalink
Post by Wenzhuo Lu
Add a function to configure vlan strip enable/disable for specific
SRIOV VF device.
For shared library compilation, this function also needs to be added to
rte_pmd_i40e_version.map file, otherwise throwing build error:

.../app/test-pmd/cmdline.c:(.text+0x79d4): undefined reference to
`rte_pmd_i40e_set_vf_vlan_stripq'
Post by Wenzhuo Lu
---
<...>
Wenzhuo Lu
2016-12-02 00:11:58 UTC
Permalink
Support inserting VF VLAN id from PF.
User can call the API on PF to insert a VLAN id to a
specific VF.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 53 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 +++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index b1d483b..a1aa469 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10361,3 +10361,56 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
else
return -EINVAL;
}
+
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+ uint16_t vlan_id)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ struct i40e_vsi *vsi;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+ pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ if (vf_id > pf->vf_num)
+ return -EINVAL;
+
+ if (vlan_id > 4095)
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
+ vsi->info.pvid = vlan_id;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 043ae62..8867e9c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -207,4 +207,23 @@ int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
int
rte_pmd_i40e_set_vf_vlan_stripq(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 vlan_id
+ * 0 - Disable VF's vlan insert.
+ * n - Enable; n is inserted as the vlan id.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+ uint16_t vlan_id);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 64ba93a..b55a7ca 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -13,5 +13,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_unicast_promisc;
rte_pmd_i40e_set_vf_multicast_promisc;
rte_pmd_i40e_set_vf_mac_addr;
+ rte_pmd_i40e_set_vf_vlan_insert;

} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:11:59 UTC
Permalink
Support enabling/disabling VF broadcast mode from PF.
User can call the API on PF to enable/disable a specific
VF's broadcast mode.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 43 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 18 +++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 62 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index a1aa469..ef67e4b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10414,3 +10414,46 @@ int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,

return ret;
}
+
+int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ if (vf_id > pf->vf_num)
+ return -EINVAL;
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ vf = &pf->vfs[vf_id];
+ hw = I40E_VSI_TO_HW(vf->vsi);
+
+ ret = i40e_aq_set_vsi_broadcast(hw, vf->vsi->seid, on, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 8867e9c..3e7ecb7 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -226,4 +226,22 @@ int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
uint16_t vlan_id);

+/**
+ * Enable/Disable vf broadcast mode
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * ID specifying VF.
+ * @param on
+ * 0 - Disable broadcast.
+ * 1 - Enable broadcast.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index b55a7ca..2998daf 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -14,5 +14,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_multicast_promisc;
rte_pmd_i40e_set_vf_mac_addr;
rte_pmd_i40e_set_vf_vlan_insert;
+ rte_pmd_i40e_set_vf_broadcast;

} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:00 UTC
Permalink
Add rte_pmd_i40e_set_vf_vlan_tag API.
User can call the API on PF to enable/disable a specific
VF's VLAN tag.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 59 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 18 ++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 78 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index ef67e4b..9a80237 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10457,3 +10457,62 @@ int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on)

return ret;
}
+
+int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ struct i40e_vsi *vsi;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ if (vf_id >= pf->vf_num)
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+ if (on) {
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
+ vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+ } else {
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+ vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
+ }
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 3e7ecb7..0b245da 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -244,4 +244,22 @@ int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
*/
int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on);

+/**
+ * Enable/Disable vf vlan tag
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * ID specifying VF.
+ * @param vlan_id
+ * 0 - Disable VF's vlan tag.
+ * n - Enable VF's vlan tag.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 2998daf..672316b 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -15,5 +15,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_mac_addr;
rte_pmd_i40e_set_vf_vlan_insert;
rte_pmd_i40e_set_vf_broadcast;
+ rte_pmd_i40e_set_vf_vlan_tag;

} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:01 UTC
Permalink
add rte_pmd_i40e_set_vf_vlan_filter API.
User can call the API on PF to enable/disable
a set of VF's VLAN filters.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 50 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 22 ++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 9a80237..61735fb 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10516,3 +10516,53 @@ int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)

return ret;
}
+
+int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
+ uint64_t vf_mask, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ uint16_t pool_idx;
+ int ret = 0;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vlan_id > ETHER_MAX_VLAN_ID)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ if ((pf->flags & I40E_FLAG_VMDQ) == 0) {
+ PMD_INIT_LOG(ERR, "Firmware doesn't support VMDQ");
+ return -ENOTSUP;
+ }
+
+ if (!pf->vmdq) {
+ PMD_INIT_LOG(INFO, "VMDQ not configured");
+ return -ENOTSUP;
+ }
+
+ for (pool_idx = 0;
+ pool_idx < ETH_64_POOLS && pool_idx < pf->nb_cfg_vmdq_vsi;
+ pool_idx++) {
+ if (vf_mask & ((uint64_t)(1ULL << pool_idx))) {
+ if (on)
+ ret = i40e_vsi_add_vlan(pf->vmdq[pool_idx].vsi,
+ vlan_id);
+ else
+ ret = i40e_vsi_delete_vlan(
+ pf->vmdq[pool_idx].vsi, vlan_id);
+ }
+ }
+
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 0b245da..1ce9513 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -262,4 +262,26 @@ int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
*/
int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on);

+/**
+ * Enable/Disable VF VLAN filter
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vlan_id
+ * ID specifying VLAN
+ * @param vf_mask
+ * Mask to filter VF's
+ * @param on
+ * 0 - Disable VF's VLAN filter.
+ * 1 - Enable VF's VLAN filter.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ * - (-ENOTSUP) VMDq not configured of not supported by firmware.
+ */
+int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
+ uint64_t vf_mask, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 672316b..ba7d922 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -16,5 +16,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_vlan_insert;
rte_pmd_i40e_set_vf_broadcast;
rte_pmd_i40e_set_vf_vlan_tag;
+ rte_pmd_i40e_set_vf_vlan_filter;

} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:02 UTC
Permalink
The new VF Daemon (VFD) APIs is implemented on i40e. Change
testpmd code to use them, inlcuding VF MAC anti-spoofing,
VF VLAN anti-spoofing, TX loopback, VF VLAN strip, VF VLAN
insert.

Signed-off-by: Wenzhuo Lu <***@intel.com>
Signed-off-by: Chen Jing D(Mark) <***@intel.com>
Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/cmdline.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 85 insertions(+), 7 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 63b55dc..1284d6c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -90,6 +90,9 @@
#ifdef RTE_LIBRTE_IXGBE_PMD
#include <rte_pmd_ixgbe.h>
#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
#include "testpmd.h"

static struct cmdline *testpmd_cl;
@@ -10806,9 +10809,22 @@ struct cmd_vf_vlan_anti_spoof_result {
struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
int ret = 0;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else
+ ret = -ENOSYS;

- ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id, res->vf_id,
- is_on);
switch (ret) {
case 0:
break;
@@ -10818,6 +10834,9 @@ struct cmd_vf_vlan_anti_spoof_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOSYS:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -10891,9 +10910,22 @@ struct cmd_vf_mac_anti_spoof_result {
struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
int ret;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else
+ ret = -ENOSYS;

- ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id, res->vf_id,
- is_on);
switch (ret) {
case 0:
break;
@@ -10903,6 +10935,9 @@ struct cmd_vf_mac_anti_spoof_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOSYS:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -10976,8 +11011,20 @@ struct cmd_vf_vlan_stripq_result {
struct cmd_vf_vlan_stripq_result *res = parsed_result;
int ret = 0;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+ else
+ ret = -ENOSYS;

- ret = rte_pmd_ixgbe_set_vf_vlan_stripq(res->port_id, res->vf_id, is_on);
switch (ret) {
case 0:
break;
@@ -10987,6 +11034,9 @@ struct cmd_vf_vlan_stripq_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOSYS:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -11059,8 +11109,20 @@ struct cmd_vf_vlan_insert_result {
{
struct cmd_vf_vlan_insert_result *res = parsed_result;
int ret;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+ else
+ ret = -ENOSYS;

- ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id, res->vlan_id);
switch (ret) {
case 0:
break;
@@ -11070,6 +11132,9 @@ struct cmd_vf_vlan_insert_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOSYS:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -11133,8 +11198,18 @@ struct cmd_tx_loopback_result {
struct cmd_tx_loopback_result *res = parsed_result;
int ret;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_tx_loopback(res->port_id, is_on);
+ else
+ ret = -ENOSYS;

- ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
switch (ret) {
case 0:
break;
@@ -11144,6 +11219,9 @@ struct cmd_tx_loopback_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOSYS:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
--
1.9.3
Ferruh Yigit
2016-12-02 11:22:12 UTC
Permalink
Post by Wenzhuo Lu
The new VF Daemon (VFD) APIs is implemented on i40e. Change
testpmd code to use them, inlcuding VF MAC anti-spoofing,
s/inlcuding/including
Post by Wenzhuo Lu
VF VLAN anti-spoofing, TX loopback, VF VLAN strip, VF VLAN
insert.
---
For shared library compilation, i40e library should be linked against,
this requires testpmd Makefile modification [1], otherwise throwing
compiler error [2].

[1]
diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index 891b85a..87cbaf9 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -59,6 +59,7 @@ SRCS-y += icmpecho.c
SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c

_LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe
+_LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e



[2]
cmdline.o: In function `cmd_set_vf_vlan_anti_spoof_parsed':
.../app/test-pmd/cmdline.c:(.text+0x76dc): undefined reference to
`rte_pmd_i40e_set_vf_vlan_anti_spoof'
cmdline.o: In function `cmd_set_vf_mac_anti_spoof_parsed':
.../app/test-pmd/cmdline.c:(.text+0x7854): undefined reference to
`rte_pmd_i40e_set_vf_mac_anti_spoof'
cmdline.o: In function `cmd_set_vf_vlan_stripq_parsed':
.../app/test-pmd/cmdline.c:(.text+0x79d4): undefined reference to
`rte_pmd_i40e_set_vf_vlan_stripq'
cmdline.o: In function `cmd_set_vf_vlan_insert_parsed':
.../app/test-pmd/cmdline.c:(.text+0x7b1e): undefined reference to
`rte_pmd_i40e_set_vf_vlan_insert'
cmdline.o: In function `cmd_set_tx_loopback_parsed':
.../app/test-pmd/cmdline.c:(.text+0x7c94): undefined reference to
`rte_pmd_i40e_set_tx_loopback'
cmdline.o: In function `cmd_set_vf_unicast_promisc_parsed':
.../app/test-pmd/cmdline.c:(.text+0x7f44): undefined reference to
`rte_pmd_i40e_set_vf_unicast_promisc'
cmdline.o: In function `cmd_set_vf_multicast_promisc_parsed':
.../app/test-pmd/cmdline.c:(.text+0x7fe4): undefined reference to
`rte_pmd_i40e_set_vf_multicast_promisc'
cmdline.o: In function `cmd_set_vf_broadcast_parsed':
.../app/test-pmd/cmdline.c:(.text+0x8086): undefined reference to
`rte_pmd_i40e_set_vf_broadcast'
cmdline.o: In function `cmd_set_vf_vlan_tag_parsed':
.../app/test-pmd/cmdline.c:(.text+0x8146): undefined reference to
`rte_pmd_i40e_set_vf_vlan_tag'
config.o: In function `set_vf_rx_vlan':
.../app/test-pmd/config.c:(.text+0x518d): undefined reference to
`rte_pmd_i40e_set_vf_vlan_filter'
clang-3.8: error: linker command failed with exit code 1 (use -v to see
invocation)
Post by Wenzhuo Lu
app/test-pmd/cmdline.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 85 insertions(+), 7 deletions(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 63b55dc..1284d6c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -90,6 +90,9 @@
#ifdef RTE_LIBRTE_IXGBE_PMD
#include <rte_pmd_ixgbe.h>
#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
#include "testpmd.h"
static struct cmdline *testpmd_cl;
@@ -10806,9 +10809,22 @@ struct cmd_vf_vlan_anti_spoof_result {
struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
int ret = 0;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else
+ ret = -ENOSYS;
Same checkpatch warning, for all ENOSYS usage,
WARNING:ENOSYS: ENOSYS means 'invalid syscall nr' and nothing else

If the intention is not matching error type, we may change it.
Wenzhuo Lu
2016-12-02 00:12:03 UTC
Permalink
Add testpmd CLI to set VF unicast promiscuous mode on i40e.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
app/test-pmd/cmdline.c | 89 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 8 +++
2 files changed, 97 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 1284d6c..3c0bb77 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -404,6 +404,11 @@ static void cmd_help_long_parsed(void *parsed_result,
"set allmulti (port_id|all) (on|off)\n"
" Set the allmulti mode on port_id, or all.\n\n"

+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
+ " Set unicast promiscuous mode for a VF from the PF.\n\n"
+#endif
+
"set flow_ctrl rx (on|off) tx (on|off) (high_water)"
" (low_water) (pause_time) (send_xon) mac_ctrl_frame_fwd"
" (on|off) autoneg (on|off) (port_id)\n"
@@ -11489,6 +11494,87 @@ struct cmd_set_vf_mac_addr_result {
};
#endif

+#ifdef RTE_LIBRTE_I40E_PMD
+/* VF unicast promiscuous mode configuration */
+
+/* Common result structure for VF unicast promiscuous mode */
+struct cmd_vf_unicast_promisc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t unicast_promisc;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF unicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_unicast_promisc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ unicast_promisc, "unicast-promisc");
+cmdline_parse_token_num_t cmd_vf_unicast_promisc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_unicast_promisc_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_unicast_promisc_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_unicast_promisc_result *res = parsed_result;
+ int ret = 0;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ ret = rte_pmd_i40e_set_vf_unicast_promisc(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_unicast_promisc = {
+ .f = cmd_set_vf_unicast_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf unicast promiscuous port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_vf_unicast_promisc_set,
+ (void *)&cmd_vf_unicast_promisc_vf,
+ (void *)&cmd_vf_unicast_promisc_unicast_promisc,
+ (void *)&cmd_vf_unicast_promisc_port_id,
+ (void *)&cmd_vf_unicast_promisc_vf_id,
+ (void *)&cmd_vf_unicast_promisc_on_off,
+ NULL,
+ },
+};
+#endif
+
/* ******************************************************************************** */

/* list of instructions */
@@ -11655,6 +11741,9 @@ struct cmd_set_vf_mac_addr_result {
(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ (cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
+#endif
NULL,
};

diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f1c269a..e17e3d5 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -820,6 +820,14 @@ Set the allmulti mode for a port or for all ports::

Same as the ifconfig (8) option. Controls how multicast packets are handled.

+set unicast promisc (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set the unicast promiscuous mode for a VF from PF.
+In promiscuous mode packets are not dropped if they aren't for the specified MAC address::
+
+ testpmd> set vf unicast-promisc (port_id) (vf_id) (on|off)
+
set flow_ctrl rx
~~~~~~~~~~~~~~~~
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:04 UTC
Permalink
Add testpmd CLI to set VF multicast promiscuous mode on i40e.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
app/test-pmd/cmdline.c | 83 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 8 +++
2 files changed, 91 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 3c0bb77..fa60086 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -407,6 +407,9 @@ static void cmd_help_long_parsed(void *parsed_result,
#ifdef RTE_LIBRTE_I40E_PMD
"set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
" Set unicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set vf multicast-promisc (port_id) (vf_id) (on|off)\n"
+ " Set multicast promiscuous mode for a VF from the PF.\n\n"
#endif

"set flow_ctrl rx (on|off) tx (on|off) (high_water)"
@@ -11573,6 +11576,85 @@ struct cmd_vf_unicast_promisc_result {
NULL,
},
};
+
+/* VF multicast promiscuous mode configuration */
+
+/* Common result structure for VF multicast promiscuous mode */
+struct cmd_vf_multicast_promisc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t multicast_promisc;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF multicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_multicast_promisc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ multicast_promisc, "multicast-promisc");
+cmdline_parse_token_num_t cmd_vf_multicast_promisc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_multicast_promisc_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_multicast_promisc_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_multicast_promisc_result *res = parsed_result;
+ int ret = 0;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ ret = rte_pmd_i40e_set_vf_multicast_promisc(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_multicast_promisc = {
+ .f = cmd_set_vf_multicast_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf multicast promiscuous port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_vf_multicast_promisc_set,
+ (void *)&cmd_vf_multicast_promisc_vf,
+ (void *)&cmd_vf_multicast_promisc_multicast_promisc,
+ (void *)&cmd_vf_multicast_promisc_port_id,
+ (void *)&cmd_vf_multicast_promisc_vf_id,
+ (void *)&cmd_vf_multicast_promisc_on_off,
+ NULL,
+ },
+};
#endif

/* ******************************************************************************** */
@@ -11743,6 +11825,7 @@ struct cmd_vf_unicast_promisc_result {
#endif
#ifdef RTE_LIBRTE_I40E_PMD
(cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
+ (cmdline_parse_inst_t *)&cmd_set_vf_multicast_promisc,
#endif
NULL,
};
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index e17e3d5..e1545b7 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -828,6 +828,14 @@ In promiscuous mode packets are not dropped if they aren't for the specified MAC

testpmd> set vf unicast-promisc (port_id) (vf_id) (on|off)

+set multicast promisc (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set the multicast promiscuous mode for a VF from PF.
+In promiscuous mode packets are not dropped if they aren't for the specified MAC address::
+
+ testpmd> set vf multicast-promisc (port_id) (vf_id) (on|off)
+
set flow_ctrl rx
~~~~~~~~~~~~~~~~
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:05 UTC
Permalink
Add command to call rte_pmd_i40e_set_vf_broadcast.
Add set vf broadcast in testpmd_funcs.rst file.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/cmdline.c | 84 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 +++
2 files changed, 91 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index fa60086..56d275b 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -279,6 +279,11 @@ static void cmd_help_long_parsed(void *parsed_result,
" Set MAC antispoof for a VF from the PF.\n\n"
#endif

+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf broadcast (port_id) (vf_id) (on|off)\n"
+ " Set VF broadcast for a VF from the PF.\n\n"
+#endif
+
"vlan set strip (on|off) (port_id)\n"
" Set the VLAN strip on a port.\n\n"

@@ -11655,6 +11660,84 @@ struct cmd_vf_multicast_promisc_result {
NULL,
},
};
+
+/* vf broadcast mode configuration */
+
+/* Common result structure for vf broadcast */
+struct cmd_set_vf_broadcast_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t broadcast;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf broadcast enable disable */
+cmdline_parse_token_string_t cmd_set_vf_broadcast_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_broadcast =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ broadcast, "broadcast");
+cmdline_parse_token_num_t cmd_set_vf_broadcast_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_broadcast_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_broadcast_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_broadcast_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_broadcast_result *res = parsed_result;
+ int ret;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ ret = rte_pmd_i40e_set_vf_broadcast(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_broadcast = {
+ .f = cmd_set_vf_broadcast_parsed,
+ .data = NULL,
+ .help_str = "set vf broadcast port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_broadcast_set,
+ (void *)&cmd_set_vf_broadcast_vf,
+ (void *)&cmd_set_vf_broadcast_broadcast,
+ (void *)&cmd_set_vf_broadcast_port_id,
+ (void *)&cmd_set_vf_broadcast_vf_id,
+ (void *)&cmd_set_vf_broadcast_on_off,
+ NULL,
+ },
+};
#endif

/* ******************************************************************************** */
@@ -11826,6 +11909,7 @@ struct cmd_vf_multicast_promisc_result {
#ifdef RTE_LIBRTE_I40E_PMD
(cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
(cmdline_parse_inst_t *)&cmd_set_vf_multicast_promisc,
+ (cmdline_parse_inst_t *)&cmd_set_vf_broadcast,
#endif
NULL,
};
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index e1545b7..525d0df 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -507,6 +507,13 @@ Set mac antispoof for a VF from the PF::

testpmd> set vf mac antispoof (port_id) (vf_id) (on|off)

+set broadcast mode (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set broadcast mode for a VF from the PF::
+
+ testpmd> set vf broadcast (port_id) (vf_id) (on|off)
+
vlan set strip
~~~~~~~~~~~~~~
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:06 UTC
Permalink
command is: set vf vlan tag port_id vf_id on|off

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/cmdline.c | 90 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 +++
2 files changed, 97 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 56d275b..9135e45 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -301,6 +301,11 @@ static void cmd_help_long_parsed(void *parsed_result,
" Set VLAN antispoof for a VF from the PF.\n\n"
#endif

+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf vlan tag (port_id) (vf_id) (on|off)\n"
+ " Set VLAN tag for a VF from the PF.\n\n"
+#endif
+
"vlan set filter (on|off) (port_id)\n"
" Set the VLAN filter on a port.\n\n"

@@ -11738,6 +11743,90 @@ struct cmd_set_vf_broadcast_result {
NULL,
},
};
+
+/* vf vlan tag configuration */
+
+/* Common result structure for vf vlan tag */
+struct cmd_set_vf_vlan_tag_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t tag;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan tag enable disable */
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_tag =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ tag, "tag");
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_tag_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_vlan_tag_result *res = parsed_result;
+ int ret;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ ret = rte_pmd_i40e_set_vf_vlan_tag(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_tag = {
+ .f = cmd_set_vf_vlan_tag_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan tag port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_vlan_tag_set,
+ (void *)&cmd_set_vf_vlan_tag_vf,
+ (void *)&cmd_set_vf_vlan_tag_vlan,
+ (void *)&cmd_set_vf_vlan_tag_tag,
+ (void *)&cmd_set_vf_vlan_tag_port_id,
+ (void *)&cmd_set_vf_vlan_tag_vf_id,
+ (void *)&cmd_set_vf_vlan_tag_on_off,
+ NULL,
+ },
+};
#endif

/* ******************************************************************************** */
@@ -11910,6 +11999,7 @@ struct cmd_set_vf_broadcast_result {
(cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
(cmdline_parse_inst_t *)&cmd_set_vf_multicast_promisc,
(cmdline_parse_inst_t *)&cmd_set_vf_broadcast,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_tag,
#endif
NULL,
};
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 525d0df..cffcac8 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -542,6 +542,13 @@ Set VLAN insert for a VF from the PF::

testpmd> set vf vlan insert (port_id) (vf_id) (vlan_id)

+vlan set tag (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN tag for a VF from the PF::
+
+ testpmd> set vf vlan tag (port_id) (vf_id) (on|off)
+
vlan set antispoof (for VF)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:07 UTC
Permalink
modify set_vf_rx_vlan function to handle the i40e PMD.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/config.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 36c47ab..0368dc6 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -92,6 +92,9 @@
#include <rte_ethdev.h>
#include <rte_string_fns.h>
#include <rte_cycles.h>
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif

#include "testpmd.h"

@@ -2349,12 +2352,24 @@ struct igb_ring_desc_16_bytes {
set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
{
int diag;
+ struct rte_eth_dev_info dev_info;

if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
- diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on);
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (strstr(dev_info.driver_name, "i40e") != NULL)
+ diag = rte_pmd_i40e_set_vf_vlan_filter(port_id, vlan_id,
+ vf_mask, on);
+ else
+#endif
+ diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id,
+ vf_mask, on);
+
if (diag == 0)
return;
printf("rte_eth_dev_set_vf_vlan_filter for port_id=%d failed "
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:08 UTC
Permalink
Initialise VMDq in the init_port_config function in a similar
way to how it is done in the VMDq sample application.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/testpmd.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index a0332c2..c0c8f60 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1842,9 +1842,12 @@ struct pmd_test_command {
ETH_MQ_RX_VMDQ_RSS;
else
port->dev_conf.rxmode.mq_mode =
- ETH_MQ_RX_NONE;
+ ETH_MQ_RX_VMDQ_ONLY;

port->dev_conf.txmode.mq_mode = ETH_MQ_TX_NONE;
+
+ port->dev_conf.rx_adv_conf.vmdq_rx_conf.nb_queue_pools =
+ ETH_8_POOLS;
}

rxtx_port_config(port);
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:09 UTC
Permalink
i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in version
number returned.

Current version info returned won't be able to be recognized
by Linux VF driver, change to values that both DPDK VF and Linux
driver can recognize.

The expense is original DPDK host specific feature like
CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.

DPDK VF also can't identify host driver by version number returned.
It always assume talking with Linux PF.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 2bc3355..0f582ed 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -279,8 +279,19 @@
{
struct i40e_virtchnl_version_info info;

- info.major = I40E_DPDK_VERSION_MAJOR;
- info.minor = I40E_DPDK_VERSION_MINOR;
+ /* Respond like a Linux PF host in order to support both DPDK VF and
+ * Linux VF driver. The expense is original DPDK host specific feature
+ * like CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.
+ *
+ * DPDK VF also can't identify host driver by version number returned.
+ * It always assume talking with Linux PF.
+ *
+ * TODO:
+ * Discuss with Linux driver maintainer if possible to carry more info
+ * in this function to identify it's Linux or DPDK host.
+ */
+ info.major = I40E_VIRTCHNL_VERSION_MAJOR;
+ info.minor = I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;

if (b_op)
i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:10 UTC
Permalink
PF host didn't return correct VSI id to VF.
This change fix it.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 0f582ed..8319c2c 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -351,8 +351,7 @@

/* Change below setting if PF host can support more VSIs for VF */
vf_res->vsi_res[0].vsi_type = I40E_VSI_SRIOV;
- /* As assume Vf only has single VSI now, always return 0 */
- vf_res->vsi_res[0].vsi_id = 0;
+ vf_res->vsi_res[0].vsi_id = vf->vsi->vsi_id;
vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;
ether_addr_copy(&vf->mac_addr,
(struct ether_addr *)vf_res->vsi_res[0].default_mac_addr);
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:11 UTC
Permalink
When VF requested to configure TX queue, a few parameters are
missed to be configured in PF host. This change have more
fields parsed and configured for TX context.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 8319c2c..1ad5ed1 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -422,10 +422,12 @@

/* clear the context structure first */
memset(&tx_ctx, 0, sizeof(tx_ctx));
- tx_ctx.new_context = 1;
tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
tx_ctx.qlen = txq->ring_len;
tx_ctx.rdylist = rte_le_to_cpu_16(vf->vsi->info.qs_handle[0]);
+ tx_ctx.head_wb_ena = txq->headwb_enabled;
+ tx_ctx.head_wb_addr = txq->dma_headwb_addr;
+
err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id);
if (err != I40E_SUCCESS)
return err;
--
1.9.3
Wenzhuo Lu
2016-12-02 00:12:12 UTC
Permalink
i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in
configuring IRQ link list.

This Change will identify VF client by number of vector
requested. DPDK VF will ask only single one while Linux VF
will request at least 2. It will have different configuration
for different clients. DPDK VF will be configured to link all
queue together, while Linux VF will be configured per request.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 151 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 138 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 1ad5ed1..4b0da75 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -585,14 +585,116 @@
return ret;
}

+static void
+i40e_pf_config_irq_link_list(struct i40e_pf_vf *vf,
+ struct i40e_virtchnl_vector_map *vvm)
+{
+ uint64_t linklistmap = 0, tempmap;
+ struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
+ uint16_t qid;
+ bool b_first_q = true;
+ enum i40e_queue_type qtype;
+ uint16_t vector_id;
+ uint32_t reg, reg_idx;
+ uint16_t itr_idx = 0, i;
+
+ vector_id = vvm->vector_id;
+ /* setup the head */
+ if (!vector_id)
+ reg_idx = I40E_VPINT_LNKLST0(vf->vf_idx);
+ else
+ reg_idx = I40E_VPINT_LNKLSTN(
+ ((hw->func_caps.num_msix_vectors_vf - 1) * vf->vf_idx)
+ + (vector_id - 1));
+
+ if (vvm->rxq_map == 0 && vvm->txq_map == 0) {
+ I40E_WRITE_REG(hw, reg_idx,
+ I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK);
+ goto cfg_irq_done;
+ }
+
+ /* sort all rx and tx queues */
+ tempmap = vvm->rxq_map;
+ for (i = 0; i < sizeof(vvm->rxq_map) * 8; i++) {
+ if (tempmap & 0x1)
+ linklistmap |= (1 << (2 * i));
+ tempmap >>= 1;
+ }
+
+ tempmap = vvm->txq_map;
+ for (i = 0; i < sizeof(vvm->txq_map) * 8; i++) {
+ if (tempmap & 0x1)
+ linklistmap |= (1 << (2 * i + 1));
+ tempmap >>= 1;
+ }
+
+ /* Link all rx and tx queues into a chained list */
+ tempmap = linklistmap;
+ i = 0;
+ b_first_q = true;
+ do {
+ if (tempmap & 0x1) {
+ qtype = i % 2;
+ qid = vf->vsi->base_queue + i / 2;
+ if (b_first_q) {
+ /* This is header */
+ b_first_q = false;
+ reg = ((qtype <<
+ I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+ | qid);
+ } else {
+ /* element in the link list */
+ reg = (vector_id) |
+ (qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
+ (qid << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+ BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
+ (itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
+ }
+ I40E_WRITE_REG(hw, reg_idx, reg);
+ /* find next register to program */
+ switch (qtype) {
+ case I40E_QUEUE_TYPE_RX:
+ reg_idx = I40E_QINT_RQCTL(qid);
+ itr_idx = vvm->rxitr_idx;
+ break;
+ case I40E_QUEUE_TYPE_TX:
+ reg_idx = I40E_QINT_TQCTL(qid);
+ itr_idx = vvm->txitr_idx;
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ tempmap >>= 1;
+ } while (tempmap);
+
+ /* Terminate the link list */
+ reg = (vector_id) |
+ (0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
+ (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+ BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
+ (itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
+ I40E_WRITE_REG(hw, reg_idx, reg);
+
+cfg_irq_done:
+ I40E_WRITE_FLUSH(hw);
+}
+
static int
i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
uint8_t *msg, uint16_t msglen,
bool b_op)
{
int ret = I40E_SUCCESS;
+ struct i40e_pf *pf = vf->pf;
+ struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_virtchnl_irq_map_info *irqmap =
(struct i40e_virtchnl_irq_map_info *)msg;
+ struct i40e_virtchnl_vector_map *map;
+ int i;
+ uint16_t vector_id;
+ unsigned long qbit_max;

if (!b_op) {
i40e_pf_host_send_msg_to_vf(
@@ -608,23 +710,46 @@
goto send_msg;
}

- /* Assume VF only have 1 vector to bind all queues */
- if (irqmap->num_vectors != 1) {
- PMD_DRV_LOG(ERR, "DKDK host only support 1 vector");
- ret = I40E_ERR_PARAM;
+ /* PF host will support both DPDK VF or Linux VF driver, identify by
+ * number of vectors requested.
+ */
+
+ /* DPDK VF only requires single vector */
+ if (irqmap->num_vectors == 1) {
+ /* This MSIX intr store the intr in VF range */
+ vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+ vf->vsi->nb_msix = irqmap->num_vectors;
+ vf->vsi->nb_used_qps = vf->vsi->nb_qps;
+
+ /* Don't care how the TX/RX queue mapping with this vector.
+ * Link all VF RX queues together. Only did mapping work.
+ * VF can disable/enable the intr by itself.
+ */
+ i40e_vsi_queues_bind_intr(vf->vsi);
goto send_msg;
}

- /* This MSIX intr store the intr in VF range */
- vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
- vf->vsi->nb_msix = irqmap->num_vectors;
- vf->vsi->nb_used_qps = vf->vsi->nb_qps;
+ /* Then, it's Linux VF driver */
+ qbit_max = 1 << pf->vf_nb_qp_max;
+ for (i = 0; i < irqmap->num_vectors; i++) {
+ map = &irqmap->vecmap[i];
+
+ vector_id = map->vector_id;
+ /* validate msg params */
+ if (vector_id >= hw->func_caps.num_msix_vectors_vf) {
+ ret = I40E_ERR_PARAM;
+ goto send_msg;
+ }
+
+ if ((map->rxq_map < qbit_max) && (map->txq_map < qbit_max)) {
+ i40e_pf_config_irq_link_list(vf, map);
+ } else {
+ /* configured queue size excceed limit */
+ ret = I40E_ERR_PARAM;
+ goto send_msg;
+ }
+ }

- /* Don't care how the TX/RX queue mapping with this vector.
- * Link all VF RX queues together. Only did mapping work.
- * VF can disable/enable the intr by itself.
- */
- i40e_vsi_queues_bind_intr(vf->vsi);
send_msg:
i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
ret, NULL, 0);
--
1.9.3
Ferruh Yigit
2016-12-02 11:25:46 UTC
Permalink
Post by Wenzhuo Lu
i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in
configuring IRQ link list.
This Change will identify VF client by number of vector
requested. DPDK VF will ask only single one while Linux VF
will request at least 2. It will have different configuration
for different clients. DPDK VF will be configured to link all
queue together, while Linux VF will be configured per request.
---
drivers/net/i40e/i40e_pf.c | 151 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 138 insertions(+), 13 deletions(-)
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 1ad5ed1..4b0da75 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -585,14 +585,116 @@
return ret;
}
+static void
+i40e_pf_config_irq_link_list(struct i40e_pf_vf *vf,
+ struct i40e_virtchnl_vector_map *vvm)
+{
+ uint64_t linklistmap = 0, tempmap;
+ struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
+ uint16_t qid;
+ bool b_first_q = true;
+ enum i40e_queue_type qtype;
+ uint16_t vector_id;
+ uint32_t reg, reg_idx;
+ uint16_t itr_idx = 0, i;
+
+ vector_id = vvm->vector_id;
+ /* setup the head */
+ if (!vector_id)
+ reg_idx = I40E_VPINT_LNKLST0(vf->vf_idx);
+ else
+ reg_idx = I40E_VPINT_LNKLSTN(
+ ((hw->func_caps.num_msix_vectors_vf - 1) * vf->vf_idx)
+ + (vector_id - 1));
+
+ if (vvm->rxq_map == 0 && vvm->txq_map == 0) {
+ I40E_WRITE_REG(hw, reg_idx,
+ I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK);
+ goto cfg_irq_done;
+ }
+
+ /* sort all rx and tx queues */
+ tempmap = vvm->rxq_map;
+ for (i = 0; i < sizeof(vvm->rxq_map) * 8; i++) {
+ if (tempmap & 0x1)
+ linklistmap |= (1 << (2 * i));
+ tempmap >>= 1;
+ }
+
+ tempmap = vvm->txq_map;
+ for (i = 0; i < sizeof(vvm->txq_map) * 8; i++) {
+ if (tempmap & 0x1)
+ linklistmap |= (1 << (2 * i + 1));
+ tempmap >>= 1;
+ }
+
+ /* Link all rx and tx queues into a chained list */
+ tempmap = linklistmap;
+ i = 0;
+ b_first_q = true;
+ do {
+ if (tempmap & 0x1) {
+ qtype = i % 2;
This cause ICC compilation error:

.../app/test-pmd/cmdline.c:(.text+0x79d4): undefined reference to
`rte_pmd_i40e_set_vf_vlan_stripq'
Lu, Wenzhuo
2016-12-05 03:02:24 UTC
Permalink
Hi Ferruh,
Thanks for the comments!

Hi Ferruh, Jing, Bernard,
As they're not functionality issues. Most of them are compile and typo issues. I'll fix them and send a V2.


Best regards
Wenzhuo Lu
Wenzhuo Lu
2016-12-02 00:12:13 UTC
Permalink
When VF sends request to add a new mac address, PF host
will check if it's a non-zero or uncast address, or it
will return with error. In fact, VF still can set multicast
address. This change remove to check if it's a unicast
address.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 4b0da75..c9cca1e 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -890,7 +890,7 @@
mac = (struct ether_addr *)(addr_list->list[i].addr);
(void)rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
- if(!is_valid_assigned_ether_addr(mac) ||
+ if(is_zero_ether_addr(mac) ||
i40e_vsi_add_mac(vf->vsi, &filter)) {
ret = I40E_ERR_INVALID_MAC_ADDR;
goto send_msg;
--
1.9.3
Ferruh Yigit
2016-12-02 11:23:11 UTC
Permalink
Post by Wenzhuo Lu
When VF sends request to add a new mac address, PF host
will check if it's a non-zero or uncast address, or it
will return with error. In fact, VF still can set multicast
address. This change remove to check if it's a unicast
address.
---
commit subject tag should be: "net/i40e:", and MAC is uppercase.
Post by Wenzhuo Lu
drivers/net/i40e/i40e_pf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 4b0da75..c9cca1e 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -890,7 +890,7 @@
mac = (struct ether_addr *)(addr_list->list[i].addr);
(void)rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
- if(!is_valid_assigned_ether_addr(mac) ||
+ if(is_zero_ether_addr(mac) ||
checkpatch warning:
ERROR:SPACING: space required before the open parenthesis '('
Post by Wenzhuo Lu
i40e_vsi_add_mac(vf->vsi, &filter)) {
ret = I40E_ERR_INVALID_MAC_ADDR;
goto send_msg;
Andrew Rybchenko
2016-12-02 08:59:32 UTC
Permalink
Post by Wenzhuo Lu
1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK follows the interface
between kernel PF + kernel VF. We don't want to introduce too many new messages
between PF and VF. So this patch set adds some new APIs to control VFs directly
from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
12) set VF VLAN tag
13) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP. When PF receives mailbox
messages from VF, PF should call the callback provided by APP to know if they're
permitted to be processed.
The patch series adds i40e-specific API functions for VF control (advertise link
status change, MAC anti-spoofing, VLAN anti-spoofing, promiscuous mode, MAC change,
VLAN controls), but RTE API is added to get VF stats. I'm wondering why.
Corresponding patches do not explain why i40e-specific API is added instead of
generic RTE API. IMHO, it is hardly convenient for applications.
(I guess it was a discussion and decision, but I've failed to find in the archive).

Andrew.
Iremonger, Bernard
2016-12-02 10:58:53 UTC
Permalink
Hi Andrew,
-----Original Message-----
Sent: Friday, December 2, 2016 9:00 AM
Subject: Re: [dpdk-dev] [PATCH 00/31] Support VFD and DPDK PF + kernel VF
on i40e
Post by Wenzhuo Lu
1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK follows
the interface between kernel PF + kernel VF. We don't want to
introduce too many new messages between PF and VF. So this patch set
adds some new APIs to control VFs directly from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
12) set VF VLAN tag
13) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP. When PF
receives mailbox messages from VF, PF should call the callback
provided by APP to know if they're permitted to be processed.
The patch series adds i40e-specific API functions for VF control (advertise link
status change, MAC anti-spoofing, VLAN anti-spoofing, promiscuous mode,
MAC change, VLAN controls), but RTE API is added to get VF stats. I'm
wondering why.
Corresponding patches do not explain why i40e-specific API is added instead
of generic RTE API. IMHO, it is hardly convenient for applications.
(I guess it was a discussion and decision, but I've failed to find in the archive).
Andrew.
There was a discussion previously in DPDK 16.11 about this approach being used for the ixgbe PMD.
I have
Iremonger, Bernard
2016-12-02 11:28:58 UTC
Permalink
Hi Andrew,
-----Original Message-----
Sent: Friday, December 2, 2016 10:59 AM
Subject: Re: [dpdk-dev] [PATCH 00/31] Support VFD and DPDK PF + kernel VF
on i40e
Hi Andrew,
-----Original Message-----
Rybchenko
Sent: Friday, December 2, 2016 9:00 AM
Subject: Re: [dpdk-dev] [PATCH 00/31] Support VFD and DPDK PF + kernel
VF on i40e
Post by Wenzhuo Lu
1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK follows
the interface between kernel PF + kernel VF. We don't want to
introduce too many new messages between PF and VF. So this patch set
adds some new APIs to control VFs directly from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
12) set VF VLAN tag
13) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP. When
PF receives mailbox messages from VF, PF should call the callback
provided by APP to know if they're permitted to be processed.
The patch series adds i40e-specific API functions for VF control
(advertise link status change, MAC anti-spoofing, VLAN anti-spoofing,
promiscuous mode, MAC change, VLAN controls), but RTE API is added to
get VF stats. I'm wondering why.
Corresponding patches do not explain why i40e-specific API is added
instead of generic RTE API. IMHO, it is hardly convenient for applications.
(I guess it was a discussion and decision, but I've failed to find in the
archive).
Andrew.
There was a discussion previously in DPDK 16.11 about this approach being
used for the ixgbe PMD.
I have attached the email thread.
Regards,
Bernard.
The attached email did not get through for some reason. Here is a link to the email archive.


http://dpdk.org/ml/archives/dev/2016-September/047786.html

Regar
Andrew Rybchenko
2016-12-02 12:09:43 UTC
Permalink
Hi Bernard,
Post by Iremonger, Bernard
-----Original Message-----
Sent: Friday, December 2, 2016 9:00 AM
Subject: Re: [dpdk-dev] [PATCH 00/31] Support VFD and DPDK PF + kernel VF
on i40e
Post by Wenzhuo Lu
1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK follows
the interface between kernel PF + kernel VF. We don't want to
introduce too many new messages between PF and VF. So this patch set
adds some new APIs to control VFs directly from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
12) set VF VLAN tag
13) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP. When PF
receives mailbox messages from VF, PF should call the callback
provided by APP to know if they're permitted to be processed.
The patch series adds i40e-specific API functions for VF control (advertise link
status change, MAC anti-spoofing, VLAN anti-spoofing, promiscuous mode,
MAC change, VLAN controls), but RTE API is added to get VF stats. I'm
wondering why.
Corresponding patches do not explain why i40e-specific API is added instead
of generic RTE API. IMHO, it is hardly convenient for applications.
(I guess it was a discussion and decision, but I've failed to find in the archive).
Andrew.
There was a discussion previously in DPDK 16.11 about this approach being used for the ixgbe PMD.
I have attached the email thread.
Many thanks. I see that it is a staging area waiting for a later
generalization.

Andrew.
Thomas Monjalon
2016-12-02 14:16:27 UTC
Permalink
Do you agree to copy the remaining VF-specific functions from the
generic ethdev API to ixgbe in 17.02?
After a deprecation notice, we could remove them from the generic API in 17.05.
So we will have a consistent status in 17.05 regarding VF functions.

After some time (and experience) we will be able to discuss wether
we need something more to access to these specific features.
Iremonger, Bernard
2016-12-02 14:25:30 UTC
Permalink
Hi Thomas,
-----Original Message-----
Sent: Friday, December 2, 2016 2:16 PM
Subject: Re: [dpdk-dev] [PATCH 00/31] Support VFD and DPDK PF + kernel VF
on i40e
Do you agree to copy the remaining VF-specific functions from the generic
ethdev API to ixgbe in 17.02?
After a deprecation notice, we could remove them from the generic API in 17.05.
So we will have a consistent status in 17.05 regarding VF functions.
After some time (and experience) we will be able to discuss wether we need
something more to access to these specific features.
I had intended to copy the remaining VF-specific functions from the generic ethdev API to ixgbe in 17.02 and a deprecation notice was sent in 16.11.

This work was parked in order work on the VF-specfic functionsfor the i40e. Is it ok to submit patches for this work after the V1 deadline (today)?

Regards,

Bernard.
Thomas Monjalon
2016-12-02 14:33:29 UTC
Permalink
Post by Iremonger, Bernard
Hi Thomas,
Do you agree to copy the remaining VF-specific functions from the generic
ethdev API to ixgbe in 17.02?
After a deprecation notice, we could remove them from the generic API in 17.05.
So we will have a consistent status in 17.05 regarding VF functions.
After some time (and experience) we will be able to discuss wether we need
something more to access to these specific features.
I had intended to copy the remaining VF-specific functions from the generic ethdev API to ixgbe in 17.02 and a deprecation notice was sent in 16.11.
This work was parked in order work on the VF-specfic functionsfor the i40e. Is it ok to submit patches for this work after the V1 deadline (today)?
Yes, it is a kind of cleanup and it has been discussed earlier.
So yes you can submit it later. Sooner is better though :)
Thanks
Wenzhuo Lu
2016-12-07 03:31:43 UTC
Permalink
1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK
follows the interface between kernel PF + kernel VF. We don't
want to introduce too many new messages between PF and VF. So
this patch set adds some new APIs to control VFs directly
from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
12) set VF VLAN tag
13) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP.
When PF receives mailbox messages from VF, PF should call the
callback provided by APP to know if they're permitted to be
processed.

2, Implement VF MAC address setting on VF.

3, Support the scenario DPDK PF + kernel VF.

v2:
- fix the compile issues.
- fix the checkpatch warning and typo.
- update the commit log of some patches.
- fix the invalid port ID issue of testpmd.

Bernard Iremonger (8):
net/i40e: add set VF VLAN insert function
net/i40e: set VF broadcast mode from PF
net/i40e: set VF VLAN tag from PF
net/i40e: set VF VLAN filter from PF
app/testpmd: add command to test VF broadcast mode on i40e
app/testpmd: add command to test VF VLAN tag on i40e
app/testpmd: handle i40e in VF VLAN filter command
app/testpmd: initialize receive mode for VMDq

Chen Jing D(Mark) (6):
net/i40e: add VF vlan strip func
net/i40e: change version number to support Linux VF
net/i40e: return correct vsi_id
net/i40e: parse more VF parameter and configure
net/i40e: support Linux VF to configure IRQ link list
net/i40e: enhance in sanity check of MAC

Ferruh Yigit (3):
net/i40e: set VF MAC from PF support
net/i40e: set VF MAC from VF support
net/i40e: fix VF MAC address assignment

Qi Zhang (4):
net/i40e: enable VF MTU change
rte: add APIs for VF stats get/reset
net/i40e: implement ops for VF stats get/reset
net/i40e: fix VF reset flow

Wenzhuo Lu (11):
net/i40e: support link status notification
net/i40e: add callback to user on VF to PF mbox msg
net/i40e: set VF MAC anti-spoofing from PF
net/i40e: set VF VLAN anti-spoofing from PF
net/i40e: set TX loopback from PF
net/i40e: set VF unicast promisc mode from PF
net/i40e: set VF multicast promisc mode from PF
app/testpmd: use VFD APIs on i40e
app/testpmd: use unicast promiscuous mode on i40e
app/testpmd: use multicast promiscuous mode on i40e
app/testpmd: fix invalid port ID

app/test-pmd/Makefile | 1 +
app/test-pmd/cmdline.c | 474 +++++++++++++++-
app/test-pmd/config.c | 17 +-
app/test-pmd/testpmd.c | 5 +-
app/test/Makefile | 8 +
app/test/test_pmd_i40e.c | 96 ++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 30 +
drivers/net/i40e/Makefile | 4 +-
drivers/net/i40e/i40e_ethdev.c | 835 +++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 5 +-
drivers/net/i40e/i40e_ethdev_vf.c | 81 ++-
drivers/net/i40e/i40e_pf.c | 417 ++++++++++++--
drivers/net/i40e/i40e_pf.h | 9 +-
drivers/net/i40e/rte_pmd_i40e.h | 287 ++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 18 +
lib/librte_ether/rte_ethdev.c | 47 ++
lib/librte_ether/rte_ethdev.h | 47 ++
17 files changed, 2294 insertions(+), 87 deletions(-)
create mode 100644 app/test/test_pmd_i40e.c
create mode 100644 drivers/net/i40e/rte_pmd_i40e.h
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:44 UTC
Permalink
Add an API to expose the ability, that PF can notify VF
when link status changes, to APP.
So if PF APP doesn't want to enable interruption but check
link status by itself, PF APP can let VF know link status
changed.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/Makefile | 4 ++-
drivers/net/i40e/i40e_ethdev.c | 28 +++++++++++++++
drivers/net/i40e/i40e_pf.c | 4 +--
drivers/net/i40e/i40e_pf.h | 4 ++-
drivers/net/i40e/rte_pmd_i40e.h | 58 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 6 ++++
6 files changed, 100 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/i40e/rte_pmd_i40e.h

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 13085fb..de7f384 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -1,6 +1,6 @@
# 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
@@ -111,6 +111,8 @@ ifeq ($(findstring RTE_MACHINE_CPUFLAG_SSE4_1,$(CFLAGS)),)
CFLAGS_i40e_rxtx_vec_sse.o += -msse4.1
endif

+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h

# this lib depends upon:
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..fda1454 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -62,6 +62,7 @@
#include "i40e_rxtx.h"
#include "i40e_pf.h"
#include "i40e_regs.h"
+#include "rte_pmd_i40e.h"

#define ETH_I40E_FLOATING_VEB_ARG "enable_floating_veb"
#define ETH_I40E_FLOATING_VEB_LIST_ARG "floating_veb_list"
@@ -9735,3 +9736,30 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+
+ 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;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
+
+ return 0;
+}
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index ddfc140..f70712b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -1,7 +1,7 @@
/*-
* 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
@@ -897,7 +897,7 @@
return ret;
}

-static void
+void
i40e_notify_vf_link_status(struct rte_eth_dev *dev, struct i40e_pf_vf *vf)
{
struct i40e_virtchnl_pf_event event;
diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index cddc45c..59bf2ee 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -1,7 +1,7 @@
/*-
* 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
@@ -123,5 +123,7 @@ void i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
uint8_t *msg, uint16_t msglen);
int i40e_pf_host_init(struct rte_eth_dev *dev);
int i40e_pf_host_uninit(struct rte_eth_dev *dev);
+void i40e_notify_vf_link_status(struct rte_eth_dev *dev,
+ struct i40e_pf_vf *vf);

#endif /* _I40E_PF_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
new file mode 100644
index 0000000..14852f2
--- /dev/null
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -0,0 +1,58 @@
+/*-
+ * 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_i40e.h
+ * i40e PMD specific functions.
+ *
+ **/
+
+#ifndef _PMD_I40E_H_
+#define _PMD_I40E_H_
+
+#include <rte_ethdev.h>
+
+/**
+ * Notify VF when PF link status changes.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * VF id.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if *vf* invalid.
+ */
+int rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf);
+
+#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef35398..4555446 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -2,3 +2,9 @@ DPDK_2.0 {

local: *;
};
+
+DPDK_17.02 {
+ global:
+
+ rte_pmd_i40e_ping_vfs;
+} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:45 UTC
Permalink
The callback asks the user application if it is allowed to
perform the mailbox messages.

If the return value from user is RTE_PMD_I40E_MB_EVENT_PROCEED
then continue. If ACK or NACK, do nothing and send
not_supported to VF.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 230 ++++++++++++++++++++++++++++++++++------
drivers/net/i40e/rte_pmd_i40e.h | 21 ++++
2 files changed, 216 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index f70712b..8b8a14f 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -55,6 +55,7 @@
#include "i40e_ethdev.h"
#include "i40e_rxtx.h"
#include "i40e_pf.h"
+#include "rte_pmd_i40e.h"

#define I40E_CFG_CRCSTRIP_DEFAULT 1

@@ -272,14 +273,23 @@
}

static void
-i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf, bool b_op)
{
struct i40e_virtchnl_version_info info;

info.major = I40E_DPDK_VERSION_MAJOR;
info.minor = I40E_DPDK_VERSION_MINOR;
- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
- I40E_SUCCESS, (uint8_t *)&info, sizeof(info));
+
+ if (b_op)
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+ I40E_SUCCESS,
+ (uint8_t *)&info,
+ sizeof(info));
+ else
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+ I40E_NOT_SUPPORTED,
+ (uint8_t *)&info,
+ sizeof(info));
}

static int
@@ -292,13 +302,20 @@
}

static int
-i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf, bool b_op)
{
struct i40e_virtchnl_vf_resource *vf_res = NULL;
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
uint32_t len = 0;
int ret = I40E_SUCCESS;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(vf,
+ I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
/* only have 1 VSI by default */
len = sizeof(struct i40e_virtchnl_vf_resource) +
I40E_DEFAULT_VF_VSI_NUM *
@@ -423,7 +440,8 @@
static int
i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_vsi *vsi = vf->vsi;
@@ -432,6 +450,13 @@
struct i40e_virtchnl_queue_pair_info *vc_qpi;
int i, ret = I40E_SUCCESS;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(vf,
+ I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP ||
msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci,
@@ -482,7 +507,8 @@
static int
i40e_pf_host_process_cmd_config_vsi_queues_ext(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_vsi *vsi = vf->vsi;
@@ -491,6 +517,14 @@
struct i40e_virtchnl_queue_pair_ext_info *vc_qpei;
int i, ret = I40E_SUCCESS;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (!msg || vc_vqcei->num_queue_pairs > vsi->nb_qps ||
vc_vqcei->num_queue_pairs > I40E_MAX_VSI_QP ||
msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei,
@@ -539,12 +573,21 @@

static int
i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
- uint8_t *msg, uint16_t msglen)
+ uint8_t *msg, uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_irq_map_info *irqmap =
(struct i40e_virtchnl_irq_map_info *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen < sizeof(struct i40e_virtchnl_irq_map_info)) {
PMD_DRV_LOG(ERR, "buffer too short");
ret = I40E_ERR_PARAM;
@@ -646,12 +689,21 @@
static int
i40e_pf_host_process_cmd_disable_queues(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_queue_select *q_sel =
(struct i40e_virtchnl_queue_select *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*q_sel)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -669,7 +721,8 @@
static int
i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -678,6 +731,14 @@
int i;
struct ether_addr *mac;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
memset(&filter, 0 , sizeof(struct i40e_mac_filter_info));

if (msg == NULL || msglen <= sizeof(*addr_list)) {
@@ -707,7 +768,8 @@
static int
i40e_pf_host_process_cmd_del_ether_address(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -715,6 +777,14 @@
int i;
struct ether_addr *mac;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*addr_list)) {
PMD_DRV_LOG(ERR, "delete_ether_address argument too short");
ret = I40E_ERR_PARAM;
@@ -739,7 +809,8 @@

static int
i40e_pf_host_process_cmd_add_vlan(struct i40e_pf_vf *vf,
- uint8_t *msg, uint16_t msglen)
+ uint8_t *msg, uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -747,6 +818,14 @@
int i;
uint16_t *vid;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_ADD_VLAN,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
PMD_DRV_LOG(ERR, "add_vlan argument too short");
ret = I40E_ERR_PARAM;
@@ -771,7 +850,8 @@
static int
i40e_pf_host_process_cmd_del_vlan(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -779,6 +859,14 @@
int i;
uint16_t *vid;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DEL_VLAN,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
PMD_DRV_LOG(ERR, "delete_vlan argument too short");
ret = I40E_ERR_PARAM;
@@ -803,7 +891,8 @@
i40e_pf_host_process_cmd_config_promisc_mode(
struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_promisc_info *promisc =
@@ -811,6 +900,14 @@
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
bool unicast = FALSE, multicast = FALSE;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*promisc)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -836,13 +933,20 @@
}

static int
-i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf, bool b_op)
{
i40e_update_vsi_stats(vf->vsi);

- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
- I40E_SUCCESS, (uint8_t *)&vf->vsi->eth_stats,
- sizeof(vf->vsi->eth_stats));
+ if (b_op)
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+ I40E_SUCCESS,
+ (uint8_t *)&vf->vsi->eth_stats,
+ sizeof(vf->vsi->eth_stats));
+ else
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+ I40E_NOT_SUPPORTED,
+ (uint8_t *)&vf->vsi->eth_stats,
+ sizeof(vf->vsi->eth_stats));

return I40E_SUCCESS;
}
@@ -851,12 +955,21 @@
i40e_pf_host_process_cmd_cfg_vlan_offload(
struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_offload_info *offload =
(struct i40e_virtchnl_vlan_offload_info *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*offload)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -877,12 +990,21 @@
static int
i40e_pf_host_process_cmd_cfg_pvid(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_pvid_info *tpid_info =
(struct i40e_virtchnl_pvid_info *)msg;

+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CFG_VLAN_PVID,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*tpid_info)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -923,6 +1045,8 @@
struct i40e_pf_vf *vf;
/* AdminQ will pass absolute VF id, transfer to internal vf id */
uint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id;
+ struct rte_pmd_i40e_mb_event_param cb_param;
+ bool b_op = TRUE;

if (vf_id > pf->vf_num - 1 || !pf->vfs) {
PMD_DRV_LOG(ERR, "invalid argument");
@@ -937,10 +1061,35 @@
return;
}

+ /**
+ * initialise structure to send to user application
+ * will return response from user in retval field
+ */
+ cb_param.retval = RTE_PMD_I40E_MB_EVENT_PROCEED;
+ cb_param.vfid = vf_id;
+ cb_param.msg_type = opcode;
+ cb_param.msg = (void *)msg;
+ cb_param.msglen = msglen;
+
+ /**
+ * Ask user application if we're allowed to perform those functions.
+ * If we get cb_param.retval == RTE_PMD_I40E_MB_EVENT_PROCEED,
+ * then business as usual.
+ * If RTE_PMD_I40E_MB_EVENT_NOOP_ACK or RTE_PMD_I40E_MB_EVENT_NOOP_NACK,
+ * do nothing and send not_supported to VF. As PF must send a response
+ * to VF and ACK/NACK is not defined.
+ */
+ _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
+ if (cb_param.retval != RTE_PMD_I40E_MB_EVENT_PROCEED) {
+ PMD_DRV_LOG(WARNING, "VF to PF message(%d) is not permitted!",
+ opcode);
+ b_op = FALSE;
+ }
+
switch (opcode) {
case I40E_VIRTCHNL_OP_VERSION :
PMD_DRV_LOG(INFO, "OP_VERSION received");
- i40e_pf_host_process_cmd_version(vf);
+ i40e_pf_host_process_cmd_version(vf, b_op);
break;
case I40E_VIRTCHNL_OP_RESET_VF :
PMD_DRV_LOG(INFO, "OP_RESET_VF received");
@@ -948,61 +1097,72 @@
break;
case I40E_VIRTCHNL_OP_GET_VF_RESOURCES:
PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received");
- i40e_pf_host_process_cmd_get_vf_resource(vf);
+ i40e_pf_host_process_cmd_get_vf_resource(vf, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received");
- i40e_pf_host_process_cmd_config_vsi_queues(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT:
PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES_EXT received");
i40e_pf_host_process_cmd_config_vsi_queues_ext(vf, msg,
- msglen);
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP:
PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received");
- i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
- i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
- i40e_notify_vf_link_status(dev, vf);
+ if (b_op) {
+ i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
+ i40e_notify_vf_link_status(dev, vf);
+ } else {
+ i40e_pf_host_send_msg_to_vf(
+ vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ }
break;
case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
- i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen);
+ i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS:
PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received");
- i40e_pf_host_process_cmd_add_ether_address(vf, msg, msglen);
+ i40e_pf_host_process_cmd_add_ether_address(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS:
PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received");
- i40e_pf_host_process_cmd_del_ether_address(vf, msg, msglen);
+ i40e_pf_host_process_cmd_del_ether_address(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_ADD_VLAN:
PMD_DRV_LOG(INFO, "OP_ADD_VLAN received");
- i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen);
+ i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_DEL_VLAN:
PMD_DRV_LOG(INFO, "OP_DEL_VLAN received");
- i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen);
+ i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received");
- i40e_pf_host_process_cmd_config_promisc_mode(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_GET_STATS:
PMD_DRV_LOG(INFO, "OP_GET_STATS received");
- i40e_pf_host_process_cmd_get_stats(vf);
+ i40e_pf_host_process_cmd_get_stats(vf, b_op);
break;
case I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD:
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received");
- i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen);
+ i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg,
+ msglen, b_op);
break;
case I40E_VIRTCHNL_OP_CFG_VLAN_PVID:
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_PVID received");
- i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen);
+ i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen, b_op);
break;
/* Don't add command supported below, which will
* return an error code.
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 14852f2..eb7a72b 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -42,6 +42,27 @@
#include <rte_ethdev.h>

/**
+ * Response sent back to i40e driver from user app after callback
+ */
+enum rte_pmd_i40e_mb_event_rsp {
+ RTE_PMD_I40E_MB_EVENT_NOOP_ACK, /**< skip mbox request and ACK */
+ RTE_PMD_I40E_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+ RTE_PMD_I40E_MB_EVENT_PROCEED, /**< proceed with mbox request */
+ RTE_PMD_I40E_MB_EVENT_MAX /**< max value of this enum */
+};
+
+/**
+ * Data sent to the user application when the callback is executed.
+ */
+struct rte_pmd_i40e_mb_event_param {
+ uint16_t vfid; /**< Virtual Function number */
+ uint16_t msg_type; /**< VF to PF message type, see i40e_virtchnl_ops */
+ uint16_t retval; /**< return value */
+ void *msg; /**< pointer to message */
+ uint16_t msglen; /**< length of the message */
+};
+
+/**
* Notify VF when PF link status changes.
*
* @param port
--
1.9.3
Ferruh Yigit
2016-12-07 12:44:43 UTC
Permalink
Post by Wenzhuo Lu
The callback asks the user application if it is allowed to
perform the mailbox messages.
If the return value from user is RTE_PMD_I40E_MB_EVENT_PROCEED
then continue. If ACK or NACK, do nothing and send
not_supported to VF.
---
drivers/net/i40e/i40e_pf.c | 230 ++++++++++++++++++++++++++++++++++------
drivers/net/i40e/rte_pmd_i40e.h | 21 ++++
2 files changed, 216 insertions(+), 35 deletions(-)
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index f70712b..8b8a14f 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -55,6 +55,7 @@
#include "i40e_ethdev.h"
#include "i40e_rxtx.h"
#include "i40e_pf.h"
+#include "rte_pmd_i40e.h"
#define I40E_CFG_CRCSTRIP_DEFAULT 1
@@ -272,14 +273,23 @@
}
static void
-i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf, bool b_op)
{
struct i40e_virtchnl_version_info info;
info.major = I40E_DPDK_VERSION_MAJOR;
info.minor = I40E_DPDK_VERSION_MINOR;
- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
- I40E_SUCCESS, (uint8_t *)&info, sizeof(info));
+
+ if (b_op)
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+ I40E_SUCCESS,
+ (uint8_t *)&info,
+ sizeof(info));
+ else
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+ I40E_NOT_SUPPORTED,
+ (uint8_t *)&info,
+ sizeof(info));
Even I40E_NOT_SUPPORTED returned to the VF, it seems VF is ignoring this
value, is it something should be fixed as part of this patch?

This path is a little complex, I may be missing something but stack
trace is:

VF:
i40evf_check_api_version()
i40evf_execute_vf_cmd(vfd_cmd_info arg)
i40e_aq_send_msg_to_pf(arg->op, retval, arg->in_msg)
desc <- op, retval
msg_in <- arg_in_msg
i40e_asq_send_command(desc, msg_in)

PF:
i40e_pf_host_handle_vf_msg(op, msg_in)
i40e_pf_host_process_cmd_version()
i40e_pf_host_send_msg_to_vf(op, retval, msg_out)
i40e_aq_send_msg_to_vf(op, retval, msg_out)
desc <- op, retval
i40e_asq_send_command(desc, msg_out)

VF:
data <- arg->out_xxx
i40evf_read_pfmsg(data)
event <- data->out_msg
op <-
retval <-
i40e_clean_arq_element(event)
event->desc <- desc
event->msg <- msg_out
data->result = retval <----------------
return 0;
ver = arg->out_msg
return 0;


So, as far as I can see I40E_NOT_SUPPORTED is somewhere in the stack but
not reached to the final VF function, is this OK?
Post by Wenzhuo Lu
}
static int
@@ -292,13 +302,20 @@
}
static int
-i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf, bool b_op)
{
struct i40e_virtchnl_vf_resource *vf_res = NULL;
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
uint32_t len = 0;
int ret = I40E_SUCCESS;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(vf,
+ I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
/* only have 1 VSI by default */
len = sizeof(struct i40e_virtchnl_vf_resource) +
I40E_DEFAULT_VF_VSI_NUM *
@@ -423,7 +440,8 @@
static int
i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_vsi *vsi = vf->vsi;
@@ -432,6 +450,13 @@
struct i40e_virtchnl_queue_pair_info *vc_qpi;
int i, ret = I40E_SUCCESS;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(vf,
+ I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP ||
msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci,
@@ -482,7 +507,8 @@
static int
i40e_pf_host_process_cmd_config_vsi_queues_ext(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_vsi *vsi = vf->vsi;
@@ -491,6 +517,14 @@
struct i40e_virtchnl_queue_pair_ext_info *vc_qpei;
int i, ret = I40E_SUCCESS;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (!msg || vc_vqcei->num_queue_pairs > vsi->nb_qps ||
vc_vqcei->num_queue_pairs > I40E_MAX_VSI_QP ||
msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei,
@@ -539,12 +573,21 @@
static int
i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
- uint8_t *msg, uint16_t msglen)
+ uint8_t *msg, uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_irq_map_info *irqmap =
(struct i40e_virtchnl_irq_map_info *)msg;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen < sizeof(struct i40e_virtchnl_irq_map_info)) {
PMD_DRV_LOG(ERR, "buffer too short");
ret = I40E_ERR_PARAM;
@@ -646,12 +689,21 @@
static int
i40e_pf_host_process_cmd_disable_queues(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_queue_select *q_sel =
(struct i40e_virtchnl_queue_select *)msg;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*q_sel)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -669,7 +721,8 @@
static int
i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -678,6 +731,14 @@
int i;
struct ether_addr *mac;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
memset(&filter, 0 , sizeof(struct i40e_mac_filter_info));
if (msg == NULL || msglen <= sizeof(*addr_list)) {
@@ -707,7 +768,8 @@
static int
i40e_pf_host_process_cmd_del_ether_address(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -715,6 +777,14 @@
int i;
struct ether_addr *mac;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*addr_list)) {
PMD_DRV_LOG(ERR, "delete_ether_address argument too short");
ret = I40E_ERR_PARAM;
@@ -739,7 +809,8 @@
static int
i40e_pf_host_process_cmd_add_vlan(struct i40e_pf_vf *vf,
- uint8_t *msg, uint16_t msglen)
+ uint8_t *msg, uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -747,6 +818,14 @@
int i;
uint16_t *vid;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_ADD_VLAN,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
PMD_DRV_LOG(ERR, "add_vlan argument too short");
ret = I40E_ERR_PARAM;
@@ -771,7 +850,8 @@
static int
i40e_pf_host_process_cmd_del_vlan(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -779,6 +859,14 @@
int i;
uint16_t *vid;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_DEL_VLAN,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
PMD_DRV_LOG(ERR, "delete_vlan argument too short");
ret = I40E_ERR_PARAM;
@@ -803,7 +891,8 @@
i40e_pf_host_process_cmd_config_promisc_mode(
struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_promisc_info *promisc =
@@ -811,6 +900,14 @@
struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
bool unicast = FALSE, multicast = FALSE;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*promisc)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -836,13 +933,20 @@
}
static int
-i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf, bool b_op)
{
i40e_update_vsi_stats(vf->vsi);
- i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
- I40E_SUCCESS, (uint8_t *)&vf->vsi->eth_stats,
- sizeof(vf->vsi->eth_stats));
+ if (b_op)
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+ I40E_SUCCESS,
+ (uint8_t *)&vf->vsi->eth_stats,
+ sizeof(vf->vsi->eth_stats));
+ else
+ i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+ I40E_NOT_SUPPORTED,
+ (uint8_t *)&vf->vsi->eth_stats,
+ sizeof(vf->vsi->eth_stats));
return I40E_SUCCESS;
}
@@ -851,12 +955,21 @@
i40e_pf_host_process_cmd_cfg_vlan_offload(
struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_vlan_offload_info *offload =
(struct i40e_virtchnl_vlan_offload_info *)msg;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*offload)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -877,12 +990,21 @@
static int
i40e_pf_host_process_cmd_cfg_pvid(struct i40e_pf_vf *vf,
uint8_t *msg,
- uint16_t msglen)
+ uint16_t msglen,
+ bool b_op)
{
int ret = I40E_SUCCESS;
struct i40e_virtchnl_pvid_info *tpid_info =
(struct i40e_virtchnl_pvid_info *)msg;
+ if (!b_op) {
+ i40e_pf_host_send_msg_to_vf(
+ vf,
+ I40E_VIRTCHNL_OP_CFG_VLAN_PVID,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ return ret;
+ }
+
if (msg == NULL || msglen != sizeof(*tpid_info)) {
ret = I40E_ERR_PARAM;
goto send_msg;
@@ -923,6 +1045,8 @@
struct i40e_pf_vf *vf;
/* AdminQ will pass absolute VF id, transfer to internal vf id */
uint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id;
+ struct rte_pmd_i40e_mb_event_param cb_param;
+ bool b_op = TRUE;
if (vf_id > pf->vf_num - 1 || !pf->vfs) {
PMD_DRV_LOG(ERR, "invalid argument");
@@ -937,10 +1061,35 @@
return;
}
+ /**
+ * initialise structure to send to user application
+ * will return response from user in retval field
+ */
+ cb_param.retval = RTE_PMD_I40E_MB_EVENT_PROCEED;
+ cb_param.vfid = vf_id;
+ cb_param.msg_type = opcode;
+ cb_param.msg = (void *)msg;
+ cb_param.msglen = msglen;
+
+ /**
+ * Ask user application if we're allowed to perform those functions.
+ * If we get cb_param.retval == RTE_PMD_I40E_MB_EVENT_PROCEED,
+ * then business as usual.
+ * If RTE_PMD_I40E_MB_EVENT_NOOP_ACK or RTE_PMD_I40E_MB_EVENT_NOOP_NACK,
+ * do nothing and send not_supported to VF. As PF must send a response
+ * to VF and ACK/NACK is not defined.
+ */
+ _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
+ if (cb_param.retval != RTE_PMD_I40E_MB_EVENT_PROCEED) {
+ PMD_DRV_LOG(WARNING, "VF to PF message(%d) is not permitted!",
+ opcode);
+ b_op = FALSE;
+ }
+
Is the reason you just not do [1], because final function requires valid
buffers? Can it be an option to fix them?

[1]
if (!b_op) {
i40e_pf_host_send_msg_to_vf(vf, opcode, I40E_NOT_SUPPORTED, NULL, 0);
}
Post by Wenzhuo Lu
switch (opcode) {
PMD_DRV_LOG(INFO, "OP_VERSION received");
- i40e_pf_host_process_cmd_version(vf);
+ i40e_pf_host_process_cmd_version(vf, b_op);
break;
PMD_DRV_LOG(INFO, "OP_RESET_VF received");
@@ -948,61 +1097,72 @@
break;
PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received");
- i40e_pf_host_process_cmd_get_vf_resource(vf);
+ i40e_pf_host_process_cmd_get_vf_resource(vf, b_op);
break;
PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received");
- i40e_pf_host_process_cmd_config_vsi_queues(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
+ msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES_EXT received");
i40e_pf_host_process_cmd_config_vsi_queues_ext(vf, msg,
- msglen);
+ msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received");
- i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
- i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
- i40e_notify_vf_link_status(dev, vf);
+ if (b_op) {
+ i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
+ i40e_notify_vf_link_status(dev, vf);
+ } else {
+ i40e_pf_host_send_msg_to_vf(
+ vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+ I40E_NOT_SUPPORTED, NULL, 0);
+ }
break;
PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
- i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen);
+ i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received");
- i40e_pf_host_process_cmd_add_ether_address(vf, msg, msglen);
+ i40e_pf_host_process_cmd_add_ether_address(vf, msg,
+ msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received");
- i40e_pf_host_process_cmd_del_ether_address(vf, msg, msglen);
+ i40e_pf_host_process_cmd_del_ether_address(vf, msg,
+ msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_ADD_VLAN received");
- i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen);
+ i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_DEL_VLAN received");
- i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen);
+ i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received");
- i40e_pf_host_process_cmd_config_promisc_mode(vf, msg, msglen);
+ i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
+ msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_GET_STATS received");
- i40e_pf_host_process_cmd_get_stats(vf);
+ i40e_pf_host_process_cmd_get_stats(vf, b_op);
break;
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received");
- i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen);
+ i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg,
+ msglen, b_op);
break;
PMD_DRV_LOG(INFO, "OP_CFG_VLAN_PVID received");
- i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen);
+ i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen, b_op);
break;
/* Don't add command supported below, which will
* return an error code.
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 14852f2..eb7a72b 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -42,6 +42,27 @@
#include <rte_ethdev.h>
/**
+ * Response sent back to i40e driver from user app after callback
+ */
+enum rte_pmd_i40e_mb_event_rsp {
+ RTE_PMD_I40E_MB_EVENT_NOOP_ACK, /**< skip mbox request and ACK */
+ RTE_PMD_I40E_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+ RTE_PMD_I40E_MB_EVENT_PROCEED, /**< proceed with mbox request */
+ RTE_PMD_I40E_MB_EVENT_MAX /**< max value of this enum */
+};
+
+/**
+ * Data sent to the user application when the callback is executed.
+ */
+struct rte_pmd_i40e_mb_event_param {
+ uint16_t vfid; /**< Virtual Function number */
+ uint16_t msg_type; /**< VF to PF message type, see i40e_virtchnl_ops */
+ uint16_t retval; /**< return value */
+ void *msg; /**< pointer to message */
+ uint16_t msglen; /**< length of the message */
+};
+
+/**
* Notify VF when PF link status changes.
*
Wenzhuo Lu
2016-12-07 03:31:46 UTC
Permalink
Support enabling/disabling VF MAC anti-spoofing from
PF.
User can call the API on PF to enable/disable a specific
VF's MAC anti-spoofing.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 63 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 83 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index fda1454..0821734 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -9763,3 +9763,66 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return 0;
}
+
+int
+rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ struct i40e_hw *hw;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ /* Check if it has been already on or off */
+ if (vsi->info.valid_sections &
+ rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SECURITY_VALID)) {
+ if (on) {
+ if ((vsi->info.sec_flags &
+ I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
+ I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
+ return 0; /* already on */
+ } else {
+ if ((vsi->info.sec_flags &
+ I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
+ return 0; /* already off */
+ }
+ }
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+ if (on)
+ vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+ else
+ vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index eb7a72b..52319cf 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -76,4 +76,23 @@ struct rte_pmd_i40e_mb_event_param {
*/
int rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf);

+/**
+ * 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_i40e_set_vf_mac_anti_spoof(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 4555446..30efb08 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -7,4 +7,5 @@ DPDK_17.02 {
global:

rte_pmd_i40e_ping_vfs;
+ rte_pmd_i40e_set_vf_mac_anti_spoof;
} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:47 UTC
Permalink
Support enabling/disabling VF VLAN anti-spoofing from
PF.
User can call the API on PF to enable/disable a specific
VF's VLAN anti-spoofing.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 116 +++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/rte_pmd_i40e.h | 19 +++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
4 files changed, 135 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 0821734..ec863b9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -4418,6 +4418,7 @@ struct i40e_vsi *
vsi->max_macaddrs = I40E_NUM_MACADDR_MAX;
vsi->parent_vsi = uplink_vsi ? uplink_vsi : pf->main_vsi;
vsi->user_param = user_param;
+ vsi->vlan_anti_spoof_on = 0;
/* Allocate queues */
switch (vsi->type) {
case I40E_VSI_MAIN :
@@ -5761,17 +5762,35 @@ struct i40e_vsi *
uint16_t vlan_id, bool on)
{
uint32_t vid_idx, vid_bit;
+ struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+ struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+ int ret;

if (vlan_id > ETH_VLAN_ID_MAX)
return;

vid_idx = I40E_VFTA_IDX(vlan_id);
vid_bit = I40E_VFTA_BIT(vlan_id);
+ vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);

- if (on)
+ if (on) {
+ if (vsi->vlan_anti_spoof_on) {
+ ret = i40e_aq_add_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to add vlan filter");
+ }
vsi->vfta[vid_idx] |= vid_bit;
- else
+ } else {
+ if (vsi->vlan_anti_spoof_on) {
+ ret = i40e_aq_remove_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR,
+ "Failed to remove vlan filter");
+ }
vsi->vfta[vid_idx] &= ~vid_bit;
+ }
}

/**
@@ -9826,3 +9845,96 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+static int
+i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
+{
+ uint32_t j, k;
+ uint16_t vlan_id;
+ struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+ struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+ int ret;
+
+ for (j = 0; j < I40E_VFTA_SIZE; j++) {
+ if (!vsi->vfta[j])
+ continue;
+
+ for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
+ if (!(vsi->vfta[j] & (1 << k)))
+ continue;
+
+ vlan_id = j * I40E_UINT32_BIT_SIZE + k;
+ vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
+ if (add)
+ ret = i40e_aq_add_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ else
+ ret = i40e_aq_remove_vlan(hw, vsi->seid,
+ &vlan_data, 1, NULL);
+ if (ret != I40E_SUCCESS) {
+ PMD_DRV_LOG(ERR,
+ "Failed to add/rm vlan filter");
+ return ret;
+ }
+ }
+ }
+
+ return I40E_SUCCESS;
+}
+
+int
+rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ struct i40e_hw *hw;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ /* Check if it has been already on or off */
+ if (vsi->vlan_anti_spoof_on == on)
+ return 0; /* already on or off */
+
+ vsi->vlan_anti_spoof_on = on;
+ ret = i40e_add_rm_all_vlan_filter(vsi, on);
+ if (ret)
+ return ret;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+ if (on)
+ vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+ else
+ vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 298cef4..0db140b 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -300,6 +300,7 @@ struct i40e_vsi {
uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
uint16_t nb_msix; /* The max number of msix vector */
uint8_t enabled_tc; /* The traffic class enabled */
+ uint8_t vlan_anti_spoof_on; /* The VLAN anti-spoofing enabled */
struct i40e_bw_info bw_info; /* VSI bandwidth information */
};

diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 52319cf..c8736c8 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -95,4 +95,23 @@ int rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port,
uint16_t vf_id,
uint8_t 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 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_i40e_set_vf_vlan_anti_spoof(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 30efb08..fff6cf9 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -8,4 +8,5 @@ DPDK_17.02 {

rte_pmd_i40e_ping_vfs;
rte_pmd_i40e_set_vf_mac_anti_spoof;
+ rte_pmd_i40e_set_vf_vlan_anti_spoof;
} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:48 UTC
Permalink
Support enabling/disabling TX loopback from PF.
User can call the API on PF to enable/disable TX loopback
for all the PF and VFs.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 219 ++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 16 +++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 236 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index ec863b9..8bd0d70 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -9938,3 +9938,222 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+static int
+i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
+{
+ struct i40e_mac_filter *f;
+ struct i40e_macvlan_filter *mv_f;
+ int i, vlan_num;
+ enum rte_mac_filter_type filter_type;
+ int ret = I40E_SUCCESS;
+
+ /* remove all the MACs */
+ TAILQ_FOREACH(f, &vsi->mac_list, next) {
+ vlan_num = vsi->vlan_num;
+ filter_type = f->mac_info.filter_type;
+ if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+ filter_type == RTE_MACVLAN_HASH_MATCH) {
+ if (vlan_num == 0) {
+ PMD_DRV_LOG(ERR,
+ "VLAN number shouldn't be 0\n");
+ return I40E_ERR_PARAM;
+ }
+ } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
+ filter_type == RTE_MAC_HASH_MATCH)
+ vlan_num = 1;
+
+ mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+ if (!mv_f) {
+ PMD_DRV_LOG(ERR, "failed to allocate memory");
+ return I40E_ERR_NO_MEMORY;
+ }
+
+ for (i = 0; i < vlan_num; i++) {
+ mv_f[i].filter_type = filter_type;
+ (void)rte_memcpy(&mv_f[i].macaddr,
+ &f->mac_info.mac_addr,
+ ETH_ADDR_LEN);
+ }
+ if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+ filter_type == RTE_MACVLAN_HASH_MATCH) {
+ ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+ &f->mac_info.mac_addr);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+ }
+
+ ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+
+ rte_free(mv_f);
+ ret = I40E_SUCCESS;
+ }
+
+ return ret;
+}
+
+static int
+i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
+{
+ struct i40e_mac_filter *f;
+ struct i40e_macvlan_filter *mv_f;
+ int i, vlan_num = 0;
+ int ret = I40E_SUCCESS;
+
+ /* restore all the MACs */
+ TAILQ_FOREACH(f, &vsi->mac_list, next) {
+ if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
+ (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
+ /**
+ * If vlan_num is 0, that's the first time to add mac,
+ * set mask for vlan_id 0.
+ */
+ if (vsi->vlan_num == 0) {
+ i40e_set_vlan_filter(vsi, 0, 1);
+ vsi->vlan_num = 1;
+ }
+ vlan_num = vsi->vlan_num;
+ } else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
+ (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
+ vlan_num = 1;
+
+ mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+ if (!mv_f) {
+ PMD_DRV_LOG(ERR, "failed to allocate memory");
+ return I40E_ERR_NO_MEMORY;
+ }
+
+ for (i = 0; i < vlan_num; i++) {
+ mv_f[i].filter_type = f->mac_info.filter_type;
+ (void)rte_memcpy(&mv_f[i].macaddr,
+ &f->mac_info.mac_addr,
+ ETH_ADDR_LEN);
+ }
+
+ if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+ f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
+ ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+ &f->mac_info.mac_addr);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+ }
+
+ ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
+ if (ret != I40E_SUCCESS) {
+ rte_free(mv_f);
+ return ret;
+ }
+
+ rte_free(mv_f);
+ ret = I40E_SUCCESS;
+ }
+
+ return ret;
+}
+
+static int
+i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+{
+ struct i40e_vsi_context ctxt;
+ struct i40e_hw *hw;
+ int ret;
+
+ hw = I40E_VSI_TO_HW(vsi);
+
+ /* Use the FW API if FW >= v5.0 */
+ if (hw->aq.fw_maj_ver < 5) {
+ PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
+ return -ENOTSUP;
+ }
+
+ /* Check if it has been already on or off */
+ if (vsi->info.valid_sections &
+ rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
+ if (on) {
+ if ((vsi->info.switch_id &
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
+ return 0; /* already on */
+ } else {
+ if ((vsi->info.switch_id &
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
+ return 0; /* already off */
+ }
+ }
+
+ /* remove all the MACs first */
+ ret = i40e_vsi_rm_mac_filter(vsi);
+ if (ret)
+ return ret;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+ if (on)
+ vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+ else
+ vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS) {
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+ return ret;
+ }
+
+ /* add all the MACs back */
+ ret = i40e_vsi_restore_mac_filter(vsi);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+int
+rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ uint16_t vf_id;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ /* setup PF TX loopback */
+ vsi = pf->main_vsi;
+ ret = i40e_vsi_set_tx_loopback(vsi, on);
+ if (ret)
+ return ret;
+
+ /* setup TX loopback for all the VFs */
+ if (!pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ ret = i40e_vsi_set_tx_loopback(vsi, on);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index c8736c8..3c65be4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -114,4 +114,20 @@ int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
uint16_t vf_id,
uint8_t on);

+/**
+ * Enable/Disable TX loopback on all the PF and VFs.
+ *
+ * @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_i40e_set_tx_loopback(uint8_t port,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index fff6cf9..3da04d3 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -9,4 +9,5 @@ DPDK_17.02 {
rte_pmd_i40e_ping_vfs;
rte_pmd_i40e_set_vf_mac_anti_spoof;
rte_pmd_i40e_set_vf_vlan_anti_spoof;
+ rte_pmd_i40e_set_tx_loopback;
} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-07 13:04:47 UTC
Permalink
Post by Wenzhuo Lu
Support enabling/disabling TX loopback from PF.
User can call the API on PF to enable/disable TX loopback
for all the PF and VFs.
---
drivers/net/i40e/i40e_ethdev.c | 219 ++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 16 +++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 236 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index ec863b9..8bd0d70 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -9938,3 +9938,222 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
return ret;
}
+
<...>
Post by Wenzhuo Lu
+
+static int
+i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+{
+ struct i40e_vsi_context ctxt;
+ struct i40e_hw *hw;
+ int ret;
+
+ hw = I40E_VSI_TO_HW(vsi);
+
+ /* Use the FW API if FW >= v5.0 */
+ if (hw->aq.fw_maj_ver < 5) {
+ PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
+ return -ENOTSUP;
+ }
+
+ /* Check if it has been already on or off */
+ if (vsi->info.valid_sections &
+ rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
+ if (on) {
+ if ((vsi->info.switch_id &
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
+ return 0; /* already on */
+ } else {
+ if ((vsi->info.switch_id &
+ I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
+ return 0; /* already off */
+ }
+ }
+
+ /* remove all the MACs first */
+ ret = i40e_vsi_rm_mac_filter(vsi);
+ if (ret)
+ return ret;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+ if (on)
+ vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+ else
+ vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+
---->
Post by Wenzhuo Lu
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS) {
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+ return ret;
+ }
<----

This part is now duplicated in a few functions, does it make sense to
make it separate function, in the first patch it appeared 3/32 ?
Post by Wenzhuo Lu
+
+ /* add all the MACs back */
+ ret = i40e_vsi_restore_mac_filter(vsi);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+int
+rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ uint16_t vf_id;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ /* setup PF TX loopback */
+ vsi = pf->main_vsi;
+ ret = i40e_vsi_set_tx_loopback(vsi, on);
+ if (ret)
+ return ret;
+
+ /* setup TX loopback for all the VFs */
+ if (!pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ ret = i40e_vsi_set_tx_loopback(vsi, on);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index c8736c8..3c65be4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -114,4 +114,20 @@ int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
uint16_t vf_id,
uint8_t on);
+/**
+ * Enable/Disable TX loopback on all the PF and VFs.
+ *
+ * The port identifier of the Ethernet device.
+ * 1 - Enable TX loopback.
+ * 0 - Disable TX loopback.
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_tx_loopback(uint8_t port,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index fff6cf9..3da04d3 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -9,4 +9,5 @@ DPDK_17.02 {
rte_pmd_i40e_ping_vfs;
rte_pmd_i40e_set_vf_mac_anti_spoof;
rte_pmd_i40e_set_vf_vlan_anti_spoof;
+ rte_pmd_i40e_set_tx_loopback;
We can add these alphabetically.
This may not worth to create a new version of the patch itself, but can
be fixed if a new version already required..
Post by Wenzhuo Lu
} DPDK_2.0;
Wenzhuo Lu
2016-12-07 03:31:49 UTC
Permalink
Support enabling/disabling VF unicast promiscuous mode from
PF.
User can call the API on PF to enable/disable a specific
VF's unicast promiscuous mode.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 36 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 56 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8bd0d70..18ac2f0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10157,3 +10157,39 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ hw = I40E_VSI_TO_HW(vf->vsi);
+
+ ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vf->vsi->seid,
+ on, NULL, true);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set unicast promiscuous mode");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 3c65be4..4c98136 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -130,4 +130,23 @@ int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
int rte_pmd_i40e_set_tx_loopback(uint8_t port,
uint8_t on);

+/**
+ * Enable/Disable VF unicast promiscuous mode.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * VF on which to set.
+ * @param on
+ * 1 - Enable.
+ * 0 - Disable.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 3da04d3..24b78ce 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -10,4 +10,5 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_mac_anti_spoof;
rte_pmd_i40e_set_vf_vlan_anti_spoof;
rte_pmd_i40e_set_tx_loopback;
+ rte_pmd_i40e_set_vf_unicast_promisc;
} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:50 UTC
Permalink
Support enabling/disabling VF multicast promiscuous mode from
PF.
User can call the API on PF to enable/disable a specific
VF's multicast promiscuous mode.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 36 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 56 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 18ac2f0..88ff6aa 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10193,3 +10193,39 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vf = &pf->vfs[vf_id];
+ hw = I40E_VSI_TO_HW(vf->vsi);
+
+ ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid,
+ on, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set multicast promiscuous mode");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 4c98136..9091520 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -149,4 +149,23 @@ int rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port,
uint16_t vf_id,
uint8_t on);

+/**
+ * Enable/Disable VF multicast promiscuous mode.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * VF on which to set.
+ * @param on
+ * 1 - Enable.
+ * 0 - Disable.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
+ uint16_t vf_id,
+ uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 24b78ce..08d3028 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -11,4 +11,5 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_vlan_anti_spoof;
rte_pmd_i40e_set_tx_loopback;
rte_pmd_i40e_set_vf_unicast_promisc;
+ rte_pmd_i40e_set_vf_multicast_promisc;
} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:51 UTC
Permalink
This patch implement mtu_set ops for i40e VF.

Signed-off-by: Qi Zhang <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index aa306d6..262c4c1 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -151,6 +151,7 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
+static int i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
static int
i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
static int
@@ -225,6 +226,7 @@ struct rte_i40evf_xstats_name_off {
.reta_query = i40evf_dev_rss_reta_query,
.rss_hash_update = i40evf_dev_rss_hash_update,
.rss_hash_conf_get = i40evf_dev_rss_hash_conf_get,
+ .mtu_set = i40evf_dev_mtu_set,
};

/*
@@ -2635,3 +2637,34 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,

return 0;
}
+
+static int
+i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct rte_eth_dev_data *dev_data = vf->dev_data;
+ uint32_t frame_size = mtu + ETHER_HDR_LEN
+ + ETHER_CRC_LEN + I40E_VLAN_TAG_SIZE;
+ int ret = 0;
+
+ /* check if mtu is within the allowed range */
+ if ((mtu < ETHER_MIN_MTU) || (frame_size > I40E_FRAME_SIZE_MAX))
+ return -EINVAL;
+
+ /* mtu setting is forbidden if port is start */
+ if (dev_data->dev_started) {
+ PMD_DRV_LOG(ERR,
+ "port %d must be stopped before configuration\n",
+ dev_data->port_id);
+ return -EBUSY;
+ }
+
+ if (frame_size > ETHER_MAX_LEN)
+ dev_data->dev_conf.rxmode.jumbo_frame = 1;
+ else
+ dev_data->dev_conf.rxmode.jumbo_frame = 0;
+
+ dev_data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+
+ return ret;
+}
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:52 UTC
Permalink
This patch add below two APIs so that VF statistics
can be get/clear from PF side.
rte_eth_vf_stats_get.
rte_eth_vf_stats_reset.

Signed-off-by: Qi Zhang <***@intel.com>
---
lib/librte_ether/rte_ethdev.c | 47 +++++++++++++++++++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 47 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index fde8112..03b4edf 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3270,3 +3270,50 @@ int rte_eth_dev_bypass_init(uint8_t port_id)
-ENOTSUP);
return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
}
+
+int
+rte_eth_vf_stats_get(uint8_t port_id,
+ uint16_t vf,
+ struct rte_eth_stats *stats)
+{
+ 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);
+
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_stats_get, -ENOTSUP);
+
+ if (vf >= dev_info.max_vfs) {
+ RTE_PMD_DEBUG_TRACE("Get VF Stats:port %d: "
+ "invalid vf id=%d\n", port_id, vf);
+ return -EINVAL;
+ }
+
+ return (*dev->dev_ops->vf_stats_get)(dev, vf, stats);
+}
+
+int
+rte_eth_vf_stats_reset(uint8_t port_id,
+ uint16_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);
+
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vf_stats_reset, -ENOTSUP);
+
+ if (vf >= dev_info.max_vfs) {
+ RTE_PMD_DEBUG_TRACE("Reset VF Stats:port %d: "
+ "invalid vf id=%d\n", port_id, vf);
+ return -EINVAL;
+ }
+
+ return (*dev->dev_ops->vf_stats_reset)(dev, vf);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..8b564ee 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1271,6 +1271,15 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
uint8_t vlan_on);
/**< @internal Set VF VLAN pool filter */

+typedef int (*eth_vf_stats_get)(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+/**< @internal Get VF statistics */
+
+typedef int (*eth_vf_stats_reset)(struct rte_eth_dev *dev,
+ uint16_t vf);
+/**< @internal Clear VF statistics */
+
typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t tx_rate);
@@ -1483,6 +1492,8 @@ 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_vf_stats_get vf_stats_get; /**< Get VF's statistics */
+ eth_vf_stats_reset vf_stats_reset; /**< Reset VF's statistics */
/** Add UDP tunnel port. */
eth_udp_tunnel_port_add_t udp_tunnel_port_add;
/** Del UDP tunnel port. */
@@ -4379,6 +4390,42 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);

+/**
+ * Get VF's statistics
+ *
+ * @param port_id
+ * pointer to port identifier of the device
+ * @param vf
+ * VF id
+ * @param stats
+ * A pointer to a structure of type *rte_eth_stats* to be filled with
+ * the values of device counters for the following set of statistics:
+ * - *ipackets* with the total of successfully received packets.
+ * - *opackets* with the total of successfully transmitted packets.
+ * - *ibytes* with the total of successfully received bytes.
+ * - *obytes* with the total of successfully transmitted bytes.
+ * - *ierrors* with the total of erroneous received packets.
+ * - *oerrors* with the total of failed transmitted packets.
+ * @return
+ * Zero if successful. Non-zero otherwise.
+ */
+int rte_eth_vf_stats_get(uint8_t port_id,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+
+/**
+ * Clear VF's statistics
+ *
+ * @param port_id
+ * pointer to port identifier of the device
+ * @param vf
+ * vf id
+ * @return
+ * Zero if successful. Non-zero otherwise.
+ */
+int rte_eth_vf_stats_reset(uint8_t port_id,
+ uint16_t vf);
+
#ifdef __cplusplus
}
#endif
--
1.9.3
Ferruh Yigit
2016-12-07 13:52:06 UTC
Permalink
Post by Wenzhuo Lu
This patch add below two APIs so that VF statistics
can be get/clear from PF side.
rte_eth_vf_stats_get.
rte_eth_vf_stats_reset.
patch subject can have " ... from PF" both to be consistent with other
patches and to clarify what it does: add APIS to get/reset VF stats from PF?
Post by Wenzhuo Lu
---
<...>
Post by Wenzhuo Lu
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..8b564ee 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1271,6 +1271,15 @@ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
uint8_t vlan_on);
+typedef int (*eth_vf_stats_get)(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+
+typedef int (*eth_vf_stats_reset)(struct rte_eth_dev *dev,
+ uint16_t vf);
+
typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t tx_rate);
@@ -1483,6 +1492,8 @@ 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_vf_stats_get vf_stats_get; /**< Get VF's statistics */
+ eth_vf_stats_reset vf_stats_reset; /**< Reset VF's statistics */
Do we really want to add more ops to the eth_dev_ops?

Although vf_stats_get & vf_stats_reset sounds generic, why not implement
these first in PMD specific manner, and more PMDs implement these, move
to the generic eth_dev_ops layer?

CC: Thomas

<...>
Wenzhuo Lu
2016-12-07 03:31:53 UTC
Permalink
This patch implement vf_stats_get and vf_stats_reset ops for i40e.

Signed-off-by: Qi Zhang <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 64 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 88ff6aa..5c9d6d1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -462,6 +462,13 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);

+static int i40e_vf_stats_get(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats);
+
+static int i40e_vf_stats_reset(struct rte_eth_dev *dev,
+ uint16_t vf);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -554,6 +561,8 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
.get_eeprom = i40e_get_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set = i40e_dev_mtu_set,
+ .vf_stats_get = i40e_vf_stats_get,
+ .vf_stats_reset = i40e_vf_stats_reset,
};

/* store statistics names and its offset in stats structure */
@@ -10229,3 +10238,58 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+static int
+i40e_vf_stats_get(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_vsi *vsi;
+
+ int ret = 0;
+
+ if (pf->vf_num <= vf) {
+ PMD_DRV_LOG(ERR, "Invalid VF id %d\n", vf);
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf].vsi;
+
+ i40e_update_vsi_stats(vsi);
+
+ stats->ipackets = vsi->eth_stats.rx_unicast +
+ vsi->eth_stats.rx_multicast +
+ vsi->eth_stats.rx_broadcast;
+ stats->opackets = vsi->eth_stats.tx_unicast +
+ vsi->eth_stats.tx_multicast +
+ vsi->eth_stats.tx_broadcast;
+ stats->ibytes = vsi->eth_stats.rx_bytes;
+ stats->obytes = vsi->eth_stats.tx_bytes;
+ stats->ierrors = vsi->eth_stats.rx_discards;
+ stats->oerrors = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
+
+ return ret;
+}
+
+static int
+i40e_vf_stats_reset(struct rte_eth_dev *dev,
+ uint16_t vf)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_vsi *vsi;
+
+ int ret = 0;
+
+ if (pf->vf_num <= vf) {
+ PMD_DRV_LOG(ERR, "Invalid VF id %d\n", vf);
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf].vsi;
+
+ vsi->offset_loaded = false;
+ i40e_update_vsi_stats(vsi);
+
+ return ret;
+}
--
1.9.3
Ferruh Yigit
2016-12-07 13:59:54 UTC
Permalink
Post by Wenzhuo Lu
This patch implement vf_stats_get and vf_stats_reset ops for i40e.
---
<...>
Post by Wenzhuo Lu
+static int
+i40e_vf_stats_get(struct rte_eth_dev *dev,
+ uint16_t vf,
+ struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_vsi *vsi;
+
+ int ret = 0;
+
+ if (pf->vf_num <= vf) {
+ PMD_DRV_LOG(ERR, "Invalid VF id %d\n", vf);
+ return -EINVAL;
+ }
Do we need following check as it has been done in prev patches:

+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
Wenzhuo Lu
2016-12-07 03:31:54 UTC
Permalink
Add missing step during VF reset: PF should
set I40E_VFGEN_RSTAT to ACTIVE at end of the
VF reset operation or VF driver may not able
to detect that reset is already completed.
This patch also remove the unnecessary enum
for vfr state.

Fixes: 4861cde46116 ("i40e: new poll mode driver")

CC: ***@dpdk.org
Signed-off-by: Qi Zhang <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 6 ++++--
drivers/net/i40e/i40e_pf.h | 5 -----
2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 8b8a14f..2bc3355 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -139,7 +139,7 @@
abs_vf_id = vf_id + hw->func_caps.vf_base_id;

/* Notify VF that we are in VFR progress */
- I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_INPROGRESS);
+ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_INPROGRESS);

/*
* If require a SW VF reset, a VFLR interrupt will be generated,
@@ -220,7 +220,7 @@
}

/* Reset done, Set COMPLETE flag and clear reset bit */
- I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_COMPLETED);
+ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_COMPLETED);
val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
val &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
@@ -248,6 +248,8 @@
return -EFAULT;
}

+ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_VFACTIVE);
+
return ret;
}

diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index 59bf2ee..ada398b 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -48,11 +48,6 @@

#define I40E_DPDK_OFFSET 0x100

-enum i40e_pf_vfr_state {
- I40E_PF_VFR_INPROGRESS = 0,
- I40E_PF_VFR_COMPLETED = 1,
-};
-
/* DPDK pf driver specific command to VF */
enum i40e_virtchnl_ops_dpdk {
/*
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:55 UTC
Permalink
Support setting VF MAC address from PF.
User can call the API on PF to set a specific
VF's MAC address.

This will reset the VF.

Signed-off-by: Ferruh Yigit <***@intel.com>
---
app/test/Makefile | 8 +++
app/test/test_pmd_i40e.c | 96 +++++++++++++++++++++++++++++++
drivers/net/i40e/i40e_ethdev.c | 42 ++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 ++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 2 +
5 files changed, 167 insertions(+)
create mode 100644 app/test/test_pmd_i40e.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..b3f6ecb 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -199,6 +199,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev.c

SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c

+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += test_pmd_i40e.c
+
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)

@@ -228,6 +230,12 @@ endif
endif
endif

+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+ifeq ($(CONFIG_RTE_LIBRTE_I40E_PMD),y)
+LDLIBS += -lrte_pmd_i40e
+endif
+endif
+
ifeq ($(CONFIG_RTE_APP_TEST_RESOURCE_TAR),y)
LDLIBS += -larchive
endif
diff --git a/app/test/test_pmd_i40e.c b/app/test/test_pmd_i40e.c
new file mode 100644
index 0000000..c901e89
--- /dev/null
+++ b/app/test/test_pmd_i40e.c
@@ -0,0 +1,96 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_pmd_i40e.h>
+#include <rte_ethdev.h>
+
+#include "test.h"
+
+#define I40E_DRV_NAME "net_i40e"
+
+static struct ether_addr mac_addr = {
+ { 0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x00 }
+};
+
+static const int max_vfs = 3;
+
+static int
+test_i40e(void)
+{
+ struct rte_eth_dev_info dev_info;
+ struct ether_addr current_mac_addr;
+ uint8_t nb_ports;
+ uint8_t port;
+ int ret = 0;
+ int i;
+
+ nb_ports = rte_eth_dev_count();
+ printf("nb_ports=%d\n", nb_ports);
+
+ for (port = 0; port < nb_ports; port++) {
+ rte_eth_dev_info_get(port, &dev_info);
+
+ printf("%d: %s\n", port, dev_info.driver_name);
+
+ if (strcmp(dev_info.driver_name, I40E_DRV_NAME))
+ continue;
+
+ rte_eth_macaddr_get(port, &current_mac_addr);
+
+ printf("%d: mac address:", port);
+ for (i = 0; i < ETHER_ADDR_LEN - 1; i++)
+ printf("%x:", current_mac_addr.addr_bytes[i]);
+ printf("%x\n", current_mac_addr.addr_bytes[ETHER_ADDR_LEN - 1]);
+
+ for (i = 0; i < max_vfs; i++) {
+ if (i >= dev_info.max_vfs)
+ break;
+
+ mac_addr.addr_bytes[ETHER_ADDR_LEN - 2] = port + 1;
+ mac_addr.addr_bytes[ETHER_ADDR_LEN - 1] = i + 1;
+
+ ret = rte_pmd_i40e_set_vf_mac_addr(port, i, &mac_addr);
+ printf("port:%d vf:%d set mac %s\n",
+ port, i, ret ? "failed" : "succeed");
+ }
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(i40e_autotest, test_i40e);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5c9d6d1..832995a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10293,3 +10293,45 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return ret;
}
+
+int
+rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
+ struct ether_addr *mac_addr)
+{
+ struct rte_eth_dev_info dev_info;
+ struct i40e_mac_filter *f;
+ struct rte_eth_dev *dev;
+ struct i40e_pf_vf *vf;
+ struct i40e_vsi *vsi;
+ struct i40e_pf *pf;
+ void *temp;
+
+ if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+ return -EINVAL;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs)
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ ether_addr_copy(mac_addr, &vf->mac_addr);
+
+ /* Remove all existing mac */
+ TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
+ i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
+
+ i40e_pf_host_vf_reset(vf, 1);
+
+ return 0;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 9091520..ca5e05a 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -168,4 +168,23 @@ int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
uint16_t vf_id,
uint8_t on);

+/**
+ * Set the VF MAC address.
+ *
+ * This will reset the vf.
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf_id
+ * VF id.
+ * @param mac_addr
+ * VF MAC address.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
+ struct ether_addr *mac_addr);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 08d3028..64ba93a 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -12,4 +12,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_tx_loopback;
rte_pmd_i40e_set_vf_unicast_promisc;
rte_pmd_i40e_set_vf_multicast_promisc;
+ rte_pmd_i40e_set_vf_mac_addr;
+
} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-07 14:29:51 UTC
Permalink
Post by Wenzhuo Lu
Support setting VF MAC address from PF.
User can call the API on PF to set a specific
VF's MAC address.
This will reset the VF.
---
<...>
Post by Wenzhuo Lu
+/**
+ * Set the VF MAC address.
+ *
+ * This will reset the vf.
It may be good if I add a comment that this also will remove all
existing mac filters. Same to commit log perhaps.
Post by Wenzhuo Lu
+ *
+ * The port identifier of the Ethernet device.
+ * VF id.
+ * VF MAC address.
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
+ struct ether_addr *mac_addr);
+
<...>
Wenzhuo Lu
2016-12-07 03:31:56 UTC
Permalink
Support changing VF default MAC address.
This function is not supported if PF set the MAC
address for the PF.

Signed-off-by: Ferruh Yigit <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.h | 4 +++-
drivers/net/i40e/i40e_ethdev_vf.c | 48 +++++++++++++++++++++++++++++++++------
2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 0db140b..b687b0c 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -126,6 +126,7 @@ enum i40e_flxpld_layer_idx {
#define I40E_FLAG_FDIR (1ULL << 6)
#define I40E_FLAG_VXLAN (1ULL << 7)
#define I40E_FLAG_RSS_AQ_CAPABLE (1ULL << 8)
+#define I40E_FLAG_VF_MAC_BY_PF (1ULL << 9)
#define I40E_FLAG_ALL (I40E_FLAG_RSS | \
I40E_FLAG_DCB | \
I40E_FLAG_VMDQ | \
@@ -134,7 +135,8 @@ enum i40e_flxpld_layer_idx {
I40E_FLAG_HEADER_SPLIT_ENABLED | \
I40E_FLAG_FDIR | \
I40E_FLAG_VXLAN | \
- I40E_FLAG_RSS_AQ_CAPABLE)
+ I40E_FLAG_RSS_AQ_CAPABLE | \
+ I40E_FLAG_VF_MAC_BY_PF)

#define I40E_RSS_OFFLOAD_ALL ( \
ETH_RSS_FRAG_IPV4 | \
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 262c4c1..cc2d03c 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -152,6 +152,8 @@ static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev,
static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf);
static int i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+static void i40evf_set_default_mac_addr(struct rte_eth_dev *dev,
+ struct ether_addr *mac_addr);
static int
i40evf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
static int
@@ -227,6 +229,7 @@ struct rte_i40evf_xstats_name_off {
.rss_hash_update = i40evf_dev_rss_hash_update,
.rss_hash_conf_get = i40evf_dev_rss_hash_conf_get,
.mtu_set = i40evf_dev_mtu_set,
+ .mac_addr_set = i40evf_set_default_mac_addr,
};

/*
@@ -888,19 +891,15 @@ struct rte_i40evf_xstats_name_off {
}

static void
-i40evf_del_mac_addr(struct rte_eth_dev *dev, uint32_t index)
+i40evf_del_mac_addr_by_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
{
struct i40e_virtchnl_ether_addr_list *list;
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
- struct rte_eth_dev_data *data = dev->data;
- struct ether_addr *addr;
uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_ether_addr_list) + \
sizeof(struct i40e_virtchnl_ether_addr)];
int err;
struct vf_cmd_info args;

- addr = &(data->mac_addrs[index]);
-
if (i40e_validate_mac_addr(addr->addr_bytes) != I40E_SUCCESS) {
PMD_DRV_LOG(ERR, "Invalid mac:%x-%x-%x-%x-%x-%x",
addr->addr_bytes[0], addr->addr_bytes[1],
@@ -927,6 +926,17 @@ struct rte_i40evf_xstats_name_off {
return;
}

+static void
+i40evf_del_mac_addr(struct rte_eth_dev *dev, uint32_t index)
+{
+ struct rte_eth_dev_data *data = dev->data;
+ struct ether_addr *addr;
+
+ addr = &data->mac_addrs[index];
+
+ i40evf_del_mac_addr_by_addr(dev, addr);
+}
+
static int
i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
@@ -1261,10 +1271,12 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,

/* Store the MAC address configured by host, or generate random one */
p_mac_addr = (struct ether_addr *)(vf->vsi_res->default_mac_addr);
- if (is_valid_assigned_ether_addr(p_mac_addr)) /* Configured by host */
+ if (is_valid_assigned_ether_addr(p_mac_addr)) { /* Configured by host */
ether_addr_copy(p_mac_addr, (struct ether_addr *)hw->mac.addr);
- else
+ vf->flags |= I40E_FLAG_VF_MAC_BY_PF;
+ } else {
eth_random_addr(hw->mac.addr); /* Generate a random one */
+ }

/* If the PF host is not DPDK, set the interval of ITR0 to max*/
if (vf->version_major != I40E_DPDK_VERSION_MAJOR) {
@@ -2668,3 +2680,25 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,

return ret;
}
+
+static void
+i40evf_set_default_mac_addr(struct rte_eth_dev *dev,
+ struct ether_addr *mac_addr)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+ if (!is_valid_assigned_ether_addr(mac_addr)) {
+ PMD_DRV_LOG(ERR, "Tried to set invalid MAC address.");
+ return;
+ }
+
+ if (is_same_ether_addr(mac_addr, dev->data->mac_addrs))
+ return;
+
+ if (vf->flags & I40E_FLAG_VF_MAC_BY_PF)
+ return;
+
+ i40evf_del_mac_addr_by_addr(dev, dev->data->mac_addrs);
+
+ i40evf_add_mac_addr(dev, mac_addr, 0, 0);
+}
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:57 UTC
Permalink
If PF sets vf->mac_addr, in VF initialization hw->mac.addr will be set
to that same value. It is possible to check if PF set a MAC address or
not through the hw->mac.addr variable.

hw->mac.addr set by i40e_vf_parse_hw_config(), call stack is:

In PF side
i40e_pf_host_process_cmd_get_vf_resources()
eth_addr_copy(vf->mac_addr, vf_res->vsi_res[0].default_mac_address)

In VF sise
i40evf_init_vf()
i40evf_get_vf_resources()
i40e_vf_parse_hw_config()
memcpy(hw->mac.addr, vsi_res->default_mac_addr)

Updated code is after i40evf_get_vf_resources() and can benefit from
hw->mac.addr variable.

Fixes: 89e6b86384bb ("i40evf: rework MAC address validation")

CC: ***@dpdk.org
Signed-off-by: Ferruh Yigit <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index cc2d03c..3b9a673 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1193,7 +1193,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
int i, err, bufsz;
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
- struct ether_addr *p_mac_addr;
uint16_t interval =
i40e_calc_itr_interval(I40E_QUEUE_ITR_INTERVAL_MAX);

@@ -1270,13 +1269,10 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
vf->vsi.adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);

/* Store the MAC address configured by host, or generate random one */
- p_mac_addr = (struct ether_addr *)(vf->vsi_res->default_mac_addr);
- if (is_valid_assigned_ether_addr(p_mac_addr)) { /* Configured by host */
- ether_addr_copy(p_mac_addr, (struct ether_addr *)hw->mac.addr);
+ if (is_valid_assigned_ether_addr((struct ether_addr *)hw->mac.addr))
vf->flags |= I40E_FLAG_VF_MAC_BY_PF;
- } else {
+ else
eth_random_addr(hw->mac.addr); /* Generate a random one */
- }

/* If the PF host is not DPDK, set the interval of ITR0 to max*/
if (vf->version_major != I40E_DPDK_VERSION_MAJOR) {
--
1.9.3
Wenzhuo Lu
2016-12-07 03:31:58 UTC
Permalink
Add a function to configure vlan strip enable/disable for specific
SRIOV VF device.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 26 ++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 20 ++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 47 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 832995a..253209b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10335,3 +10335,29 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,

return 0;
}
+
+/* Set vlan strip on/off for specific VF from host */
+int
+rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct i40e_pf *pf;
+ struct i40e_vsi *vsi;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf_id].vsi;
+
+ if (vsi)
+ return i40e_vsi_config_vlan_stripping(vsi, !!on);
+ else
+ return -EINVAL;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index ca5e05a..043ae62 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -187,4 +187,24 @@ int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
struct ether_addr *mac_addr);

+/**
+ * Enable/Disable vf vlan strip for all queues in a pool
+ *
+ * @param port
+ * 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.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENOTSUP) if hardware doesn't support this feature.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int
+rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 64ba93a..2497b3e 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -13,5 +13,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_unicast_promisc;
rte_pmd_i40e_set_vf_multicast_promisc;
rte_pmd_i40e_set_vf_mac_addr;
+ rte_pmd_i40e_set_vf_vlan_stripq;

} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-07 14:18:09 UTC
Permalink
Post by Wenzhuo Lu
Add a function to configure vlan strip enable/disable for specific
SRIOV VF device.
---
<...>
Post by Wenzhuo Lu
+
+/* Set vlan strip on/off for specific VF from host */
+int
+rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct i40e_pf *pf;
+ struct i40e_vsi *vsi;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ if (vf_id > pf->vf_num - 1 || !pf->vfs) {
+ PMD_DRV_LOG(ERR, "Invalid argument.");
+ return -EINVAL;
+ }
+
+ vsi = pf->vfs[vf_id].vsi;
+
+ if (vsi)
+ return i40e_vsi_config_vlan_stripping(vsi, !!on);
+ else
if vd_if is valid, can vsi be NULL? If so this check may be required in
some prev patches too.
Post by Wenzhuo Lu
+ return -EINVAL;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index ca5e05a..043ae62 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -187,4 +187,24 @@ int rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port,
int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
struct ether_addr *mac_addr);
+/**
+ * Enable/Disable vf vlan strip for all queues in a pool
+ *
+ * The port identifier of the Ethernet device.
+ * ID specifying VF.
+ * 1 - Enable VF's vlan strip on RX queues.
+ * 0 - Disable VF's vlan strip on RX queues.
+ *
+ * - (0) if successful.
+ * - (-ENOTSUP) if hardware doesn't support this feature.
Is this error type returned?
Post by Wenzhuo Lu
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
<...>
Wenzhuo Lu
2016-12-07 03:31:59 UTC
Permalink
Support inserting VF VLAN id from PF.
User can call the API on PF to insert a VLAN id to a
specific VF.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 53 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 +++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 253209b..c571d8b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10361,3 +10361,56 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
else
return -EINVAL;
}
+
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+ uint16_t vlan_id)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ struct i40e_vsi *vsi;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+ pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ if (vf_id > pf->vf_num)
+ return -EINVAL;
+
+ if (vlan_id > 4095)
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
+ vsi->info.pvid = vlan_id;
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 043ae62..8867e9c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -207,4 +207,23 @@ int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
int
rte_pmd_i40e_set_vf_vlan_stripq(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 vlan_id
+ * 0 - Disable VF's vlan insert.
+ * n - Enable; n is inserted as the vlan id.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+ uint16_t vlan_id);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 2497b3e..e5e70e9 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -14,5 +14,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_multicast_promisc;
rte_pmd_i40e_set_vf_mac_addr;
rte_pmd_i40e_set_vf_vlan_stripq;
+ rte_pmd_i40e_set_vf_vlan_insert;

} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-07 14:26:19 UTC
Permalink
Post by Wenzhuo Lu
Support inserting VF VLAN id from PF.
User can call the API on PF to insert a VLAN id to a
specific VF.
Same comment with prev patch, does it make sense to insert " from PF" to
patch title?
Post by Wenzhuo Lu
---
drivers/net/i40e/i40e_ethdev.c | 53 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 +++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 253209b..c571d8b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10361,3 +10361,56 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
else
return -EINVAL;
}
+
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+ uint16_t vlan_id)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ struct i40e_vsi *vsi;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+ pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ if (vf_id > pf->vf_num)
This check was [1] in prev patches:
[1]
if (vf_id > pf->vf_num - 1 || !pf->vfs)
Post by Wenzhuo Lu
+ return -EINVAL;
+
+ if (vlan_id > 4095)
Can there be any define in base driver for this? Or ETH_VLAN_ID_MAX perhaps?
Post by Wenzhuo Lu
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
+ vsi->info.pvid = vlan_id;
+
--->
Post by Wenzhuo Lu
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
<-----

If Wenzhuo prefers to extract this part into a function, it can be
re-used here too.

<...>
Ferruh Yigit
2016-12-07 14:42:51 UTC
Permalink
Post by Ferruh Yigit
Post by Wenzhuo Lu
Support inserting VF VLAN id from PF.
User can call the API on PF to insert a VLAN id to a
specific VF.
Same comment with prev patch, does it make sense to insert " from PF" to
patch title?
Post by Wenzhuo Lu
---
drivers/net/i40e/i40e_ethdev.c | 53 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 19 +++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 253209b..c571d8b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10361,3 +10361,56 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
else
return -EINVAL;
}
+
+int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
+ uint16_t vlan_id)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ struct i40e_vsi *vsi;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
+ pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ if (vf_id > pf->vf_num)
[1]
if (vf_id > pf->vf_num - 1 || !pf->vfs)
Post by Wenzhuo Lu
+ return -EINVAL;
+
+ if (vlan_id > 4095)
Can there be any define in base driver for this? Or ETH_VLAN_ID_MAX perhaps?
Answer was in next patches, it seems we have two options (which is bad)

lib/librte_net/rte_ether.h
#define ETHER_MAX_VLAN_ID 4095 /**< Maximum VLAN ID. */

lib/librte_ether/rte_ethdev.h
#define ETH_VLAN_ID_MAX 0x0FFF /**< VLAN ID is in lower 12 bits*/
Post by Ferruh Yigit
Post by Wenzhuo Lu
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
+ vsi->info.pvid = vlan_id;
+
--->
Post by Wenzhuo Lu
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
<-----
If Wenzhuo prefers to extract this part into a function, it can be
re-used here too.
<...>
Wenzhuo Lu
2016-12-07 03:32:00 UTC
Permalink
Support enabling/disabling VF broadcast mode from PF.
User can call the API on PF to enable/disable a specific
VF's broadcast mode.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 43 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 18 +++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 62 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index c571d8b..10be00c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10414,3 +10414,46 @@ int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,

return ret;
}
+
+int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ if (vf_id > pf->vf_num)
+ return -EINVAL;
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ vf = &pf->vfs[vf_id];
+ hw = I40E_VSI_TO_HW(vf->vsi);
+
+ ret = i40e_aq_set_vsi_broadcast(hw, vf->vsi->seid, on, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 8867e9c..3e7ecb7 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -226,4 +226,22 @@ int rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
uint16_t vlan_id);

+/**
+ * Enable/Disable vf broadcast mode
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * ID specifying VF.
+ * @param on
+ * 0 - Disable broadcast.
+ * 1 - Enable broadcast.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index e5e70e9..76a3ef8 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -15,5 +15,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_mac_addr;
rte_pmd_i40e_set_vf_vlan_stripq;
rte_pmd_i40e_set_vf_vlan_insert;
+ rte_pmd_i40e_set_vf_broadcast;

} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-07 14:32:40 UTC
Permalink
Post by Wenzhuo Lu
Support enabling/disabling VF broadcast mode from PF.
User can call the API on PF to enable/disable a specific
VF's broadcast mode.
<...>
Post by Wenzhuo Lu
+int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ if (vf_id > pf->vf_num)
if (vf_id > pf->vf_num - 1 || !pf->vfs)
Post by Wenzhuo Lu
+ return -EINVAL;
+
<...>
Wenzhuo Lu
2016-12-07 03:32:01 UTC
Permalink
Add rte_pmd_i40e_set_vf_vlan_tag API.
User can call the API on PF to enable/disable a specific
VF's VLAN tag.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 59 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 18 ++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 78 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 10be00c..601e933 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10457,3 +10457,62 @@ int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on)

return ret;
}
+
+int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ struct i40e_pf_vf *vf;
+ struct i40e_hw *hw;
+ struct i40e_vsi *vsi;
+ struct i40e_vsi_context ctxt;
+ int ret;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vf_id >= dev_info.max_vfs)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ hw = I40E_PF_TO_HW(pf);
+
+ /**
+ * return -ENODEV if SRIOV not enabled, VF number not configured
+ * or no queue assigned.
+ */
+ if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0)
+ return -ENODEV;
+
+ if (vf_id >= pf->vf_num)
+ return -EINVAL;
+
+ vf = &pf->vfs[vf_id];
+ vsi = vf->vsi;
+
+ vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
+ if (on) {
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
+ vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+ } else {
+ vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
+ vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
+ }
+
+ memset(&ctxt, 0, sizeof(ctxt));
+ (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+ ctxt.seid = vsi->seid;
+
+ hw = I40E_VSI_TO_HW(vsi);
+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to update VSI params");
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 3e7ecb7..0b245da 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -244,4 +244,22 @@ int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
*/
int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id, uint8_t on);

+/**
+ * Enable/Disable vf vlan tag
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vf
+ * ID specifying VF.
+ * @param vlan_id
+ * 0 - Disable VF's vlan tag.
+ * n - Enable VF's vlan tag.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 76a3ef8..22e2716 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -16,5 +16,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_vlan_stripq;
rte_pmd_i40e_set_vf_vlan_insert;
rte_pmd_i40e_set_vf_broadcast;
+ rte_pmd_i40e_set_vf_vlan_tag;

} DPDK_2.0;
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:02 UTC
Permalink
add rte_pmd_i40e_set_vf_vlan_filter API.
User can call the API on PF to enable/disable
a set of VF's VLAN filters.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 50 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 22 ++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 601e933..bc96698 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10516,3 +10516,53 @@ int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)

return ret;
}
+
+int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
+ uint64_t vf_mask, uint8_t on)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ struct i40e_pf *pf;
+ uint16_t pool_idx;
+ int ret = 0;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ rte_eth_dev_info_get(port, &dev_info);
+
+ if (vlan_id > ETHER_MAX_VLAN_ID)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ if ((pf->flags & I40E_FLAG_VMDQ) == 0) {
+ PMD_INIT_LOG(ERR, "Firmware doesn't support VMDQ");
+ return -ENOTSUP;
+ }
+
+ if (!pf->vmdq) {
+ PMD_INIT_LOG(INFO, "VMDQ not configured");
+ return -ENOTSUP;
+ }
+
+ for (pool_idx = 0;
+ pool_idx < ETH_64_POOLS && pool_idx < pf->nb_cfg_vmdq_vsi;
+ pool_idx++) {
+ if (vf_mask & ((uint64_t)(1ULL << pool_idx))) {
+ if (on)
+ ret = i40e_vsi_add_vlan(pf->vmdq[pool_idx].vsi,
+ vlan_id);
+ else
+ ret = i40e_vsi_delete_vlan(
+ pf->vmdq[pool_idx].vsi, vlan_id);
+ }
+ }
+
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
+
+ return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 0b245da..1ce9513 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -262,4 +262,26 @@ int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
*/
int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on);

+/**
+ * Enable/Disable VF VLAN filter
+ *
+ * @param port
+ * The port identifier of the Ethernet device.
+ * @param vlan_id
+ * ID specifying VLAN
+ * @param vf_mask
+ * Mask to filter VF's
+ * @param on
+ * 0 - Disable VF's VLAN filter.
+ * 1 - Enable VF's VLAN filter.
+ *
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if *port* invalid.
+ * - (-EINVAL) if bad parameter.
+ * - (-ENOTSUP) VMDq not configured of not supported by firmware.
+ */
+int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
+ uint64_t vf_mask, uint8_t on);
+
#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 22e2716..818ff9c 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -17,5 +17,6 @@ DPDK_17.02 {
rte_pmd_i40e_set_vf_vlan_insert;
rte_pmd_i40e_set_vf_broadcast;
rte_pmd_i40e_set_vf_vlan_tag;
+ rte_pmd_i40e_set_vf_vlan_filter;

} DPDK_2.0;
--
1.9.3
Ferruh Yigit
2016-12-07 14:46:13 UTC
Permalink
Post by Wenzhuo Lu
add rte_pmd_i40e_set_vf_vlan_filter API.
User can call the API on PF to enable/disable
a set of VF's VLAN filters.
---
drivers/net/i40e/i40e_ethdev.c | 50 +++++++++++++++++++++++++++++++
drivers/net/i40e/rte_pmd_i40e.h | 22 ++++++++++++++
drivers/net/i40e/rte_pmd_i40e_version.map | 1 +
3 files changed, 73 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 601e933..bc96698 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10516,3 +10516,53 @@ int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
return ret;
}
+
+int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
+ uint64_t vf_mask, uint8_t on)
+{
<...>
Post by Wenzhuo Lu
+
+ for (pool_idx = 0;
+ pool_idx < ETH_64_POOLS && pool_idx < pf->nb_cfg_vmdq_vsi;
+ pool_idx++) {
+ if (vf_mask & ((uint64_t)(1ULL << pool_idx))) {
+ if (on)
+ ret = i40e_vsi_add_vlan(pf->vmdq[pool_idx].vsi,
+ vlan_id);
+ else
+ ret = i40e_vsi_delete_vlan(
+ pf->vmdq[pool_idx].vsi, vlan_id);
+ }
+ }
+
+ if (ret != I40E_SUCCESS)
+ PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
Since loop not break on error, this will only log the last one, if the
error is in the middle, it is missed.

<...>
Wenzhuo Lu
2016-12-07 03:32:03 UTC
Permalink
The new VF Daemon (VFD) APIs is implemented on i40e. Change
testpmd code to use them, including VF MAC anti-spoofing,
VF VLAN anti-spoofing, TX loopback, VF VLAN strip, VF VLAN
insert.

Signed-off-by: Wenzhuo Lu <***@intel.com>
Signed-off-by: Chen Jing D(Mark) <***@intel.com>
Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/Makefile | 1 +
app/test-pmd/cmdline.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index 891b85a..87cbaf9 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -59,6 +59,7 @@ SRCS-y += icmpecho.c
SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c

_LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe
+_LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e

CFLAGS_cmdline.o := -D_GNU_SOURCE

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 63b55dc..12126ce 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -90,6 +90,9 @@
#ifdef RTE_LIBRTE_IXGBE_PMD
#include <rte_pmd_ixgbe.h>
#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
#include "testpmd.h"

static struct cmdline *testpmd_cl;
@@ -10806,9 +10809,22 @@ struct cmd_vf_vlan_anti_spoof_result {
struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
int ret = 0;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else
+ ret = -ENOTSUP;

- ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id, res->vf_id,
- is_on);
switch (ret) {
case 0:
break;
@@ -10818,6 +10834,9 @@ struct cmd_vf_vlan_anti_spoof_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -10891,9 +10910,22 @@ struct cmd_vf_mac_anti_spoof_result {
struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
int ret;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id,
+ is_on);
+ else
+ ret = -ENOTSUP;

- ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id, res->vf_id,
- is_on);
switch (ret) {
case 0:
break;
@@ -10903,6 +10935,9 @@ struct cmd_vf_mac_anti_spoof_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -10976,8 +11011,20 @@ struct cmd_vf_vlan_stripq_result {
struct cmd_vf_vlan_stripq_result *res = parsed_result;
int ret = 0;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+ else
+ ret = -ENOTSUP;

- ret = rte_pmd_ixgbe_set_vf_vlan_stripq(res->port_id, res->vf_id, is_on);
switch (ret) {
case 0:
break;
@@ -10987,6 +11034,9 @@ struct cmd_vf_vlan_stripq_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -11059,8 +11109,20 @@ struct cmd_vf_vlan_insert_result {
{
struct cmd_vf_vlan_insert_result *res = parsed_result;
int ret;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+ else
+ ret = -ENOTSUP;

- ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id, res->vlan_id);
switch (ret) {
case 0:
break;
@@ -11070,6 +11132,9 @@ struct cmd_vf_vlan_insert_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
@@ -11133,8 +11198,18 @@ struct cmd_tx_loopback_result {
struct cmd_tx_loopback_result *res = parsed_result;
int ret;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+
+ if (strstr(dev_info.driver_name, "ixgbe") != NULL)
+ ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
+ else if (strstr(dev_info.driver_name, "i40e") != NULL)
+ ret = rte_pmd_i40e_set_tx_loopback(res->port_id, is_on);
+ else
+ ret = -ENOTSUP;

- ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
switch (ret) {
case 0:
break;
@@ -11144,6 +11219,9 @@ struct cmd_tx_loopback_result {
case -ENODEV:
printf("invalid port_id %d\n", res->port_id);
break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
default:
printf("programming error: (%s)\n", strerror(-ret));
}
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:04 UTC
Permalink
Add testpmd CLI to set VF unicast promiscuous mode on i40e.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
app/test-pmd/cmdline.c | 92 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 8 +++
2 files changed, 100 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 12126ce..d39712e 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -404,6 +404,11 @@ static void cmd_help_long_parsed(void *parsed_result,
"set allmulti (port_id|all) (on|off)\n"
" Set the allmulti mode on port_id, or all.\n\n"

+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
+ " Set unicast promiscuous mode for a VF from the PF.\n\n"
+#endif
+
"set flow_ctrl rx (on|off) tx (on|off) (high_water)"
" (low_water) (pause_time) (send_xon) mac_ctrl_frame_fwd"
" (on|off) autoneg (on|off) (port_id)\n"
@@ -11489,6 +11494,90 @@ struct cmd_set_vf_mac_addr_result {
};
#endif

+#ifdef RTE_LIBRTE_I40E_PMD
+/* VF unicast promiscuous mode configuration */
+
+/* Common result structure for VF unicast promiscuous mode */
+struct cmd_vf_unicast_promisc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t unicast_promisc;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF unicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_unicast_promisc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ unicast_promisc, "unicast-promisc");
+cmdline_parse_token_num_t cmd_vf_unicast_promisc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_unicast_promisc_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_unicast_promisc_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_unicast_promisc_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_unicast_promisc_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_unicast_promisc_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_pmd_i40e_set_vf_unicast_promisc(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_unicast_promisc = {
+ .f = cmd_set_vf_unicast_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf unicast promiscuous port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_vf_unicast_promisc_set,
+ (void *)&cmd_vf_unicast_promisc_vf,
+ (void *)&cmd_vf_unicast_promisc_unicast_promisc,
+ (void *)&cmd_vf_unicast_promisc_port_id,
+ (void *)&cmd_vf_unicast_promisc_vf_id,
+ (void *)&cmd_vf_unicast_promisc_on_off,
+ NULL,
+ },
+};
+#endif
+
/* ******************************************************************************** */

/* list of instructions */
@@ -11655,6 +11744,9 @@ struct cmd_set_vf_mac_addr_result {
(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ (cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
+#endif
NULL,
};

diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f1c269a..e17e3d5 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -820,6 +820,14 @@ Set the allmulti mode for a port or for all ports::

Same as the ifconfig (8) option. Controls how multicast packets are handled.

+set unicast promisc (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set the unicast promiscuous mode for a VF from PF.
+In promiscuous mode packets are not dropped if they aren't for the specified MAC address::
+
+ testpmd> set vf unicast-promisc (port_id) (vf_id) (on|off)
+
set flow_ctrl rx
~~~~~~~~~~~~~~~~
--
1.9.3
Ferruh Yigit
2016-12-07 14:59:59 UTC
Permalink
Post by Wenzhuo Lu
Add testpmd CLI to set VF unicast promiscuous mode on i40e.
---
app/test-pmd/cmdline.c | 92 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 8 +++
2 files changed, 100 insertions(+)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 12126ce..d39712e 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -404,6 +404,11 @@ static void cmd_help_long_parsed(void *parsed_result,
"set allmulti (port_id|all) (on|off)\n"
" Set the allmulti mode on port_id, or all.\n\n"
+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
Previous usages are all "promisc" instead of "unicals-promisc". Is this
to promisc mode for multicast packets? If so testpmd calls them
"allmulti" I guess, so they won't cause trouble.

Can we keep using command: "promisc"?

<...>
Post by Wenzhuo Lu
+
+cmdline_parse_inst_t cmd_set_vf_unicast_promisc = {
+ .f = cmd_set_vf_unicast_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf unicast promiscuous port_id vf_id on|off",
Can you please differentiate the keyword and variable by wrapping
variables with <>? Like:
"set vf unicast-promiscuous <port_id> <vf_id> on|off"

<...>
Post by Wenzhuo Lu
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f1c269a..e17e3d5 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
Same as the ifconfig (8) option. Controls how multicast packets are handled.
+set unicast promisc (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Should we mention this is PMD specific feature and only enabled with
some PMDs?
Post by Wenzhuo Lu
+
+Set the unicast promiscuous mode for a VF from PF.
+
+ testpmd> set vf unicast-promisc (port_id) (vf_id) (on|off)
+
set flow_ctrl rx
~~~~~~~~~~~~~~~~
Wenzhuo Lu
2016-12-07 03:32:05 UTC
Permalink
Add testpmd CLI to set VF multicast promiscuous mode on i40e.

Signed-off-by: Wenzhuo Lu <***@intel.com>
---
app/test-pmd/cmdline.c | 86 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 8 +++
2 files changed, 94 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index d39712e..7e7a016 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -407,6 +407,9 @@ static void cmd_help_long_parsed(void *parsed_result,
#ifdef RTE_LIBRTE_I40E_PMD
"set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
" Set unicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set vf multicast-promisc (port_id) (vf_id) (on|off)\n"
+ " Set multicast promiscuous mode for a VF from the PF.\n\n"
#endif

"set flow_ctrl rx (on|off) tx (on|off) (high_water)"
@@ -11576,6 +11579,88 @@ struct cmd_vf_unicast_promisc_result {
NULL,
},
};
+
+/* VF multicast promiscuous mode configuration */
+
+/* Common result structure for VF multicast promiscuous mode */
+struct cmd_vf_multicast_promisc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t multicast_promisc;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF multicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_multicast_promisc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ multicast_promisc, "multicast-promisc");
+cmdline_parse_token_num_t cmd_vf_multicast_promisc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_multicast_promisc_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_multicast_promisc_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_multicast_promisc_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_multicast_promisc_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_multicast_promisc_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_pmd_i40e_set_vf_multicast_promisc(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_multicast_promisc = {
+ .f = cmd_set_vf_multicast_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf multicast promiscuous port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_vf_multicast_promisc_set,
+ (void *)&cmd_vf_multicast_promisc_vf,
+ (void *)&cmd_vf_multicast_promisc_multicast_promisc,
+ (void *)&cmd_vf_multicast_promisc_port_id,
+ (void *)&cmd_vf_multicast_promisc_vf_id,
+ (void *)&cmd_vf_multicast_promisc_on_off,
+ NULL,
+ },
+};
#endif

/* ******************************************************************************** */
@@ -11746,6 +11831,7 @@ struct cmd_vf_unicast_promisc_result {
#endif
#ifdef RTE_LIBRTE_I40E_PMD
(cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
+ (cmdline_parse_inst_t *)&cmd_set_vf_multicast_promisc,
#endif
NULL,
};
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index e17e3d5..e1545b7 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -828,6 +828,14 @@ In promiscuous mode packets are not dropped if they aren't for the specified MAC

testpmd> set vf unicast-promisc (port_id) (vf_id) (on|off)

+set multicast promisc (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set the multicast promiscuous mode for a VF from PF.
+In promiscuous mode packets are not dropped if they aren't for the specified MAC address::
+
+ testpmd> set vf multicast-promisc (port_id) (vf_id) (on|off)
+
set flow_ctrl rx
~~~~~~~~~~~~~~~~
--
1.9.3
Ferruh Yigit
2016-12-07 15:01:45 UTC
Permalink
Post by Wenzhuo Lu
Add testpmd CLI to set VF multicast promiscuous mode on i40e.
---
app/test-pmd/cmdline.c | 86 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 8 +++
2 files changed, 94 insertions(+)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index d39712e..7e7a016 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -407,6 +407,9 @@ static void cmd_help_long_parsed(void *parsed_result,
#ifdef RTE_LIBRTE_I40E_PMD
"set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
" Set unicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set vf multicast-promisc (port_id) (vf_id) (on|off)\n"
+ " Set multicast promiscuous mode for a VF from the PF.\n\n"
Why not "allmulti" instead of multicast-promisc?

Also same comments as previous patch for help_str and documentation.

<...>
Wenzhuo Lu
2016-12-07 03:32:06 UTC
Permalink
Add command to call rte_pmd_i40e_set_vf_broadcast.
Add set vf broadcast in testpmd_funcs.rst file.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/cmdline.c | 87 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 +++
2 files changed, 94 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 7e7a016..2c663c3 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -279,6 +279,11 @@ static void cmd_help_long_parsed(void *parsed_result,
" Set MAC antispoof for a VF from the PF.\n\n"
#endif

+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf broadcast (port_id) (vf_id) (on|off)\n"
+ " Set VF broadcast for a VF from the PF.\n\n"
+#endif
+
"vlan set strip (on|off) (port_id)\n"
" Set the VLAN strip on a port.\n\n"

@@ -11661,6 +11666,87 @@ struct cmd_vf_multicast_promisc_result {
NULL,
},
};
+
+/* vf broadcast mode configuration */
+
+/* Common result structure for vf broadcast */
+struct cmd_set_vf_broadcast_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t broadcast;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf broadcast enable disable */
+cmdline_parse_token_string_t cmd_set_vf_broadcast_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_broadcast =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ broadcast, "broadcast");
+cmdline_parse_token_num_t cmd_set_vf_broadcast_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_broadcast_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_broadcast_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_broadcast_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_broadcast_result *res = parsed_result;
+ int ret;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_pmd_i40e_set_vf_broadcast(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_broadcast = {
+ .f = cmd_set_vf_broadcast_parsed,
+ .data = NULL,
+ .help_str = "set vf broadcast port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_broadcast_set,
+ (void *)&cmd_set_vf_broadcast_vf,
+ (void *)&cmd_set_vf_broadcast_broadcast,
+ (void *)&cmd_set_vf_broadcast_port_id,
+ (void *)&cmd_set_vf_broadcast_vf_id,
+ (void *)&cmd_set_vf_broadcast_on_off,
+ NULL,
+ },
+};
#endif

/* ******************************************************************************** */
@@ -11832,6 +11918,7 @@ struct cmd_vf_multicast_promisc_result {
#ifdef RTE_LIBRTE_I40E_PMD
(cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
(cmdline_parse_inst_t *)&cmd_set_vf_multicast_promisc,
+ (cmdline_parse_inst_t *)&cmd_set_vf_broadcast,
#endif
NULL,
};
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index e1545b7..525d0df 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -507,6 +507,13 @@ Set mac antispoof for a VF from the PF::

testpmd> set vf mac antispoof (port_id) (vf_id) (on|off)

+set broadcast mode (for VF)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set broadcast mode for a VF from the PF::
+
+ testpmd> set vf broadcast (port_id) (vf_id) (on|off)
+
vlan set strip
~~~~~~~~~~~~~~
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:09 UTC
Permalink
Initialise VMDq in the init_port_config function in a similar
way to how it is done in the VMDq sample application.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/testpmd.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index a0332c2..c0c8f60 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1842,9 +1842,12 @@ struct pmd_test_command {
ETH_MQ_RX_VMDQ_RSS;
else
port->dev_conf.rxmode.mq_mode =
- ETH_MQ_RX_NONE;
+ ETH_MQ_RX_VMDQ_ONLY;

port->dev_conf.txmode.mq_mode = ETH_MQ_TX_NONE;
+
+ port->dev_conf.rx_adv_conf.vmdq_rx_conf.nb_queue_pools =
+ ETH_8_POOLS;
}

rxtx_port_config(port);
--
1.9.3
Ferruh Yigit
2016-12-07 15:06:37 UTC
Permalink
Post by Wenzhuo Lu
Initialise VMDq in the init_port_config function in a similar
way to how it is done in the VMDq sample application.
What is the effect of doing existing initialization?
Post by Wenzhuo Lu
---
<...>
Wenzhuo Lu
2016-12-07 03:32:07 UTC
Permalink
command is: set vf vlan tag port_id vf_id on|off

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/cmdline.c | 93 +++++++++++++++++++++++++++++
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 +++
2 files changed, 100 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 2c663c3..e1a7e02 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -301,6 +301,11 @@ static void cmd_help_long_parsed(void *parsed_result,
" Set VLAN antispoof for a VF from the PF.\n\n"
#endif

+#ifdef RTE_LIBRTE_I40E_PMD
+ "set vf vlan tag (port_id) (vf_id) (on|off)\n"
+ " Set VLAN tag for a VF from the PF.\n\n"
+#endif
+
"vlan set filter (on|off) (port_id)\n"
" Set the VLAN filter on a port.\n\n"

@@ -11747,6 +11752,93 @@ struct cmd_set_vf_broadcast_result {
NULL,
},
};
+
+/* vf vlan tag configuration */
+
+/* Common result structure for vf vlan tag */
+struct cmd_set_vf_vlan_tag_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t tag;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan tag enable disable */
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_tag =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ tag, "tag");
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_tag_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_vlan_tag_result *res = parsed_result;
+ int ret;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_pmd_i40e_set_vf_vlan_tag(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_tag = {
+ .f = cmd_set_vf_vlan_tag_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan tag port_id vf_id on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_vlan_tag_set,
+ (void *)&cmd_set_vf_vlan_tag_vf,
+ (void *)&cmd_set_vf_vlan_tag_vlan,
+ (void *)&cmd_set_vf_vlan_tag_tag,
+ (void *)&cmd_set_vf_vlan_tag_port_id,
+ (void *)&cmd_set_vf_vlan_tag_vf_id,
+ (void *)&cmd_set_vf_vlan_tag_on_off,
+ NULL,
+ },
+};
#endif

/* ******************************************************************************** */
@@ -11919,6 +12011,7 @@ struct cmd_set_vf_broadcast_result {
(cmdline_parse_inst_t *)&cmd_set_vf_unicast_promisc,
(cmdline_parse_inst_t *)&cmd_set_vf_multicast_promisc,
(cmdline_parse_inst_t *)&cmd_set_vf_broadcast,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_tag,
#endif
NULL,
};
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 525d0df..cffcac8 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -542,6 +542,13 @@ Set VLAN insert for a VF from the PF::

testpmd> set vf vlan insert (port_id) (vf_id) (vlan_id)

+vlan set tag (for VF)
+~~~~~~~~~~~~~~~~~~~~~
+
+Set VLAN tag for a VF from the PF::
+
+ testpmd> set vf vlan tag (port_id) (vf_id) (on|off)
+
vlan set antispoof (for VF)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:10 UTC
Permalink
i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in version
number returned.

Current version info returned won't be able to be recognized
by Linux VF driver, change to values that both DPDK VF and Linux
driver can recognize.

The expense is original DPDK host specific feature like
CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.

DPDK VF also can't identify host driver by version number returned.
It always assume talking with Linux PF.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 2bc3355..0f582ed 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -279,8 +279,19 @@
{
struct i40e_virtchnl_version_info info;

- info.major = I40E_DPDK_VERSION_MAJOR;
- info.minor = I40E_DPDK_VERSION_MINOR;
+ /* Respond like a Linux PF host in order to support both DPDK VF and
+ * Linux VF driver. The expense is original DPDK host specific feature
+ * like CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.
+ *
+ * DPDK VF also can't identify host driver by version number returned.
+ * It always assume talking with Linux PF.
+ *
+ * TODO:
+ * Discuss with Linux driver maintainer if possible to carry more info
+ * in this function to identify it's Linux or DPDK host.
+ */
+ info.major = I40E_VIRTCHNL_VERSION_MAJOR;
+ info.minor = I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;

if (b_op)
i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
--
1.9.3
Ferruh Yigit
2016-12-07 15:13:59 UTC
Permalink
Post by Wenzhuo Lu
i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in version
number returned.
Current version info returned won't be able to be recognized
by Linux VF driver, change to values that both DPDK VF and Linux
driver can recognize.
The expense is original DPDK host specific feature like
CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.
DPDK VF also can't identify host driver by version number returned.
It always assume talking with Linux PF.
I guess you mention from following code [1], should it be also updated
to prevent it giving wrong information:

[1] i40e_ethdev_vf.c
if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
PMD_DRV_LOG(INFO, "Peer is DPDK PF host");
else if ((vf->version_major == I40E_VIRTCHNL_VERSION_MAJOR) &&
(vf->version_minor <= I40E_VIRTCHNL_VERSION_MINOR))
PMD_DRV_LOG(INFO, "Peer is Linux PF host");
else {
Post by Wenzhuo Lu
---
<...>
Wenzhuo Lu
2016-12-07 03:32:08 UTC
Permalink
modify set_vf_rx_vlan function to handle the i40e PMD.

Signed-off-by: Bernard Iremonger <***@intel.com>
---
app/test-pmd/config.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 36c47ab..0368dc6 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -92,6 +92,9 @@
#include <rte_ethdev.h>
#include <rte_string_fns.h>
#include <rte_cycles.h>
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif

#include "testpmd.h"

@@ -2349,12 +2352,24 @@ struct igb_ring_desc_16_bytes {
set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
{
int diag;
+ struct rte_eth_dev_info dev_info;

if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
- diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on);
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (strstr(dev_info.driver_name, "i40e") != NULL)
+ diag = rte_pmd_i40e_set_vf_vlan_filter(port_id, vlan_id,
+ vf_mask, on);
+ else
+#endif
+ diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id,
+ vf_mask, on);
+
if (diag == 0)
return;
printf("rte_eth_dev_set_vf_vlan_filter for port_id=%d failed "
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:11 UTC
Permalink
PF host didn't return correct VSI id to VF.
This change fix it.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 0f582ed..8319c2c 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -351,8 +351,7 @@

/* Change below setting if PF host can support more VSIs for VF */
vf_res->vsi_res[0].vsi_type = I40E_VSI_SRIOV;
- /* As assume Vf only has single VSI now, always return 0 */
- vf_res->vsi_res[0].vsi_id = 0;
+ vf_res->vsi_res[0].vsi_id = vf->vsi->vsi_id;
vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;
ether_addr_copy(&vf->mac_addr,
(struct ether_addr *)vf_res->vsi_res[0].default_mac_addr);
--
1.9.3
Ferruh Yigit
2016-12-07 15:16:19 UTC
Permalink
Post by Wenzhuo Lu
PF host didn't return correct VSI id to VF.
This change fix it.
This looks like a fix for current code,
can you please update commit title and log to reflect the fix?
Post by Wenzhuo Lu
---
drivers/net/i40e/i40e_pf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 0f582ed..8319c2c 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -351,8 +351,7 @@
/* Change below setting if PF host can support more VSIs for VF */
vf_res->vsi_res[0].vsi_type = I40E_VSI_SRIOV;
- /* As assume Vf only has single VSI now, always return 0 */
- vf_res->vsi_res[0].vsi_id = 0;
+ vf_res->vsi_res[0].vsi_id = vf->vsi->vsi_id;
vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;
ether_addr_copy(&vf->mac_addr,
(struct ether_addr *)vf_res->vsi_res[0].default_mac_addr);
Wenzhuo Lu
2016-12-07 03:32:12 UTC
Permalink
When VF requested to configure TX queue, a few parameters are
missed to be configured in PF host. This change have more
fields parsed and configured for TX context.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 8319c2c..1ad5ed1 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -422,10 +422,12 @@

/* clear the context structure first */
memset(&tx_ctx, 0, sizeof(tx_ctx));
- tx_ctx.new_context = 1;
tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
tx_ctx.qlen = txq->ring_len;
tx_ctx.rdylist = rte_le_to_cpu_16(vf->vsi->info.qs_handle[0]);
+ tx_ctx.head_wb_ena = txq->headwb_enabled;
+ tx_ctx.head_wb_addr = txq->dma_headwb_addr;
+
err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id);
if (err != I40E_SUCCESS)
return err;
--
1.9.3
Ferruh Yigit
2016-12-07 15:18:53 UTC
Permalink
Post by Wenzhuo Lu
When VF requested to configure TX queue, a few parameters are
missed to be configured in PF host. This change have more
fields parsed and configured for TX context.
What is the effect of missing Tx paramters configured?

If this cause a bug, this patch should be a fix.
Post by Wenzhuo Lu
---
drivers/net/i40e/i40e_pf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 8319c2c..1ad5ed1 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -422,10 +422,12 @@
/* clear the context structure first */
memset(&tx_ctx, 0, sizeof(tx_ctx));
- tx_ctx.new_context = 1;
tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
tx_ctx.qlen = txq->ring_len;
tx_ctx.rdylist = rte_le_to_cpu_16(vf->vsi->info.qs_handle[0]);
+ tx_ctx.head_wb_ena = txq->headwb_enabled;
+ tx_ctx.head_wb_addr = txq->dma_headwb_addr;
+
err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id);
if (err != I40E_SUCCESS)
return err;
Chen, Jing D
2016-12-07 15:32:59 UTC
Permalink
Hi, Ferruh,
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, December 7, 2016 11:19 PM
Subject: Re: [dpdk-dev] [PATCH v2 29/32] net/i40e: parse more VF parameter
and configure
When VF requested to configure TX queue, a few parameters are missed
to be configured in PF host. This change have more fields parsed and
configured for TX context.
What is the effect of missing Tx paramters configured?
If this cause a bug, this patch should be a fix.
This need to analyze case by case. If PF driver is serving a DPDK VF client,
the missing part is OK. If serving a Linux VF client, the missing part will
cause some unexpected TX queue behaviors.

So, this is an enhancement to support Linux VF client.
---
drivers/net/i40e/i40e_pf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 8319c2c..1ad5ed1 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -422,10 +422,12 @@
/* clear the context structure first */
memset(&tx_ctx, 0, sizeof(tx_ctx));
- tx_ctx.new_context = 1;
tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
tx_ctx.qlen = txq->ring_len;
tx_ctx.rdylist = rte_le_to_cpu_16(vf->vsi->info.qs_handle[0]);
+ tx_ctx.head_wb_ena = txq->headwb_enabled;
+ tx_ctx.head_wb_addr = txq->dma_headwb_addr;
+
err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id);
if (err != I40E_SUCCESS)
return err;
Wenzhuo Lu
2016-12-07 03:32:13 UTC
Permalink
i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in
configuring IRQ link list.

This Change will identify VF client by number of vector
requested. DPDK VF will ask only single one while Linux VF
will request at least 2. It will have different configuration
for different clients. DPDK VF will be configured to link all
queue together, while Linux VF will be configured per request.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 151 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 138 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 1ad5ed1..71e6a3f 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -585,14 +585,116 @@
return ret;
}

+static void
+i40e_pf_config_irq_link_list(struct i40e_pf_vf *vf,
+ struct i40e_virtchnl_vector_map *vvm)
+{
+ uint64_t linklistmap = 0, tempmap;
+ struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
+ uint16_t qid;
+ bool b_first_q = true;
+ enum i40e_queue_type qtype;
+ uint16_t vector_id;
+ uint32_t reg, reg_idx;
+ uint16_t itr_idx = 0, i;
+
+ vector_id = vvm->vector_id;
+ /* setup the head */
+ if (!vector_id)
+ reg_idx = I40E_VPINT_LNKLST0(vf->vf_idx);
+ else
+ reg_idx = I40E_VPINT_LNKLSTN(
+ ((hw->func_caps.num_msix_vectors_vf - 1) * vf->vf_idx)
+ + (vector_id - 1));
+
+ if (vvm->rxq_map == 0 && vvm->txq_map == 0) {
+ I40E_WRITE_REG(hw, reg_idx,
+ I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK);
+ goto cfg_irq_done;
+ }
+
+ /* sort all rx and tx queues */
+ tempmap = vvm->rxq_map;
+ for (i = 0; i < sizeof(vvm->rxq_map) * 8; i++) {
+ if (tempmap & 0x1)
+ linklistmap |= (1 << (2 * i));
+ tempmap >>= 1;
+ }
+
+ tempmap = vvm->txq_map;
+ for (i = 0; i < sizeof(vvm->txq_map) * 8; i++) {
+ if (tempmap & 0x1)
+ linklistmap |= (1 << (2 * i + 1));
+ tempmap >>= 1;
+ }
+
+ /* Link all rx and tx queues into a chained list */
+ tempmap = linklistmap;
+ i = 0;
+ b_first_q = true;
+ do {
+ if (tempmap & 0x1) {
+ qtype = (enum i40e_queue_type)(i % 2);
+ qid = vf->vsi->base_queue + i / 2;
+ if (b_first_q) {
+ /* This is header */
+ b_first_q = false;
+ reg = ((qtype <<
+ I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+ | qid);
+ } else {
+ /* element in the link list */
+ reg = (vector_id) |
+ (qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
+ (qid << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+ BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
+ (itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
+ }
+ I40E_WRITE_REG(hw, reg_idx, reg);
+ /* find next register to program */
+ switch (qtype) {
+ case I40E_QUEUE_TYPE_RX:
+ reg_idx = I40E_QINT_RQCTL(qid);
+ itr_idx = vvm->rxitr_idx;
+ break;
+ case I40E_QUEUE_TYPE_TX:
+ reg_idx = I40E_QINT_TQCTL(qid);
+ itr_idx = vvm->txitr_idx;
+ break;
+ default:
+ break;
+ }
+ }
+ i++;
+ tempmap >>= 1;
+ } while (tempmap);
+
+ /* Terminate the link list */
+ reg = (vector_id) |
+ (0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
+ (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+ BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
+ (itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
+ I40E_WRITE_REG(hw, reg_idx, reg);
+
+cfg_irq_done:
+ I40E_WRITE_FLUSH(hw);
+}
+
static int
i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
uint8_t *msg, uint16_t msglen,
bool b_op)
{
int ret = I40E_SUCCESS;
+ struct i40e_pf *pf = vf->pf;
+ struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
struct i40e_virtchnl_irq_map_info *irqmap =
(struct i40e_virtchnl_irq_map_info *)msg;
+ struct i40e_virtchnl_vector_map *map;
+ int i;
+ uint16_t vector_id;
+ unsigned long qbit_max;

if (!b_op) {
i40e_pf_host_send_msg_to_vf(
@@ -608,23 +710,46 @@
goto send_msg;
}

- /* Assume VF only have 1 vector to bind all queues */
- if (irqmap->num_vectors != 1) {
- PMD_DRV_LOG(ERR, "DKDK host only support 1 vector");
- ret = I40E_ERR_PARAM;
+ /* PF host will support both DPDK VF or Linux VF driver, identify by
+ * number of vectors requested.
+ */
+
+ /* DPDK VF only requires single vector */
+ if (irqmap->num_vectors == 1) {
+ /* This MSIX intr store the intr in VF range */
+ vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+ vf->vsi->nb_msix = irqmap->num_vectors;
+ vf->vsi->nb_used_qps = vf->vsi->nb_qps;
+
+ /* Don't care how the TX/RX queue mapping with this vector.
+ * Link all VF RX queues together. Only did mapping work.
+ * VF can disable/enable the intr by itself.
+ */
+ i40e_vsi_queues_bind_intr(vf->vsi);
goto send_msg;
}

- /* This MSIX intr store the intr in VF range */
- vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
- vf->vsi->nb_msix = irqmap->num_vectors;
- vf->vsi->nb_used_qps = vf->vsi->nb_qps;
+ /* Then, it's Linux VF driver */
+ qbit_max = 1 << pf->vf_nb_qp_max;
+ for (i = 0; i < irqmap->num_vectors; i++) {
+ map = &irqmap->vecmap[i];
+
+ vector_id = map->vector_id;
+ /* validate msg params */
+ if (vector_id >= hw->func_caps.num_msix_vectors_vf) {
+ ret = I40E_ERR_PARAM;
+ goto send_msg;
+ }
+
+ if ((map->rxq_map < qbit_max) && (map->txq_map < qbit_max)) {
+ i40e_pf_config_irq_link_list(vf, map);
+ } else {
+ /* configured queue size excceed limit */
+ ret = I40E_ERR_PARAM;
+ goto send_msg;
+ }
+ }

- /* Don't care how the TX/RX queue mapping with this vector.
- * Link all VF RX queues together. Only did mapping work.
- * VF can disable/enable the intr by itself.
- */
- i40e_vsi_queues_bind_intr(vf->vsi);
send_msg:
i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
ret, NULL, 0);
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:14 UTC
Permalink
When VF sends request to add a new MAC address, PF host
will check if it's a non-zero or unicast address, or it
will return with error. In fact, VF still can set multicast
address. This change remove to check if it's a unicast
address.

Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
drivers/net/i40e/i40e_pf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 71e6a3f..79f4295 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -890,8 +890,8 @@
mac = (struct ether_addr *)(addr_list->list[i].addr);
(void)rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN);
filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
- if(!is_valid_assigned_ether_addr(mac) ||
- i40e_vsi_add_mac(vf->vsi, &filter)) {
+ if (is_zero_ether_addr(mac) ||
+ i40e_vsi_add_mac(vf->vsi, &filter)) {
ret = I40E_ERR_INVALID_MAC_ADDR;
goto send_msg;
}
--
1.9.3
Wenzhuo Lu
2016-12-07 03:32:15 UTC
Permalink
Some CLIs don't check the input port ID, it
may cause segmentation fault (core dumped).

Fixes: 425781ff5afe ("app/testpmd: add ixgbe VF management")

Signed-off-by: Wenzhuo Lu <***@intel.com>
Signed-off-by: Chen Jing D(Mark) <***@intel.com>
---
app/test-pmd/cmdline.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index e1a7e02..be0c424 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -10829,6 +10829,9 @@ struct cmd_vf_vlan_anti_spoof_result {
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
struct rte_eth_dev_info dev_info;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(res->port_id, &dev_info);

@@ -10930,6 +10933,9 @@ struct cmd_vf_mac_anti_spoof_result {
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
struct rte_eth_dev_info dev_info;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(res->port_id, &dev_info);

@@ -11031,6 +11037,9 @@ struct cmd_vf_vlan_stripq_result {
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
struct rte_eth_dev_info dev_info;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(res->port_id, &dev_info);

@@ -11129,6 +11138,9 @@ struct cmd_vf_vlan_insert_result {
int ret;
struct rte_eth_dev_info dev_info;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(res->port_id, &dev_info);

@@ -11218,6 +11230,9 @@ struct cmd_tx_loopback_result {
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
struct rte_eth_dev_info dev_info;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(res->port_id, &dev_info);

@@ -11307,6 +11322,9 @@ struct cmd_all_queues_drop_en_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_pmd_ixgbe_set_all_queues_drop_en(res->port_id, is_on);
switch (ret) {
case 0:
@@ -11390,6 +11408,9 @@ struct cmd_vf_split_drop_en_result {
int ret;
int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
ret = rte_pmd_ixgbe_set_vf_split_drop_en(res->port_id, res->vf_id,
is_on);
switch (ret) {
@@ -11474,6 +11495,9 @@ struct cmd_set_vf_mac_addr_result {
struct cmd_set_vf_mac_addr_result *res = parsed_result;
int ret;

+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
ret = rte_pmd_ixgbe_set_vf_mac_addr(res->port_id, res->vf_id,
&res->mac_addr);
switch (ret) {
--
1.9.3
Loading...