net/iavf: support enhanced VLAN offload
diff mbox series

Message ID 20200902082841.106117-1-qiming.yang@intel.com
State Superseded
Delegated to: Qi Zhang
Headers show
Series
  • net/iavf: support enhanced VLAN offload
Related show

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail apply issues

Commit Message

Yang, Qiming Sept. 2, 2020, 8:28 a.m. UTC
This patch add VIRTCHNL_VF_OFFLOAD_VLAN_V2 series virtual channel
support, included get VLAN offload capability, support VLAN filter
and double VLAN strip.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
 drivers/net/iavf/iavf.h        |  5 ++
 drivers/net/iavf/iavf_ethdev.c | 70 ++++++++++++++++++++-------
 drivers/net/iavf/iavf_vchnl.c  | 87 ++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 17 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index 9ad331ee9..8c10f7e59 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -149,6 +149,7 @@  struct iavf_info {
 	struct iavf_parser_list dist_parser_list;
 
 	struct iavf_fdir_info fdir; /* flow director info */
+	struct virtchnl_vlan_caps *vlan_cap;
 };
 
 #define IAVF_MAX_PKT_TYPE 1024
@@ -279,4 +280,8 @@  int iavf_add_del_rss_cfg(struct iavf_adapter *adapter,
 int iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,
 			struct rte_ether_addr *mc_addrs,
 			uint32_t mc_addrs_num, bool add);
+int iavf_get_vlan_offload_capa(struct rte_eth_dev *dev);
+int iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid,
+			 bool add, bool qinq);
+int iavf_switch_vlan_strip(struct iavf_adapter *adapter, bool qinq, bool on);
 #endif /* _IAVF_ETHDEV_H_ */
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 28ca3fa8f..af9698009 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -807,14 +807,22 @@  iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 	struct iavf_adapter *adapter =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
+	int qinq = dev->data->dev_conf.rxmode.offloads &
+		   DEV_RX_OFFLOAD_VLAN_EXTEND;
 	int err;
 
-	if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
-		return -ENOTSUP;
+	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
+		err = iavf_add_del_vlan_v2(adapter, vlan_id, on, qinq);
+		if (err)
+			return -EIO;
+		return 0;
+	}
 
-	err = iavf_add_del_vlan(adapter, vlan_id, on);
-	if (err)
-		return -EIO;
+	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
+		err = iavf_add_del_vlan(adapter, vlan_id, on);
+		if (err)
+			return -EIO;
+	}
 	return 0;
 }
 
@@ -825,22 +833,48 @@  iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
 	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+	int qinq = dev->data->dev_conf.rxmode.offloads &
+		   DEV_RX_OFFLOAD_VLAN_EXTEND;
+	bool on;
 	int err;
 
-	if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
-		return -ENOTSUP;
-
-	/* Vlan stripping setting */
-	if (mask & ETH_VLAN_STRIP_MASK) {
-		/* Enable or disable VLAN stripping */
-		if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-			err = iavf_enable_vlan_strip(adapter);
-		else
-			err = iavf_disable_vlan_strip(adapter);
+	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
+		/* Double vlan stripping setting */
+		if (mask & ETH_QINQ_STRIP_MASK) {
+			/* Enable or disable inner VLAN stripping */
+			on = dev_conf->rxmode.offloads &
+			     DEV_RX_OFFLOAD_QINQ_STRIP;
+			err = iavf_switch_vlan_strip(adapter, qinq, on);
+			if (err)
+				return -EIO;
+		}
+		/* Single vlan stripping setting */
+		if (mask & ETH_VLAN_STRIP_MASK) {
+			/* Enable or disable VLAN stripping */
+			on = dev_conf->rxmode.offloads &
+			     DEV_RX_OFFLOAD_VLAN_STRIP;
+			err = iavf_switch_vlan_strip(adapter, qinq, on);
+			if (err)
+				return -EIO;
+		}
+		return 0;
+	}
 
-		if (err)
-			return -EIO;
+	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
+		/* Vlan stripping setting */
+		if (mask & ETH_VLAN_STRIP_MASK) {
+			/* Enable or disable VLAN stripping */
+			if (dev_conf->rxmode.offloads &
+			    DEV_RX_OFFLOAD_VLAN_STRIP)
+				err = iavf_enable_vlan_strip(adapter);
+			else
+				err = iavf_disable_vlan_strip(adapter);
+
+			if (err)
+				return -EIO;
+		}
 	}
