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(-)
@@ -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_ */
@@ -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;
}
@@ -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