Skip to content

Commit f97307b

Browse files
anuragma2025bruce-richardson
authored andcommitted
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. Signed-off-by: Anurag Mandal <anurag.mandal@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
1 parent 3f4e1d2 commit f97307b

4 files changed

Lines changed: 141 additions & 3 deletions

File tree

doc/guides/nics/intel_vf.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,3 +771,34 @@ the VLAN header tag length will be automatically added to MTU when configuring q
771771
As a consequence, when attempting to configure a VF port with MTU that,
772772
together with a VLAN tag header, exceeds maximum supported MTU,
773773
port configuration will fail if kernel driver has configured VLAN filtering on that VF.
774+
775+
QinQ strip
776+
~~~~~~~~~~
777+
778+
QinQ TPID is set as 0x8100 IEEE 802.1Q by default.
779+
For QinQ strip with TPID 0x88A8 IEEE 802.1ad,
780+
extend VLAN is enabled and VLAN outer TPID is set to 0x88A8.
781+
VLAN filter steps can be added before or after.
782+
783+
To start ``testpmd``, and enable QinQ strip for TPID 0x88A8 on port 0:
784+
785+
.. code-block:: console
786+
787+
./<build_dir>/app/dpdk-testpmd -l 0-15 -- -i --forward-mode=mac
788+
...
789+
790+
testpmd> vlan set extend on 0
791+
testpmd> vlan set outer tpid 0x88A8 0
792+
testpmd> vlan set qinq_strip on 0
793+
794+
For QinQ strip with TPID 0x8100, extend VLAN is enabled only.
795+
796+
To start ``testpmd``, and enable QinQ strip for default TPID on port 0:
797+
798+
.. code-block:: console
799+
800+
./<build_dir>/app/dpdk-testpmd -l 0-15 -- -i --forward-mode=mac
801+
...
802+
803+
testpmd> vlan set extend on 0
804+
testpmd> vlan set qinq_strip on 0

drivers/net/intel/iavf/iavf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ struct iavf_adapter {
387387
uint16_t fdir_ref_cnt;
388388
struct iavf_devargs devargs;
389389
bool mac_primary_set;
390+
uint16_t tpid; /* VLAN tag identifier */
390391
};
391392

392393
/* IAVF_DEV_PRIVATE_TO */
@@ -456,6 +457,7 @@ int iavf_configure_rss_key(struct iavf_adapter *adapter);
456457
int iavf_configure_queues(struct iavf_adapter *adapter, uint16_t num_queue_pairs);
457458
int iavf_get_supported_rxdid(struct iavf_adapter *adapter);
458459
int iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable);
460+
int iavf_config_outer_vlan_strip_v2(struct iavf_adapter *adapter, bool enable);
459461
int iavf_config_vlan_insert_v2(struct iavf_adapter *adapter, bool enable);
460462
int iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid,
461463
bool add);

drivers/net/intel/iavf/iavf_ethdev.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ static int iavf_dev_add_mac_addr(struct rte_eth_dev *dev,
127127
static void iavf_dev_del_mac_addr(struct rte_eth_dev *dev, uint32_t index);
128128
static int iavf_dev_vlan_filter_set(struct rte_eth_dev *dev,
129129
uint16_t vlan_id, int on);
130+
static int iavf_vlan_tpid_set(struct rte_eth_dev *dev,
131+
enum rte_vlan_type vlan_type, uint16_t tpid);
130132
static int iavf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
131133
static int iavf_dev_rss_reta_update(struct rte_eth_dev *dev,
132134
struct rte_eth_rss_reta_entry64 *reta_conf,
@@ -226,6 +228,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
226228
.mac_addr_remove = iavf_dev_del_mac_addr,
227229
.set_mc_addr_list = iavf_set_mc_addr_list,
228230
.vlan_filter_set = iavf_dev_vlan_filter_set,
231+
.vlan_tpid_set = iavf_vlan_tpid_set,
229232
.vlan_offload_set = iavf_dev_vlan_offload_set,
230233
.rx_queue_start = iavf_dev_rx_queue_start,
231234
.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)
13651368
vf->mac_num--;
13661369
}
13671370

1371+
static int
1372+
iavf_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type, uint16_t tpid)
1373+
{
1374+
struct iavf_adapter *adapter =
1375+
IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
1376+
struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
1377+
int qinq = dev_conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
1378+
1379+
if (vlan_type != RTE_ETH_VLAN_TYPE_OUTER) {
1380+
PMD_DRV_LOG(ERR, "Unsupported vlan type.");
1381+
return -EINVAL;
1382+
} else if (!qinq) {
1383+
PMD_DRV_LOG(ERR, "VLAN-extend disabled.");
1384+
return -ENOSYS;
1385+
} else if (tpid != RTE_ETHER_TYPE_VLAN &&
1386+
tpid != RTE_ETHER_TYPE_QINQ) {
1387+
PMD_DRV_LOG(ERR, "tpid supported 0x8100/0x88A8");
1388+
return -ENOTSUP;
1389+
}
1390+
1391+
/* This API only fills internal iavf_adapter structure
1392+
* and does not send any signal to hardware.
1393+
* Inner VLAN always 0x8100, so not set explicitly.
1394+
*/
1395+
if (qinq && vlan_type == RTE_ETH_VLAN_TYPE_OUTER)
1396+
adapter->tpid = tpid; /* Outer VLAN can be 0x88a8 or 0x8100 */
1397+
1398+
return 0;
1399+
}
1400+
13681401
static int
13691402
iavf_disable_vlan_strip_ex(struct rte_eth_dev *dev, int on)
13701403
{
@@ -1453,6 +1486,8 @@ iavf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask)
14531486
struct iavf_adapter *adapter =
14541487
IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
14551488
bool enable;
1489+
int qinq = dev->data->dev_conf.rxmode.offloads &
1490+
RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
14561491
int err;
14571492

