From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f53.google.com (mail-wm0-f53.google.com [74.125.82.53]) by dpdk.org (Postfix) with ESMTP id 979D71CA84 for ; Thu, 5 Apr 2018 11:55:05 +0200 (CEST) Received: by mail-wm0-f53.google.com with SMTP id r131so5273919wmb.2 for ; Thu, 05 Apr 2018 02:55:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=MItw4DKjftQf/TFBOywHxdzLrqg8wz12OMAhyd7bXoo=; b=A4fwwxzk+VNQYuzkkh0nRB8AOgYgd5lVQwkd1H5IYtbc4nAm501brMeql4l4nDqdeo ahWzJqvxCkjLHTnzi+s8z8f+0dYuuVmzbp0FHLvRI5z1tcDM0Hq1jigdaMaHkoKj+B7/ BMVInJeJJ9GYgBGpFAtc9AYssclG9m1LDvpz3mFxejLUpVTXLin7Fy8y7ZHNkCzEmDI+ fvWnUraMF7Y9UrFM1MoyWgglGN4p34nYc6tuVLNu5WoGjTihkf6JvEbxwC2FoJI5YVD7 OWltF2pTlGWLS4vNmH3O394WNlsA3m3xO8RT4tTA1Dlc+C8SrrpZ7pssLs0c2Kg1MxTQ f0wA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=MItw4DKjftQf/TFBOywHxdzLrqg8wz12OMAhyd7bXoo=; b=FU1hciaAahoLT3XcoMVTuA7DgjUy192Q9S2KOLKomB7X6OkZD8wKFGKxk1VUljhBtm 0ploOXJJ6t5YNd3yVl/tcCZ0a2QFF7rsMuZcsms8jXc/36RfWcXSLUF96d87kFWRyNkn 56Kb4SnTA83BcrwTVZbOlF+Cxf9s+xKcfiUhTBOZ5B2TQdYPfPNig58w5pIBvWpFe8O+ CeOAHtDaf2AhBQiKXzgG70S0kKbCUz2qg6ZhzWFmFOnmMk5DgKn//kQ1QACVBCT47TFL ovFoEaen/QBfGVihoumGumyZUERMa9qUh44eSdyYG2kFkiXG6KRPVcVZvRoofkKaO+hv ggNQ== X-Gm-Message-State: AElRT7G/BZHls3lhICjlLLOZ+AqyxNF2zxJvsOBlNav8gdxxxnptYzfw R30p46r3q10pGV6oOV9+XFEL X-Google-Smtp-Source: AIpwx4+T9HkR7tPNZBKeEYHmlgsv9zvyBzMBk0bG4driVyvSRXntdNWVSPLHXxa/CpaZxBAVsHRe+Q== X-Received: by 10.28.108.20 with SMTP id h20mr10818924wmc.69.1522922105100; Thu, 05 Apr 2018 02:55:05 -0700 (PDT) Received: from laranjeiro-vm.dev.6wind.com (host.78.145.23.62.rev.coltfrance.com. [62.23.145.78]) by smtp.gmail.com with ESMTPSA id c21sm5309940wre.43.2018.04.05.02.55.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 05 Apr 2018 02:55:04 -0700 (PDT) Date: Thu, 5 Apr 2018 11:55:10 +0200 From: =?iso-8859-1?Q?N=E9lio?= Laranjeiro To: Adrien Mazarguil Cc: Thomas Monjalon , Ferruh Yigit , dev@dpdk.org, Wenzhuo Lu , Jingjing Wu , Ajit Khaparde , Somnath Kotur , John Daley , Hyong Youb Kim , Beilei Xing , Qi Zhang , Konstantin Ananyev , Yongseok Koh , Jacek Siuda , Tomasz Duszynski , Dmitri Epshtein , Natalie Samsonov , Jianbo Liu , Andrew Rybchenko , Pascal Mazon Message-ID: <20180405095510.rufofyaek6aqqenw@laranjeiro-vm.dev.6wind.com> References: <20180404150312.12304-1-adrien.mazarguil@6wind.com> <20180404150312.12304-12-adrien.mazarguil@6wind.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180404150312.12304-12-adrien.mazarguil@6wind.com> User-Agent: NeoMutt/20170113 (1.7.2) Subject: Re: [dpdk-dev] [PATCH v1 11/16] ethdev: refine TPID handling in flow API X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Apr 2018 09:55:05 -0000 On Wed, Apr 04, 2018 at 05:56:49PM +0200, Adrien Mazarguil wrote: > TPID handling in rte_flow VLAN and E_TAG pattern item definitions is not > consistent with the normal stacking order of pattern items, which is > confusing to applications. > > Problem is that when followed by one of these layers, the EtherType field > of the preceding layer keeps its "inner" definition, and the "outer" TPID > is provided by the subsequent layer, the reverse of how a packet looks like > on the wire: > > Wire: [ ETH TPID = A | VLAN EtherType = B | B DATA ] > rte_flow: [ ETH EtherType = B | VLAN TPID = A | B DATA ] > > Worse, when QinQ is involved, the stacking order of VLAN layers is > unspecified. It is unclear whether it should be reversed (innermost to > outermost) as well given TPID applies to the previous layer: > > Wire: [ ETH TPID = A | VLAN TPID = B | VLAN EtherType = C | C DATA ] > rte_flow 1: [ ETH EtherType = C | VLAN TPID = B | VLAN TPID = A | C DATA ] > rte_flow 2: [ ETH EtherType = C | VLAN TPID = A | VLAN TPID = B | C DATA ] > > While specifying EtherType/TPID is hopefully rarely necessary, the stacking > order in case of QinQ and the lack of documentation remain an issue. > > This patch replaces TPID in the VLAN pattern item with an inner > EtherType/TPID as is usually done everywhere else (e.g. struct vlan_hdr), > clarifies documentation and updates all relevant code. > > Summary of changes for PMDs that implement ETH, VLAN or E_TAG pattern > items: > > - bnxt: EtherType matching is supported, and vlan->inner_type overrides > eth->type if the latter has standard TPID value 0x8100, otherwise an > error is triggered. > > - e1000: EtherType matching is only supported with the ETHERTYPE filter, > which does not support VLAN matching, therefore no impact. > > - enic: same as bnxt. > > - i40e: same as bnxt with a configurable TPID value for the FDIR filter, > with existing limitations on allowed EtherType values. The remaining > filter types (VXLAN, NVGRE, QINQ) do not support EtherType matching. > > - ixgbe: same as e1000. > > - mlx4: EtherType/TPID matching is not supported, no impact. > > - mlx5: same as bnxt. > > - mrvl: EtherType matching is supported but eth->type cannot be specified > when a VLAN item is present. However vlan->inner_type is used if > specified. > > - sfc: same as bnxt with QinQ TPID value 0x88a8 additionally supported. > > - tap: same as bnxt. > > Signed-off-by: Adrien Mazarguil > Cc: Ferruh Yigit > Cc: Thomas Monjalon > Cc: Wenzhuo Lu > Cc: Jingjing Wu > Cc: Ajit Khaparde > Cc: Somnath Kotur > Cc: John Daley > Cc: Hyong Youb Kim > Cc: Beilei Xing > Cc: Qi Zhang > Cc: Konstantin Ananyev > Cc: Nelio Laranjeiro > Cc: Yongseok Koh > Cc: Jacek Siuda > Cc: Tomasz Duszynski > Cc: Dmitri Epshtein > Cc: Natalie Samsonov > Cc: Jianbo Liu > Cc: Andrew Rybchenko > Cc: Pascal Mazon > > --- > > Hi PMD maintainers, while I'm pretty confident in these changes, I could > not validate them with all devices. > > It would be great if you could apply this patch, run testpmd, create VLAN > flow rules with/without inner EtherType as described and send matching > traffic while making sure nothing was broken in the process. > > Thanks! > --- > app/test-pmd/cmdline_flow.c | 17 +++--- > doc/guides/nics/tap.rst | 2 +- > doc/guides/prog_guide/rte_flow.rst | 21 +++++-- > doc/guides/testpmd_app_ug/testpmd_funcs.rst | 4 +- > drivers/net/bnxt/bnxt_filter.c | 38 ++++++++++-- > drivers/net/enic/enic_flow.c | 21 ++++--- > drivers/net/i40e/i40e_flow.c | 74 ++++++++++++++++++++---- > drivers/net/mlx5/mlx5_flow.c | 14 ++++- > drivers/net/mvpp2/mrvl_flow.c | 27 +++++++-- > drivers/net/sfc/sfc_flow.c | 27 +++++++++ > drivers/net/tap/tap_flow.c | 16 +++-- > lib/librte_ether/rte_flow.h | 24 +++++--- > 12 files changed, 227 insertions(+), 58 deletions(-) > > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c > index 2fbd3d8ef..3a486032d 100644 > --- a/app/test-pmd/cmdline_flow.c > +++ b/app/test-pmd/cmdline_flow.c > @@ -99,11 +99,11 @@ enum index { > ITEM_ETH_SRC, > ITEM_ETH_TYPE, > ITEM_VLAN, > - ITEM_VLAN_TPID, > ITEM_VLAN_TCI, > ITEM_VLAN_PCP, > ITEM_VLAN_DEI, > ITEM_VLAN_VID, > + ITEM_VLAN_INNER_TYPE, > ITEM_IPV4, > ITEM_IPV4_TOS, > ITEM_IPV4_TTL, > @@ -505,11 +505,11 @@ static const enum index item_eth[] = { > }; > > static const enum index item_vlan[] = { > - ITEM_VLAN_TPID, > ITEM_VLAN_TCI, > ITEM_VLAN_PCP, > ITEM_VLAN_DEI, > ITEM_VLAN_VID, > + ITEM_VLAN_INNER_TYPE, > ITEM_NEXT, > ZERO, > }; > @@ -1142,12 +1142,6 @@ static const struct token token_list[] = { > .next = NEXT(item_vlan), > .call = parse_vc, > }, > - [ITEM_VLAN_TPID] = { > - .name = "tpid", > - .help = "tag protocol identifier", > - .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), > - .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)), > - }, > [ITEM_VLAN_TCI] = { > .name = "tci", > .help = "tag control information", > @@ -1175,6 +1169,13 @@ static const struct token token_list[] = { > .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, > tci, "\x0f\xff")), > }, > + [ITEM_VLAN_INNER_TYPE] = { > + .name = "inner_type", > + .help = "inner EtherType", > + .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), > + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, > + inner_type)), > + }, > [ITEM_IPV4] = { > .name = "ipv4", > .help = "match IPv4 header", > diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst > index 76eb0bde4..bcf3efe9e 100644 > --- a/doc/guides/nics/tap.rst > +++ b/doc/guides/nics/tap.rst > @@ -97,7 +97,7 @@ The kernel support can be checked with this command:: > Supported items: > > - eth: src and dst (with variable masks), and eth_type (0xffff mask). > -- vlan: vid, pcp, tpid, but not eid. (requires kernel 4.9) > +- vlan: vid, pcp, but not eid. (requires kernel 4.9) > - ipv4/6: src and dst (with variable masks), and ip_proto (0xffff mask). > - udp/tcp: src and dst port (0xffff) mask. > > diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst > index c893d737a..f1b9d8d76 100644 > --- a/doc/guides/prog_guide/rte_flow.rst > +++ b/doc/guides/prog_guide/rte_flow.rst > @@ -784,9 +784,15 @@ Item: ``ETH`` > > Matches an Ethernet header. > > +The ``type`` field either stands for "EtherType" or "TPID" when followed by > +so-called layer 2.5 pattern items such as ``RTE_FLOW_ITEM_TYPE_VLAN``. In > +the latter case, ``type`` refers to that of the outer header, with the inner > +EtherType/TPID provided by the subsequent pattern item. This is the same > +order as on the wire. > + > - ``dst``: destination MAC. > - ``src``: source MAC. > -- ``type``: EtherType. > +- ``type``: EtherType or TPID. > - Default ``mask`` matches destination and source addresses only. > > Item: ``VLAN`` > @@ -794,9 +800,13 @@ Item: ``VLAN`` > > Matches an 802.1Q/ad VLAN tag. > > -- ``tpid``: tag protocol identifier. > +The corresponding standard outer EtherType (TPID) values are ``0x8100`` or > +``0x88a8`` (in case of outer QinQ). It can be overridden by the preceding > +pattern item. > + > - ``tci``: tag control information. > -- Default ``mask`` matches TCI only. > +- ``inner_type``: inner EtherType or TPID. > +- Default ``mask`` matches the VID part of TCI only (lower 12 bits). > > Item: ``IPV4`` > ^^^^^^^^^^^^^^ > @@ -866,12 +876,15 @@ Item: ``E_TAG`` > > Matches an IEEE 802.1BR E-Tag header. > > -- ``tpid``: tag protocol identifier (0x893F) > +The corresponding standard outer EtherType (TPID) value is 0x893f. > +It can be overridden by the preceding pattern item. > + > - ``epcp_edei_in_ecid_b``: E-Tag control information (E-TCI), E-PCP (3b), > E-DEI (1b), ingress E-CID base (12b). > - ``rsvd_grp_ecid_b``: reserved (2b), GRP (2b), E-CID base (12b). > - ``in_ecid_e``: ingress E-CID ext. > - ``ecid_e``: E-CID ext. > +- ``inner_type``: inner EtherType or TPID. > - Default ``mask`` simultaneously matches GRP and E-CID base. > > Item: ``NVGRE`` > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst > index 738461f44..25fac8430 100644 > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst > @@ -3223,15 +3223,15 @@ This section lists supported pattern items and their attributes, if any. > > - ``dst {MAC-48}``: destination MAC. > - ``src {MAC-48}``: source MAC. > - - ``type {unsigned}``: EtherType. > + - ``type {unsigned}``: EtherType or TPID. > > - ``vlan``: match 802.1Q/ad VLAN tag. > > - - ``tpid {unsigned}``: tag protocol identifier. > - ``tci {unsigned}``: tag control information. > - ``pcp {unsigned}``: priority code point. > - ``dei {unsigned}``: drop eligible indicator. > - ``vid {unsigned}``: VLAN identifier. > + - ``inner_type {unsigned}``: inner EtherType or TPID. > > - ``ipv4``: match IPv4 header. > > diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c > index 0d735edf6..a97a8dd46 100644 > --- a/drivers/net/bnxt/bnxt_filter.c > +++ b/drivers/net/bnxt/bnxt_filter.c > @@ -327,6 +327,7 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, > uint32_t vf = 0; > int use_ntuple; > uint32_t en = 0; > + uint32_t en_ethertype; > int dflt_vnic; > > use_ntuple = bnxt_filter_type_check(pattern, error); > @@ -336,6 +337,9 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, > > filter->filter_type = use_ntuple ? > HWRM_CFA_NTUPLE_FILTER : HWRM_CFA_EM_FILTER; > + en_ethertype = use_ntuple ? > + NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE : > + EM_FLOW_ALLOC_INPUT_EN_ETHERTYPE; > > while (item->type != RTE_FLOW_ITEM_TYPE_END) { > if (item->last) { > @@ -405,30 +409,52 @@ bnxt_validate_and_parse_flow_type(struct bnxt *bp, > if (eth_mask->type) { > filter->ethertype = > rte_be_to_cpu_16(eth_spec->type); > - en |= use_ntuple ? > - NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE : > - EM_FLOW_ALLOC_INPUT_EN_ETHERTYPE; > + en |= en_ethertype; > } > > break; > case RTE_FLOW_ITEM_TYPE_VLAN: > vlan_spec = item->spec; > vlan_mask = item->mask; > + if (en & en_ethertype && > + filter->ethertype != RTE_BE16(0x8100)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "unsupported outer TPID"); > + return -rte_errno; > + } > if (vlan_mask->tci && > - vlan_mask->tci == RTE_BE16(0x0fff) && > - !vlan_mask->tpid) { > + vlan_mask->tci == RTE_BE16(0x0fff)) { > /* Only the VLAN ID can be matched. */ > filter->l2_ovlan = > rte_be_to_cpu_16(vlan_spec->tci & > RTE_BE16(0x0fff)); > en |= EM_FLOW_ALLOC_INPUT_EN_OVLAN_VID; > - } else if (vlan_mask->tci || vlan_mask->tpid) { > + } else if (vlan_mask->tci) { > rte_flow_error_set(error, EINVAL, > RTE_FLOW_ERROR_TYPE_ITEM, > item, > "VLAN mask is invalid"); > return -rte_errno; > } > + if (vlan_mask->inner_type && > + vlan_mask->inner_type != RTE_BE16(0xffff)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "inner ethertype mask not" > + " valid"); > + return -rte_errno; > + } > + if (vlan_mask->inner_type) { > + filter->ethertype = > + rte_be_to_cpu_16(vlan_spec->inner_type); > + en |= en_ethertype; > + } else { > + filter->ethertype = RTE_BE16(0x0000); > + en &= ~en_ethertype; > + } > > break; > case RTE_FLOW_ITEM_TYPE_IPV4: > diff --git a/drivers/net/enic/enic_flow.c b/drivers/net/enic/enic_flow.c > index c5c98b870..a413740ab 100644 > --- a/drivers/net/enic/enic_flow.c > +++ b/drivers/net/enic/enic_flow.c > @@ -4,6 +4,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -545,16 +546,22 @@ enic_copy_item_vlan_v2(const struct rte_flow_item *item, > if (!spec) > return 0; > > - /* Don't support filtering in tpid */ > - if (mask) { > - if (mask->tpid != 0) > - return ENOTSUP; > - } else { > + if (!mask) > mask = &rte_flow_item_vlan_mask; > - RTE_ASSERT(mask->tpid == 0); > - } > > if (*inner_ofst == 0) { > + struct ether_hdr *eth_mask = > + (void *)gp->layer[FILTER_GENERIC_1_L2].mask; > + struct ether_hdr *eth_val = > + (void *)gp->layer[FILTER_GENERIC_1_L2].val; > + > + /* Exactly one TPID value is allowed if specified */ > + if ((eth_val->ether_type & eth_mask->ether_type) != > + (RTE_BE16(0x8100) & eth_mask->ether_type)) > + return ENOTSUP; > + eth_mask->ether_type = mask->inner_type; > + eth_val->ether_type = spec->inner_type; > + > /* Outer header. Use the vlan mask/val fields */ > gp->mask_vlan = mask->tci; > gp->val_vlan = spec->tci; > diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c > index 1b336df74..c6dd889ad 100644 > --- a/drivers/net/i40e/i40e_flow.c > +++ b/drivers/net/i40e/i40e_flow.c > @@ -2490,24 +2490,36 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, > "Invalid MAC_addr mask."); > return -rte_errno; > } > + } > + if (eth_spec && eth_mask && eth_mask->type) { > + enum rte_flow_item_type next = (item + 1)->type; > > - if ((eth_mask->type & UINT16_MAX) == > - UINT16_MAX) { > - input_set |= I40E_INSET_LAST_ETHER_TYPE; > - filter->input.flow.l2_flow.ether_type = > - eth_spec->type; > + if (eth_mask->type != RTE_BE16(0xffff)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid type mask."); > + return -rte_errno; > } > > ether_type = rte_be_to_cpu_16(eth_spec->type); > - if (ether_type == ETHER_TYPE_IPv4 || > - ether_type == ETHER_TYPE_IPv6 || > - ether_type == ETHER_TYPE_ARP || > - ether_type == outer_tpid) { > + > + if ((next == RTE_FLOW_ITEM_TYPE_VLAN && > + ether_type != outer_tpid) || > + (next != RTE_FLOW_ITEM_TYPE_VLAN && > + (ether_type == ETHER_TYPE_IPv4 || > + ether_type == ETHER_TYPE_IPv6 || > + ether_type == ETHER_TYPE_ARP || > + ether_type == outer_tpid))) { > rte_flow_error_set(error, EINVAL, > RTE_FLOW_ERROR_TYPE_ITEM, > item, > "Unsupported ether_type."); > return -rte_errno; > + } else if (next != RTE_FLOW_ITEM_TYPE_VLAN) { > + input_set |= I40E_INSET_LAST_ETHER_TYPE; > + filter->input.flow.l2_flow.ether_type = > + eth_spec->type; > } > } > > @@ -2518,6 +2530,14 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, > case RTE_FLOW_ITEM_TYPE_VLAN: > vlan_spec = item->spec; > vlan_mask = item->mask; > + > + if (input_set & I40E_INSET_LAST_ETHER_TYPE) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Unsupported outer TPID."); > + return -rte_errno; > + } > if (vlan_spec && vlan_mask) { > if (vlan_mask->tci == > rte_cpu_to_be_16(I40E_TCI_MASK)) { > @@ -2526,6 +2546,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, > vlan_spec->tci; > } > } > + if (vlan_spec && vlan_mask && vlan_mask->inner_type) { > + if (vlan_mask->inner_type != RTE_BE16(0xffff)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid inner_type" > + " mask."); > + return -rte_errno; > + } > + > + ether_type = > + rte_be_to_cpu_16(vlan_spec->inner_type); > + > + if (ether_type == ETHER_TYPE_IPv4 || > + ether_type == ETHER_TYPE_IPv6 || > + ether_type == ETHER_TYPE_ARP || > + ether_type == outer_tpid) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Unsupported inner_type."); > + return -rte_errno; > + } > + input_set |= I40E_INSET_LAST_ETHER_TYPE; > + filter->input.flow.l2_flow.ether_type = > + vlan_spec->inner_type; > + } > > pctype = I40E_FILTER_PCTYPE_L2_PAYLOAD; > layer_idx = I40E_FLXPLD_L2_IDX; > @@ -3284,7 +3331,8 @@ i40e_flow_parse_vxlan_pattern(__rte_unused struct rte_eth_dev *dev, > case RTE_FLOW_ITEM_TYPE_VLAN: > vlan_spec = item->spec; > vlan_mask = item->mask; > - if (!(vlan_spec && vlan_mask)) { > + if (!(vlan_spec && vlan_mask) || > + vlan_mask->inner_type) { > rte_flow_error_set(error, EINVAL, > RTE_FLOW_ERROR_TYPE_ITEM, > item, > @@ -3514,7 +3562,8 @@ i40e_flow_parse_nvgre_pattern(__rte_unused struct rte_eth_dev *dev, > case RTE_FLOW_ITEM_TYPE_VLAN: > vlan_spec = item->spec; > vlan_mask = item->mask; > - if (!(vlan_spec && vlan_mask)) { > + if (!(vlan_spec && vlan_mask) || > + vlan_mask->inner_type) { > rte_flow_error_set(error, EINVAL, > RTE_FLOW_ERROR_TYPE_ITEM, > item, > @@ -4022,7 +4071,8 @@ i40e_flow_parse_qinq_pattern(__rte_unused struct rte_eth_dev *dev, > vlan_spec = item->spec; > vlan_mask = item->mask; > > - if (!(vlan_spec && vlan_mask)) { > + if (!(vlan_spec && vlan_mask) || > + vlan_mask->inner_type) { > rte_flow_error_set(error, EINVAL, > RTE_FLOW_ERROR_TYPE_ITEM, > item, > diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c > index bc1176819..f03413d32 100644 > --- a/drivers/net/mlx5/mlx5_flow.c > +++ b/drivers/net/mlx5/mlx5_flow.c > @@ -17,6 +17,7 @@ > #pragma GCC diagnostic error "-Wpedantic" > #endif > > +#include > #include > #include > #include > @@ -306,6 +307,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { > .actions = valid_actions, > .mask = &(const struct rte_flow_item_vlan){ > .tci = -1, > + .inner_type = -1, > }, > .default_mask = &rte_flow_item_vlan_mask, > .mask_sz = sizeof(struct rte_flow_item_vlan), > @@ -1285,6 +1287,7 @@ mlx5_flow_create_vlan(const struct rte_flow_item *item, > struct mlx5_flow_parse *parser = data->parser; > struct ibv_flow_spec_eth *eth; > const unsigned int eth_size = sizeof(struct ibv_flow_spec_eth); > + const char *msg = "VLAN cannot be empty"; > > if (spec) { > unsigned int i; > @@ -1306,12 +1309,21 @@ mlx5_flow_create_vlan(const struct rte_flow_item *item, > */ > if (!eth->mask.vlan_tag) > goto error; > + /* Exactly one TPID value is allowed if specified. */ > + if ((eth->val.ether_type & eth->mask.ether_type) != > + (RTE_BE16(0x8100) & eth->mask.ether_type)) { You can use ETHER_TYPE_VLAN present in rte_ether.h instead of hard coded values. > + msg = "unsupported outer TPID"; > + goto error; > + } > + eth->val.ether_type = spec->inner_type; > + eth->mask.ether_type = mask->inner_type; > + eth->val.ether_type &= eth->mask.ether_type; > } > return 0; > } > error: > return rte_flow_error_set(data->error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, > - item, "VLAN cannot be empty"); > + item, msg); > } > > /** > diff --git a/drivers/net/mvpp2/mrvl_flow.c b/drivers/net/mvpp2/mrvl_flow.c > index 8fd4dbfb1..6604a411f 100644 > --- a/drivers/net/mvpp2/mrvl_flow.c > +++ b/drivers/net/mvpp2/mrvl_flow.c > @@ -1091,12 +1091,6 @@ mrvl_parse_vlan(const struct rte_flow_item *item, > if (ret) > return ret; > > - if (mask->tpid) { > - rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, > - NULL, "Not supported by classifier\n"); > - return -rte_errno; > - } > - > m = rte_be_to_cpu_16(mask->tci); > if (m & MRVL_VLAN_ID_MASK) { > RTE_LOG(WARNING, PMD, "vlan id mask is ignored\n"); > @@ -1112,6 +1106,27 @@ mrvl_parse_vlan(const struct rte_flow_item *item, > goto out; > } > > + if (flow->pattern & F_TYPE) { > + rte_flow_error_set(error, ENOTSUP, > + RTE_FLOW_ERROR_TYPE_ITEM, item, > + "outer TPID cannot be explicitly matched" > + " when VLAN item is also specified\n"); > + return -rte_errno; > + } > + if (mask->inner_type) { > + struct rte_flow_item_eth spec_eth = { > + .type = spec->inner_type, > + }; > + struct rte_flow_item_eth mask_eth = { > + .type = mask->inner_type, > + }; > + > + RTE_LOG(WARNING, PMD, "inner eth type mask is ignored\n"); > + ret = mrvl_parse_type(spec_eth, mask_eth, flow); > + if (ret) > + goto out; > + } > + > return 0; > out: > rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, > diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c > index bf9609735..515a61325 100644 > --- a/drivers/net/sfc/sfc_flow.c > +++ b/drivers/net/sfc/sfc_flow.c > @@ -352,6 +352,7 @@ sfc_flow_parse_vlan(const struct rte_flow_item *item, > const struct rte_flow_item_vlan *mask = NULL; > const struct rte_flow_item_vlan supp_mask = { > .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX), > + .inner_type = RTE_BE16(0xffff), > }; > > rc = sfc_flow_parse_init(item, > @@ -394,6 +395,32 @@ sfc_flow_parse_vlan(const struct rte_flow_item *item, > return -rte_errno; > } > > + /* > + * If an EtherType was already specified, make sure it is a valid > + * TPID for the current VLAN layer before overwriting it with the > + * specified inner type. > + */ > + if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE && > + efx_spec->efs_ether_type != RTE_BE16(0x8100) && > + efx_spec->efs_ether_type != RTE_BE16(0x88a8)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, item, > + "Unsupported outer TPID"); > + return -rte_errno; > + } > + if (!mask->inner_type) { > + efx_spec->efs_match_flags &= ~EFX_FILTER_MATCH_ETHER_TYPE; > + efx_spec->efs_ether_type = RTE_BE16(0x0000); > + } else if (mask->inner_type == supp_mask.inner_type) { > + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE; > + efx_spec->efs_ether_type = rte_be_to_cpu_16(spec->inner_type); > + } else { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, item, > + "Bad mask for VLAN inner_type"); > + return -rte_errno; > + } > + > return 0; > } > > diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c > index e5eb50fc5..e53eff6ce 100644 > --- a/drivers/net/tap/tap_flow.c > +++ b/drivers/net/tap/tap_flow.c > @@ -270,13 +270,13 @@ static const struct tap_flow_items tap_flow_items[] = { > .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4, > RTE_FLOW_ITEM_TYPE_IPV6), > .mask = &(const struct rte_flow_item_vlan){ > - .tpid = -1, > /* DEI matching is not supported */ > #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN > .tci = 0xffef, > #else > .tci = 0xefff, > #endif > + .inner_type = -1, > }, > .mask_sz = sizeof(struct rte_flow_item_vlan), > .default_mask = &rte_flow_item_vlan_mask, > @@ -578,13 +578,21 @@ tap_flow_create_vlan(const struct rte_flow_item *item, void *data) > /* use default mask if none provided */ > if (!mask) > mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_VLAN].default_mask; > - /* TC does not support tpid masking. Only accept if exact match. */ > - if (mask->tpid && mask->tpid != 0xffff) > + /* check that previous eth type is compatible with VLAN */ > + if (info->eth_type && info->eth_type != RTE_BE16(ETH_P_8021Q)) > return -1; > /* Double-tagging not supported. */ > - if (spec && mask->tpid && spec->tpid != htons(ETH_P_8021Q)) > + if (info->vlan) > return -1; > info->vlan = 1; > + if (mask->inner_type) { > + /* TC does not support partial eth_type masking */ > + if (mask->inner_type != RTE_BE16(0xffff)) > + return -1; > + info->eth_type = spec->inner_type; > + } else { > + info->eth_type = 0; > + } > if (!flow) > return 0; > msg = &flow->msg; > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h > index 1b222ba60..15e383f95 100644 > --- a/lib/librte_ether/rte_flow.h > +++ b/lib/librte_ether/rte_flow.h > @@ -454,11 +454,17 @@ static const struct rte_flow_item_raw rte_flow_item_raw_mask = { > * RTE_FLOW_ITEM_TYPE_ETH > * > * Matches an Ethernet header. > + * > + * The @p type field either stands for "EtherType" or "TPID" when followed > + * by so-called layer 2.5 pattern items such as RTE_FLOW_ITEM_TYPE_VLAN. In > + * the latter case, @p type refers to that of the outer header, with the > + * inner EtherType/TPID provided by the subsequent pattern item. This is the > + * same order as on the wire. > */ > struct rte_flow_item_eth { > struct ether_addr dst; /**< Destination MAC. */ > struct ether_addr src; /**< Source MAC. */ > - rte_be16_t type; /**< EtherType. */ > + rte_be16_t type; /**< EtherType or TPID. */ > }; > > /** Default mask for RTE_FLOW_ITEM_TYPE_ETH. */ > @@ -475,19 +481,20 @@ static const struct rte_flow_item_eth rte_flow_item_eth_mask = { > * > * Matches an 802.1Q/ad VLAN tag. > * > - * This type normally follows either RTE_FLOW_ITEM_TYPE_ETH or > - * RTE_FLOW_ITEM_TYPE_VLAN. > + * The corresponding standard outer EtherType (TPID) values are 0x8100 or > + * 0x88a8 (in case of outer QinQ). It can be overridden by the preceding > + * pattern item. > */ > struct rte_flow_item_vlan { > - rte_be16_t tpid; /**< Tag protocol identifier. */ > rte_be16_t tci; /**< Tag control information. */ > + rte_be16_t inner_type; /**< Inner EtherType or TPID. */ > }; > > /** Default mask for RTE_FLOW_ITEM_TYPE_VLAN. */ > #ifndef __cplusplus > static const struct rte_flow_item_vlan rte_flow_item_vlan_mask = { > - .tpid = RTE_BE16(0x0000), > - .tci = RTE_BE16(0xffff), > + .tci = RTE_BE16(0x0fff), > + .inner_type = RTE_BE16(0x0000), > }; > #endif > > @@ -636,9 +643,11 @@ static const struct rte_flow_item_vxlan rte_flow_item_vxlan_mask = { > * RTE_FLOW_ITEM_TYPE_E_TAG. > * > * Matches a E-tag header. > + * > + * The corresponding standard outer EtherType (TPID) value is 0x893f. > + * It can be overridden by the preceding pattern item. > */ > struct rte_flow_item_e_tag { > - rte_be16_t tpid; /**< Tag protocol identifier (0x893F). */ > /** > * E-Tag control information (E-TCI). > * E-PCP (3b), E-DEI (1b), ingress E-CID base (12b). > @@ -648,6 +657,7 @@ struct rte_flow_item_e_tag { > rte_be16_t rsvd_grp_ecid_b; > uint8_t in_ecid_e; /**< Ingress E-CID ext. */ > uint8_t ecid_e; /**< E-CID ext. */ > + rte_be16_t inner_type; /**< Inner EtherType or TPID. */ > }; > > /** Default mask for RTE_FLOW_ITEM_TYPE_E_TAG. */ > -- > 2.11.0 -- Nélio Laranjeiro 6WIND