QinQ insertion with VLAN TPID 0x88a8 support is absent. This patch adds support for QinQ insertion for 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 for TPID 0x88a8.
Signed-off-by: Anurag Mandal <[email protected]> --- doc/guides/nics/intel_vf.rst | 19 ++++++++++ drivers/net/intel/iavf/iavf.h | 1 + drivers/net/intel/iavf/iavf_vchnl.c | 56 +++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/intel_vf.rst b/doc/guides/nics/intel_vf.rst index dfff69b982..ce11ea6363 100644 --- a/doc/guides/nics/intel_vf.rst +++ b/doc/guides/nics/intel_vf.rst @@ -802,3 +802,22 @@ To start ``testpmd``, and enable QinQ strip for default TPID on port 0: testpmd> vlan set extend on 0 testpmd> vlan set qinq_strip on 0 + +QinQ Configuration +~~~~~~~~~~~~~~~~~~ + +When using QinQ Tx offload (``RTE_ETH_TX_OFFLOAD_QINQ_INSERT``), +you must also enable ``RTE_ETH_RX_OFFLOAD_VLAN_EXTEND`` +to configure the hardware for double VLAN mode. +Without this, only the inner VLAN tag will be inserted. + +Example:: + + struct rte_eth_conf port_conf = { + .rxmode = { + .offloads = RTE_ETH_RX_OFFLOAD_VLAN_EXTEND, + }, + .txmode = { + .offloads = RTE_ETH_TX_OFFLOAD_QINQ_INSERT, + }, + }; diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h index 6a77dacf59..0b6ed221d0 100644 --- a/drivers/net/intel/iavf/iavf.h +++ b/drivers/net/intel/iavf/iavf.h @@ -459,6 +459,7 @@ 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_config_outer_vlan_insert_v2(struct iavf_adapter *adapter, bool enable); int iavf_add_del_vlan_v2(struct iavf_adapter *adapter, uint16_t vlanid, bool add); int iavf_get_vlan_offload_caps_v2(struct iavf_adapter *adapter); diff --git a/drivers/net/intel/iavf/iavf_vchnl.c b/drivers/net/intel/iavf/iavf_vchnl.c index c2f340db81..6dd7d455ba 100644 --- a/drivers/net/intel/iavf/iavf_vchnl.c +++ b/drivers/net/intel/iavf/iavf_vchnl.c @@ -920,6 +920,51 @@ iavf_config_vlan_strip_v2(struct iavf_adapter *adapter, bool enable) return ret; } +int +iavf_config_outer_vlan_insert_v2(struct iavf_adapter *adapter, bool enable) +{ + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter); + struct virtchnl_vlan_supported_caps *insertion_caps; + struct virtchnl_vlan_setting vlan_insert; + uint8_t msg_buf[IAVF_AQ_BUF_SZ] = {0}; + struct iavf_cmd_info args; + uint32_t *ethertype; + int ret; + + memset(&vlan_insert, 0, sizeof(vlan_insert)); + insertion_caps = &vf->vlan_v2_caps.offloads.insertion_support; + + if ((insertion_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_88A8) && + (insertion_caps->outer & VIRTCHNL_VLAN_TOGGLE) && + adapter->tpid == RTE_ETHER_TYPE_QINQ) { + ethertype = &vlan_insert.outer_ethertype_setting; + *ethertype = VIRTCHNL_VLAN_ETHERTYPE_88A8; + } else if ((insertion_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) && + (insertion_caps->outer & VIRTCHNL_VLAN_TOGGLE) && + adapter->tpid == RTE_ETHER_TYPE_VLAN) { + ethertype = &vlan_insert.outer_ethertype_setting; + *ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100; + } else { + return -ENOTSUP; + } + + vlan_insert.vport_id = vf->vsi_res->vsi_id; + + args.ops = enable ? VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2 : + VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2; + args.in_args = (uint8_t *)&vlan_insert; + args.in_args_size = sizeof(vlan_insert); + 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_INSERTION_V2" : + "VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2"); + + return ret; +} + int iavf_config_vlan_insert_v2(struct iavf_adapter *adapter, bool enable) { @@ -929,14 +974,21 @@ iavf_config_vlan_insert_v2(struct iavf_adapter *adapter, bool enable) uint8_t msg_buf[IAVF_AQ_BUF_SZ] = {0}; struct iavf_cmd_info args; uint32_t *ethertype; + bool qinq = adapter->dev_data->dev_conf.rxmode.offloads & + RTE_ETH_RX_OFFLOAD_VLAN_EXTEND; + bool insert_qinq = adapter->dev_data->dev_conf.txmode.offloads & + RTE_ETH_TX_OFFLOAD_QINQ_INSERT; int ret; + if (qinq && insert_qinq) + iavf_config_outer_vlan_insert_v2(adapter, enable); + insertion_caps = &vf->vlan_v2_caps.offloads.insertion_support; - if ((insertion_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) && + if (!qinq && (insertion_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) && (insertion_caps->outer & VIRTCHNL_VLAN_TOGGLE)) ethertype = &vlan_insert.outer_ethertype_setting; - else if ((insertion_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100) && + else if (qinq && (insertion_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100) && (insertion_caps->inner & VIRTCHNL_VLAN_TOGGLE)) ethertype = &vlan_insert.inner_ethertype_setting; else -- 2.34.1

