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.y...@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(-) 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 -- 2.17.1