+
 	return 0;
 }
 
@@ -1453,6 +1487,8 @@  iavf_dev_init(struct rte_eth_dev *eth_dev)
 		return ret;
 	}
 
+	iavf_get_vlan_offload_capa(eth_dev);
+
 	return 0;
 }
 
diff --git a/drivers/net/iavf/iavf_vchnl.c b/drivers/net/iavf/iavf_vchnl.c
index 6b57ecbba..74e73b0d3 100644
--- a/drivers/net/iavf/iavf_vchnl.c
+++ b/drivers/net/iavf/iavf_vchnl.c
@@ -314,6 +314,93 @@  iavf_disable_vlan_strip(struct iavf_adapter *adapter)
 	return ret;
 }
 
+int
+iavf_get_vlan_offload_capa(struct rte_eth_dev *dev)
+{
+	struct iavf_adapter *adapter =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
+	struct virtchnl_vlan_caps *vlan_cap = NULL;
+	struct iavf_cmd_info args;
+	int ret;
+
+	memset(&args, 0, sizeof(args));
+	args.ops = VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS;
+	args.in_args = NULL;
+	args.in_args_size = 0;
+	args.out_buffer = vf->aq_resp;
+	args.out_size = IAVF_AQ_BUF_SZ;
+	ret = iavf_execute_vf_cmd(adapter, &args);
+	if (ret)
+		PMD_DRV_LOG(ERR, "Failed to execute command of"
+				 " OP_GET_OFFLOAD_VLAN_V2_CAPS");
+	vlan_cap = (struct virtchnl_vlan_caps *)args.out_buffer;
+	vf->vlan_cap = vlan_cap;
+
+	return ret;
+}
+
+int
+iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid,
+		     bool add, bool qinq)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
+	struct virtchnl_vlan_filter vlan_filter;
+	struct iavf_cmd_info args;
+	int err;
+
+	if (qinq) {
+		vlan_filter.inner.id = vlanid;
+		vlan_filter.inner.ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
+	} else {
+		vlan_filter.outer.id = vlanid;
+		vlan_filter.outer.ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
+	}
+
+	args.ops = add ? VIRTCHNL_OP_ADD_VLAN_V2 : VIRTCHNL_OP_DEL_VLAN_V2;
+	args.in_args = (uint8_t *)&vlan_filter;
+	args.in_args_size = sizeof(vlan_filter);
+	args.out_buffer = vf->aq_resp;
+	args.out_size = IAVF_AQ_BUF_SZ;
+	err = iavf_execute_vf_cmd(adapter, &args);
+	if (err)
+		PMD_DRV_LOG(ERR, "fail to execute command %s",
+			    add ? "OP_ADD_VLAN" :  "OP_DEL_VLAN");
+
+	return err;
+}
+
+int
+iavf_switch_vlan_strip(struct iavf_adapter *adapter, bool qinq, bool on)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
+	struct virtchnl_vlan_strip vlan_strip;
+	struct iavf_cmd_info args;
+	int ret;
+
+	memset(&args, 0, sizeof(args));
+	vlan_strip.vsi_id = vf->vsi_res->vsi_id;
+	if (qinq)
+		vlan_strip.inner_ethertype_setting =
+			VIRTCHNL_VLAN_ETHERTYPE_8100;
+	else
+		vlan_strip.outer_ethertype_setting =
+			VIRTCHNL_VLAN_ETHERTYPE_8100;
+	args.ops = on ? VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2
+		   : VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2;
+	args.in_args = (uint8_t *)&vlan_strip;
+	args.in_args_size = sizeof(vlan_strip);
+	args.out_buffer = vf->aq_resp;
+	args.out_size = IAVF_AQ_BUF_SZ;
+	ret = iavf_execute_vf_cmd(adapter, &args);
+	if (ret)
+		PMD_DRV_LOG(ERR, "fail to execute command %s",
+			    on ? "VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2"
+			    :  "VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2");
+
+	return ret;
+}
+
 #define VIRTCHNL_VERSION_MAJOR_START 1
 #define VIRTCHNL_VERSION_MINOR_START 1