14581493
if (mask & RTE_ETH_VLAN_FILTER_MASK) {
@@ -1472,6 +1507,20 @@ iavf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask)
14721507
return -EIO;
14731508
}
14741509

1510+
if (mask & RTE_ETH_QINQ_STRIP_MASK) {
1511+
if (!qinq) {
1512+
PMD_DRV_LOG(ERR, "VLAN-extend disabled");
1513+
return -ENOSYS;
1514+
}
1515+
enable = !!(rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP);
1516+
err = iavf_config_outer_vlan_strip_v2(adapter, enable);
1517+
/* If not support, the stripping is already disabled by PF */
1518+
if (err == -ENOTSUP && !enable)
1519+
err = 0;
1520+
if (err)
1521+
return -EIO;
1522+
}
1523+
14751524
return 0;
14761525
}
14771526

@@ -2812,6 +2861,7 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
28122861
adapter->dev_data = eth_dev->data;
28132862
adapter->stopped = 1;
28142863
adapter->mac_primary_set = false;
2864+
adapter->tpid = RTE_ETHER_TYPE_VLAN; /* VLAN TPID set to 0x8100 by default */
28152865

28162866
if (iavf_dev_event_handler_init())
28172867
goto init_vf_err;

drivers/net/intel/iavf/iavf_vchnl.c

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,50 @@ iavf_get_supported_rxdid(struct iavf_adapter *adapter)
829829
return 0;
830830
}
831831

832+
int
833+
iavf_config_outer_vlan_strip_v2(struct iavf_adapter *adapter, bool enable)
834+
{
835+
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
836+
struct virtchnl_vlan_supported_caps *stripping_caps;
837+
struct virtchnl_vlan_setting vlan_strip;
838+
uint8_t msg_buf[IAVF_AQ_BUF_SZ] = {0};
839+
struct iavf_cmd_info args;
840+
uint32_t *ethertype;
841+
int ret;
842+
843+
memset(&vlan_strip, 0, sizeof(vlan_strip));
844+
stripping_caps = &vf->vlan_v2_caps.offloads.stripping_support;
845+
if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_88A8) &&
846+
(stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE) &&
847+
adapter->tpid == RTE_ETHER_TYPE_QINQ) {
848+
ethertype = &vlan_strip.outer_ethertype_setting;
849+
*ethertype = VIRTCHNL_VLAN_ETHERTYPE_88A8;
850+
} else if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
851+
(stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE) &&
852+
adapter->tpid == RTE_ETHER_TYPE_VLAN) {
853+
ethertype = &vlan_strip.outer_ethertype_setting;
854+
*ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
855+
} else {
856+
return -ENOTSUP;
857+
}
858+
859+
vlan_strip.vport_id = vf->vsi_res->vsi_id;
860+
861+
args.ops = enable ? VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2 :
862+
VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2;
863+
args.in_args = (uint8_t *)&vlan_strip;
864+
args.in_args_size = sizeof(vlan_strip);
865+
args.out_buffer = msg_buf;
866+
args.out_size = IAVF_AQ_BUF_SZ;
867+
ret = iavf_execute_vf_cmd_safe(adapter, &args);
868+
if (ret)
869+
PMD_DRV_LOG(ERR, "fail to execute command %s",
870+
enable ? "VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2" :
871+
"VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2");
872+
873+
return ret;
874+
}
875+
832876
int
833877
iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable)
834878
{
@@ -838,14 +882,20 @@ iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable)
838882
uint8_t msg_buf[IAVF_AQ_BUF_SZ] = {0};
839883
struct iavf_cmd_info args;
840884
uint32_t *ethertype;
885+
int qinq = adapter->dev_data->dev_conf.rxmode.offloads &
886+
RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
841887
int ret;
842888

843889
stripping_caps = &vf->vlan_v2_caps.offloads.stripping_support;
844890

845-
if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
891+
/* When VLAN extend is disabled, Single VLAN mode which is Outer VLAN
892+
* When VLAN extend is enabled, QinQ mode, this API works only on
893+
* Inner VLAN strip which is always 0x8100.
894+
*/
895+
if (!qinq && (stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
846896
(stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE))
847897
ethertype = &vlan_strip.outer_ethertype_setting;
848-
else if ((stripping_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
898+
else if (qinq && (stripping_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
849899
(stripping_caps->inner & VIRTCHNL_VLAN_TOGGLE))
850900
ethertype = &vlan_strip.inner_ethertype_setting;
851901
else
@@ -921,6 +971,8 @@ iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid, bool add)
921971
struct virtchnl_vlan *vlan_setting;
922972
struct iavf_cmd_info args;
923973
uint32_t filtering_caps;
974+
int qinq = adapter->dev_data->dev_conf.rxmode.offloads &
975+
RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
924976
int err;
925977

926978
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)
938990
memset(&vlan_filter, 0, sizeof(vlan_filter));
939991
vlan_filter.vport_id = vf->vsi_res->vsi_id;
940992
vlan_filter.num_elements = 1;
941-
vlan_setting->tpid = RTE_ETHER_TYPE_VLAN;
993+
if (qinq && adapter->tpid == RTE_ETHER_TYPE_QINQ)
994+
vlan_setting->tpid = RTE_ETHER_TYPE_QINQ;
995+
else
996+
vlan_setting->tpid = RTE_ETHER_TYPE_VLAN;
942997
vlan_setting->tci = vlanid;
943998

944999
args.ops = add ? VIRTCHNL_OP_ADD_VLAN_V2 : VIRTCHNL_OP_DEL_VLAN_V2;

0 commit comments

Comments
 (0)