Hi All, Gentle reminder for review & ack.
Thank you. Regards, Anurag M > -----Original Message----- > From: Mandal, Anurag <[email protected]> > Sent: 09 April 2026 15:50 > To: [email protected] > Cc: Richardson, Bruce <[email protected]>; Medvedkin, Vladimir > <[email protected]>; Mandal, Anurag > <[email protected]> > Subject: [PATCH v4] net/iavf: add support for QinQ strip > > QinQ strip with VLAN TPID 0x88a8 & 0x8100 support was absent. > > This patch adds support for QinQ strip with both Outer VLAN TPIDs 0x88a8 > (802.1ad) & 0x8100 (802.1Q). > VLAN Extend should be enabled for the same and Outer VLAN TPID should be > set properly. > > 1. Tested QinQ stripping with TPIDs 0x88a8 as well as 0x8100. > 2. Tested Double VLAN stripping i.e. QinQ (802.1ad/802.1Q) & > VLAN (802.1Q) stripping simultaneously. > 3. Tested Single VLAN (802.1Q) stripping. > > Signed-off-by: Anurag Mandal <[email protected]> > --- > V4: Addressed ai-code-review suggestions > V3: Rebased onto next-net-intel-for-next-net > V2: Addressed Coding Style Warnings > > doc/guides/nics/intel_vf.rst | 31 ++++++++++++++ > drivers/net/intel/iavf/iavf.h | 2 + > drivers/net/intel/iavf/iavf_ethdev.c | 50 +++++++++++++++++++++++ > drivers/net/intel/iavf/iavf_vchnl.c | 61 ++++++++++++++++++++++++++-- > 4 files changed, 141 insertions(+), 3 deletions(-) > > diff --git a/doc/guides/nics/intel_vf.rst b/doc/guides/nics/intel_vf.rst index > 5fa2ddc9ea..dfff69b982 100644 > --- a/doc/guides/nics/intel_vf.rst > +++ b/doc/guides/nics/intel_vf.rst > @@ -771,3 +771,34 @@ the VLAN header tag length will be automatically > added to MTU when configuring q As a consequence, when attempting to > configure a VF port with MTU that, together with a VLAN tag header, exceeds > maximum supported MTU, port configuration will fail if kernel driver has > configured VLAN filtering on that VF. > + > +QinQ strip > +~~~~~~~~~~ > + > +QinQ TPID is set as 0x8100 IEEE 802.1Q by default. > +For QinQ strip with TPID 0x88A8 IEEE 802.1ad, extend VLAN is enabled > +and VLAN outer TPID is set to 0x88A8. > +VLAN filter steps can be added before or after. > + > +To start ``testpmd``, and enable QinQ strip for TPID 0x88A8 on port 0: > + > +.. code-block:: console > + > + ./<build_dir>/app/dpdk-testpmd -l 0-15 -- -i --forward-mode=mac > + ... > + > + testpmd> vlan set extend on 0 > + testpmd> vlan set outer tpid 0x88A8 0 > + testpmd> vlan set qinq_strip on 0 > + > +For QinQ strip with TPID 0x8100, extend VLAN is enabled only. > + > +To start ``testpmd``, and enable QinQ strip for default TPID on port 0: > + > +.. code-block:: console > + > + ./<build_dir>/app/dpdk-testpmd -l 0-15 -- -i --forward-mode=mac > + ... > + > + testpmd> vlan set extend on 0 > + testpmd> vlan set qinq_strip on 0 > diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h > index > f8008d0fda..6a77dacf59 100644 > --- a/drivers/net/intel/iavf/iavf.h > +++ b/drivers/net/intel/iavf/iavf.h > @@ -387,6 +387,7 @@ struct iavf_adapter { > uint16_t fdir_ref_cnt; > struct iavf_devargs devargs; > bool mac_primary_set; > + uint16_t tpid; /* VLAN tag identifier */ > }; > > /* IAVF_DEV_PRIVATE_TO */ > @@ -456,6 +457,7 @@ int iavf_configure_rss_key(struct iavf_adapter > *adapter); int iavf_configure_queues(struct iavf_adapter *adapter, uint16_t > num_queue_pairs); int iavf_get_supported_rxdid(struct iavf_adapter > *adapter); int iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool > enable); > +int iavf_config_outer_vlan_strip_v2(struct iavf_adapter *adapter, bool > +enable); > int iavf_config_vlan_insert_v2(struct iavf_adapter *adapter, bool enable); > int > iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid, > bool add); > diff --git a/drivers/net/intel/iavf/iavf_ethdev.c > b/drivers/net/intel/iavf/iavf_ethdev.c > index 3126d9b644..5da2cd43c2 100644 > --- a/drivers/net/intel/iavf/iavf_ethdev.c > +++ b/drivers/net/intel/iavf/iavf_ethdev.c > @@ -127,6 +127,8 @@ static int iavf_dev_add_mac_addr(struct rte_eth_dev > *dev, static void iavf_dev_del_mac_addr(struct rte_eth_dev *dev, uint32_t > index); static int iavf_dev_vlan_filter_set(struct rte_eth_dev *dev, > uint16_t vlan_id, int on); > +static int iavf_vlan_tpid_set(struct rte_eth_dev *dev, > + enum rte_vlan_type vlan_type, uint16_t tpid); > static int iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask); > static > int iavf_dev_rss_reta_update(struct rte_eth_dev *dev, > struct rte_eth_rss_reta_entry64 *reta_conf, > @@ -226,6 +228,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = { > .mac_addr_remove = iavf_dev_del_mac_addr, > .set_mc_addr_list = iavf_set_mc_addr_list, > .vlan_filter_set = iavf_dev_vlan_filter_set, > + .vlan_tpid_set = iavf_vlan_tpid_set, > .vlan_offload_set = iavf_dev_vlan_offload_set, > .rx_queue_start = iavf_dev_rx_queue_start, > .rx_queue_stop = iavf_dev_rx_queue_stop, > @@ -1365,6 +1368,36 @@ iavf_dev_del_mac_addr(struct rte_eth_dev *dev, > uint32_t index) > vf->mac_num--; > } > > +static int > +iavf_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type > +vlan_type, uint16_t tpid) { > + struct iavf_adapter *adapter = > + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); > + struct rte_eth_conf *dev_conf = &dev->data->dev_conf; > + int qinq = dev_conf->rxmode.offloads & > RTE_ETH_RX_OFFLOAD_VLAN_EXTEND; > + > + if (vlan_type != RTE_ETH_VLAN_TYPE_OUTER) { > + PMD_DRV_LOG(ERR, "Unsupported vlan type."); > + return -EINVAL; > + } else if (!qinq) { > + PMD_DRV_LOG(ERR, "VLAN-extend disabled."); > + return -ENOSYS; > + } else if (tpid != RTE_ETHER_TYPE_VLAN && > + tpid != RTE_ETHER_TYPE_QINQ) { > + PMD_DRV_LOG(ERR, "tpid supported 0x8100/0x88A8"); > + return -ENOTSUP; > + } > + > + /* This API only fills internal iavf_adapter structure > + * and does not send any signal to hardware. > + * Inner VLAN always 0x8100, so not set explicitly. > + */ > + if (qinq && vlan_type == RTE_ETH_VLAN_TYPE_OUTER) > + adapter->tpid = tpid; /* Outer VLAN can be 0x88a8 or 0x8100 > */ > + > + return 0; > +} > + > static int > iavf_disable_vlan_strip_ex(struct rte_eth_dev *dev, int on) { @@ -1453,6 > +1486,8 @@ iavf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask) > struct iavf_adapter *adapter = > IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); > bool enable; > + int qinq = dev->data->dev_conf.rxmode.offloads & > + RTE_ETH_RX_OFFLOAD_VLAN_EXTEND; > int err; > > if (mask & RTE_ETH_VLAN_FILTER_MASK) { @@ -1472,6 +1507,20 @@ > iavf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask) > return -EIO; > } > > + if (mask & RTE_ETH_QINQ_STRIP_MASK) { > + if (!qinq) { > + PMD_DRV_LOG(ERR, "VLAN-extend disabled"); > + return -ENOSYS; > + } > + enable = !!(rxmode->offloads & > RTE_ETH_RX_OFFLOAD_QINQ_STRIP); > + err = iavf_config_outer_vlan_strip_v2(adapter, enable); > + /* If not support, the stripping is already disabled by PF */ > + if (err == -ENOTSUP && !enable) > + err = 0; > + if (err) > + return -EIO; > + } > + > return 0; > } > > @@ -2812,6 +2861,7 @@ iavf_dev_init(struct rte_eth_dev *eth_dev) > adapter->dev_data = eth_dev->data; > adapter->stopped = 1; > adapter->mac_primary_set = false; > + adapter->tpid = RTE_ETHER_TYPE_VLAN; /* VLAN TPID set to 0x8100 > by > +default */ > > if (iavf_dev_event_handler_init()) > goto init_vf_err; > diff --git a/drivers/net/intel/iavf/iavf_vchnl.c > b/drivers/net/intel/iavf/iavf_vchnl.c > index 23d115298c..c2f340db81 100644 > --- a/drivers/net/intel/iavf/iavf_vchnl.c > +++ b/drivers/net/intel/iavf/iavf_vchnl.c > @@ -829,6 +829,50 @@ iavf_get_supported_rxdid(struct iavf_adapter > *adapter) > return 0; > } > > +int > +iavf_config_outer_vlan_strip_v2(struct iavf_adapter *adapter, bool > +enable) { > + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); > + struct virtchnl_vlan_supported_caps *stripping_caps; > + struct virtchnl_vlan_setting vlan_strip; > + uint8_t msg_buf[IAVF_AQ_BUF_SZ] = {0}; > + struct iavf_cmd_info args; > + uint32_t *ethertype; > + int ret; > + > + memset(&vlan_strip, 0, sizeof(vlan_strip)); > + stripping_caps = &vf->vlan_v2_caps.offloads.stripping_support; > + if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_88A8) && > + (stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE) && > + adapter->tpid == RTE_ETHER_TYPE_QINQ) { > + ethertype = &vlan_strip.outer_ethertype_setting; > + *ethertype = VIRTCHNL_VLAN_ETHERTYPE_88A8; > + } else if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) > && > + (stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE) && > + adapter->tpid == RTE_ETHER_TYPE_VLAN) { > + ethertype = &vlan_strip.outer_ethertype_setting; > + *ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100; > + } else { > + return -ENOTSUP; > + } > + > + vlan_strip.vport_id = vf->vsi_res->vsi_id; > + > + args.ops = enable ? 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 = msg_buf; > + args.out_size = IAVF_AQ_BUF_SZ; > + ret = iavf_execute_vf_cmd_safe(adapter, &args); > + if (ret) > + PMD_DRV_LOG(ERR, "fail to execute command %s", > + enable ? > "VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2" : > + > "VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2"); > + > + return ret; > +} > + > int > iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable) { @@ - > 838,14 +882,20 @@ iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, > bool enable) > uint8_t msg_buf[IAVF_AQ_BUF_SZ] = {0}; > struct iavf_cmd_info args; > uint32_t *ethertype; > + int qinq = adapter->dev_data->dev_conf.rxmode.offloads & > + RTE_ETH_RX_OFFLOAD_VLAN_EXTEND; > int ret; > > stripping_caps = &vf->vlan_v2_caps.offloads.stripping_support; > > - if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) && > + /* When VLAN extend is disabled, Single VLAN mode which is Outer > VLAN > + * When VLAN extend is enabled, QinQ mode, this API works only on > + * Inner VLAN strip which is always 0x8100. > + */ > + if (!qinq && (stripping_caps->outer & > VIRTCHNL_VLAN_ETHERTYPE_8100) && > (stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE)) > ethertype = &vlan_strip.outer_ethertype_setting; > - else if ((stripping_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100) > && > + else if (qinq && (stripping_caps->inner & > +VIRTCHNL_VLAN_ETHERTYPE_8100) && > (stripping_caps->inner & VIRTCHNL_VLAN_TOGGLE)) > ethertype = &vlan_strip.inner_ethertype_setting; > else > @@ -921,6 +971,8 @@ iavf_add_del_vlan_v2(struct iavf_adapter *adapter, > uint16_t vlanid, bool add) > struct virtchnl_vlan *vlan_setting; > struct iavf_cmd_info args; > uint32_t filtering_caps; > + int qinq = adapter->dev_data->dev_conf.rxmode.offloads & > + RTE_ETH_RX_OFFLOAD_VLAN_EXTEND; > int err; > > supported_caps = &vf->vlan_v2_caps.filtering.filtering_support; > @@ -938,7 +990,10 @@ iavf_add_del_vlan_v2(struct iavf_adapter *adapter, > uint16_t vlanid, bool add) > memset(&vlan_filter, 0, sizeof(vlan_filter)); > vlan_filter.vport_id = vf->vsi_res->vsi_id; > vlan_filter.num_elements = 1; > - vlan_setting->tpid = RTE_ETHER_TYPE_VLAN; > + if (qinq && adapter->tpid == RTE_ETHER_TYPE_QINQ) > + vlan_setting->tpid = RTE_ETHER_TYPE_QINQ; > + else > + vlan_setting->tpid = RTE_ETHER_TYPE_VLAN; > vlan_setting->tci = vlanid; > > args.ops = add ? VIRTCHNL_OP_ADD_VLAN_V2 : > VIRTCHNL_OP_DEL_VLAN_V2; > -- > 2.34.1

