From: Ivan Malov <ivan.malov@oktetlabs.ru>
To: dev@dpdk.org
Cc: Ray Kinsella <mdr@ashroe.eu>,
Ferruh Yigit <ferruh.yigit@intel.com>,
Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,
Andy Moreton <amoreton@xilinx.com>
Subject: [dpdk-dev] [PATCH v4 3/3] net/sfc: support matching on VLAN presence in transfer rules
Date: Mon, 24 May 2021 14:48:33 +0300 [thread overview]
Message-ID: <20210524114833.4056-4-ivan.malov@oktetlabs.ru> (raw)
In-Reply-To: <20210524114833.4056-1-ivan.malov@oktetlabs.ru>
Take into account VLAN presence fields in items ETH and VLAN.
Provided that the item ETH does not match on the EtherType,
the pattern behaviour will be as follows:
- ETH (mask->has_vlan = 0) | IPv4 = match both tagged and untagged;
- ETH (mask->has_vlan = 1) | IPv4 = match as per spec->has_vlan;
- ETH (mask->has_vlan = 0) | VLAN | IPv4 = match only tagged.
Similar logic applies to double tagging.
Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
drivers/net/sfc/sfc_mae.c | 124 ++++++++++++++++++++++++++++++++------
drivers/net/sfc/sfc_mae.h | 19 +++++-
2 files changed, 123 insertions(+), 20 deletions(-)
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index a2c0aa143..33bff275c 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -728,6 +728,7 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
RTE_BE16(RTE_ETHER_TYPE_QINQ2),
RTE_BE16(RTE_ETHER_TYPE_QINQ3),
};
+ bool enforce_tag_presence[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {0};
unsigned int nb_supported_tpids = RTE_DIM(supported_tpids);
unsigned int ethertype_idx;
const uint8_t *valuep;
@@ -753,6 +754,22 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) {
unsigned int tpid_idx;
+ /*
+ * This loop can have only two iterations. On the second one,
+ * drop outer tag presence enforcement bit because the inner
+ * tag presence automatically assumes that for the outer tag.
+ */
+ enforce_tag_presence[0] = B_FALSE;
+
+ if (ethertypes[ethertype_idx].mask == RTE_BE16(0)) {
+ if (pdata->tci_masks[ethertype_idx] == RTE_BE16(0))
+ enforce_tag_presence[ethertype_idx] = B_TRUE;
+
+ /* No match on this field, and no value check. */
+ nb_supported_tpids = 1;
+ continue;
+ }
+
/* Exact match is supported only. */
if (ethertypes[ethertype_idx].mask != RTE_BE16(0xffff)) {
rc = EINVAL;
@@ -812,6 +829,24 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
}
}
+ if (enforce_tag_presence[0] || pdata->has_ovlan_mask) {
+ rc = efx_mae_match_spec_bit_set(ctx->match_spec,
+ fremap[EFX_MAE_FIELD_HAS_OVLAN],
+ enforce_tag_presence[0] ||
+ pdata->has_ovlan_value);
+ if (rc != 0)
+ goto fail;
+ }
+
+ if (enforce_tag_presence[1] || pdata->has_ivlan_mask) {
+ rc = efx_mae_match_spec_bit_set(ctx->match_spec,
+ fremap[EFX_MAE_FIELD_HAS_IVLAN],
+ enforce_tag_presence[1] ||
+ pdata->has_ivlan_value);
+ if (rc != 0)
+ goto fail;
+ }
+
valuep = (const uint8_t *)&pdata->l3_next_proto_value;
maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
rc = efx_mae_match_spec_field_set(ctx->match_spec,
@@ -1154,6 +1189,7 @@ sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth),
&supp_mask, sizeof(supp_mask));
+ supp_mask.has_vlan = 1;
rc = sfc_flow_parse_init(item,
(const void **)&spec, (const void **)&mask,
@@ -1172,14 +1208,23 @@ sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
item_spec = (const struct rte_flow_item_eth *)spec;
item_mask = (const struct rte_flow_item_eth *)mask;
+ /*
+ * Remember various match criteria in the parsing context.
+ * sfc_mae_rule_process_pattern_data() will consider them
+ * altogether when the rest of the items have been parsed.
+ */
ethertypes[0].value = item_spec->type;
ethertypes[0].mask = item_mask->type;
+ if (item_mask->has_vlan) {
+ pdata->has_ovlan_mask = B_TRUE;
+ if (item_spec->has_vlan)
+ pdata->has_ovlan_value = B_TRUE;
+ }
} else {
/*
- * The specification is empty. This is wrong in the case
- * when there are more network patterns in line. Other
- * than that, any Ethernet can match. All of that is
- * checked at the end of parsing.
+ * The specification is empty. The overall pattern
+ * validity will be enforced at the end of parsing.
+ * See sfc_mae_rule_process_pattern_data().
*/
return 0;
}
@@ -1229,6 +1274,16 @@ sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
{
struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+ boolean_t *has_vlan_mp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {
+ &pdata->has_ovlan_mask,
+ &pdata->has_ivlan_mask,
+ };
+ boolean_t *has_vlan_vp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {
+ &pdata->has_ovlan_value,
+ &pdata->has_ivlan_value,
+ };
+ boolean_t *cur_tag_presence_bit_mp;
+ boolean_t *cur_tag_presence_bit_vp;
const struct sfc_mae_field_locator *flocs;
struct rte_flow_item_vlan supp_mask;
const uint8_t *spec = NULL;
@@ -1244,14 +1299,27 @@ sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
"Can't match that many VLAN tags");
}
+ cur_tag_presence_bit_mp = has_vlan_mp_by_nb_tags[pdata->nb_vlan_tags];
+ cur_tag_presence_bit_vp = has_vlan_vp_by_nb_tags[pdata->nb_vlan_tags];
+
+ if (*cur_tag_presence_bit_mp == B_TRUE &&
+ *cur_tag_presence_bit_vp == B_FALSE) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "The previous item enforces no (more) VLAN, "
+ "so the current item (VLAN) must not exist");
+ }
+
nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS;
flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs;
- /* If parsing fails, this can remain incremented. */
- ++pdata->nb_vlan_tags;
-
sfc_mae_item_build_supp_mask(flocs, nb_flocs,
&supp_mask, sizeof(supp_mask));
+ /*
+ * This only means that the field is supported by the driver and libefx.
+ * Support on NIC level will be checked when all items have been parsed.
+ */
+ supp_mask.has_more_vlan = 1;
rc = sfc_flow_parse_init(item,
(const void **)&spec, (const void **)&mask,
@@ -1262,26 +1330,44 @@ sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
return rc;
if (spec != NULL) {
- struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
+ struct sfc_mae_ethertype *et = pdata->ethertypes;
const struct rte_flow_item_vlan *item_spec;
const struct rte_flow_item_vlan *item_mask;
item_spec = (const struct rte_flow_item_vlan *)spec;
item_mask = (const struct rte_flow_item_vlan *)mask;
- ethertypes[pdata->nb_vlan_tags].value = item_spec->inner_type;
- ethertypes[pdata->nb_vlan_tags].mask = item_mask->inner_type;
- } else {
/*
- * The specification is empty. This is wrong in the case
- * when there are more network patterns in line. Other
- * than that, any Ethernet can match. All of that is
- * checked at the end of parsing.
+ * Remember various match criteria in the parsing context.
+ * sfc_mae_rule_process_pattern_data() will consider them
+ * altogether when the rest of the items have been parsed.
*/
- return 0;
+ et[pdata->nb_vlan_tags + 1].value = item_spec->inner_type;
+ et[pdata->nb_vlan_tags + 1].mask = item_mask->inner_type;
+ pdata->tci_masks[pdata->nb_vlan_tags] = item_mask->tci;
+ if (item_mask->has_more_vlan) {
+ if (pdata->nb_vlan_tags ==
+ SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Can't use 'has_more_vlan' in "
+ "the second item VLAN");
+ }
+ pdata->has_ivlan_mask = B_TRUE;
+ if (item_spec->has_more_vlan)
+ pdata->has_ivlan_value = B_TRUE;
+ }
+
+ /* Convert TCI to MAE representation right now. */
+ rc = sfc_mae_parse_item(flocs, nb_flocs, spec, mask,
+ ctx_mae, error);
+ if (rc != 0)
+ return rc;
}
- return sfc_mae_parse_item(flocs, nb_flocs, spec, mask, ctx_mae, error);
+ ++(pdata->nb_vlan_tags);
+
+ return 0;
}
static const struct sfc_mae_field_locator flocs_ipv4[] = {
@@ -1612,6 +1698,8 @@ static const efx_mae_field_id_t field_ids_no_remap[] = {
FIELD_ID_NO_REMAP(L4_SPORT_BE),
FIELD_ID_NO_REMAP(L4_DPORT_BE),
FIELD_ID_NO_REMAP(TCP_FLAGS_BE),
+ FIELD_ID_NO_REMAP(HAS_OVLAN),
+ FIELD_ID_NO_REMAP(HAS_IVLAN),
#undef FIELD_ID_NO_REMAP
};
@@ -1642,6 +1730,8 @@ static const efx_mae_field_id_t field_ids_remap_to_encap[] = {
FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE),
FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE),
FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE),
+ FIELD_ID_REMAP_TO_ENCAP(HAS_OVLAN),
+ FIELD_ID_REMAP_TO_ENCAP(HAS_IVLAN),
#undef FIELD_ID_REMAP_TO_ENCAP
};
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 9740e54e4..0241fe33c 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -130,12 +130,14 @@ struct sfc_mae_pattern_data {
*
* - If an item ETH is followed by a single item VLAN,
* the former must have "type" set to one of supported
- * TPID values (0x8100, 0x88a8, 0x9100, 0x9200, 0x9300).
+ * TPID values (0x8100, 0x88a8, 0x9100, 0x9200, 0x9300),
+ * or 0x0000/0x0000.
*
* - If an item ETH is followed by two items VLAN, the
* item ETH must have "type" set to one of supported TPID
- * values (0x88a8, 0x9100, 0x9200, 0x9300), and the outermost
- * VLAN item must have "inner_type" set to TPID value 0x8100.
+ * values (0x88a8, 0x9100, 0x9200, 0x9300), or 0x0000/0x0000,
+ * and the outermost VLAN item must have "inner_type" set
+ * to TPID value 0x8100, or 0x0000/0x0000
*
* - If a L2 item is followed by a L3 one, the former must
* indicate "type" ("inner_type") which corresponds to
@@ -156,6 +158,9 @@ struct sfc_mae_pattern_data {
* VLAN (L3 EtherType) --> ETHER_TYPE_BE
*/
struct sfc_mae_ethertype ethertypes[SFC_MAE_L2_MAX_NITEMS];
+
+ rte_be16_t tci_masks[SFC_MAE_MATCH_VLAN_MAX_NTAGS];
+
unsigned int nb_vlan_tags;
/**
@@ -191,6 +196,14 @@ struct sfc_mae_pattern_data {
*/
uint8_t l3_next_proto_restriction_value;
uint8_t l3_next_proto_restriction_mask;
+
+ /* Projected state of EFX_MAE_FIELD_HAS_OVLAN match bit */
+ bool has_ovlan_value;
+ bool has_ovlan_mask;
+
+ /* Projected state of EFX_MAE_FIELD_HAS_IVLAN match bit */
+ bool has_ivlan_value;
+ bool has_ivlan_mask;
};
struct sfc_mae_parse_ctx {
--
2.20.1
next prev parent reply other threads:[~2021-05-24 11:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-28 9:49 [dpdk-dev] [PATCH 1/3] common/sfc_efx/base: update MCDI headers Ivan Malov
2021-04-28 9:49 ` [dpdk-dev] [PATCH 2/3] common/sfc_efx/base: add MAE VLAN presence match bits Ivan Malov
2021-04-28 10:08 ` Kinsella, Ray
2021-04-28 11:09 ` Ivan Malov
2021-04-30 14:49 ` Kinsella, Ray
2021-04-28 9:49 ` [dpdk-dev] [PATCH 3/3] net/sfc: support matching on VLAN presence in transfer rules Ivan Malov
2021-04-30 15:56 ` [dpdk-dev] [PATCH 1/3] common/sfc_efx/base: update MCDI headers Ferruh Yigit
2021-04-30 17:05 ` Ivan Malov
2021-05-04 7:50 ` Ferruh Yigit
2021-05-04 8:15 ` Andrew Rybchenko
2021-05-22 19:32 ` [dpdk-dev] [PATCH v2 0/3] Match On VLAN Presence In Transfer Flows Ivan Malov
2021-05-22 19:32 ` [dpdk-dev] [PATCH v2 1/3] common/sfc_efx/base: update MCDI headers Ivan Malov
2021-05-22 19:32 ` [dpdk-dev] [PATCH v2 2/3] common/sfc_efx/base: add MAE VLAN presence match bits Ivan Malov
2021-05-22 19:32 ` [dpdk-dev] [PATCH v2 3/3] net/sfc: support matching on VLAN presence in transfer rules Ivan Malov
2021-05-24 11:18 ` [dpdk-dev] [PATCH v3 0/3] Match On VLAN Presence In Transfer Flows Ivan Malov
2021-05-24 11:18 ` [dpdk-dev] [PATCH v3 1/3] common/sfc_efx/base: update MCDI headers Ivan Malov
2021-05-24 11:18 ` [dpdk-dev] [PATCH v3 2/3] common/sfc_efx/base: add MAE VLAN presence match bits Ivan Malov
2021-05-24 11:18 ` [dpdk-dev] [PATCH v3 3/3] net/sfc: support matching on VLAN presence in transfer rules Ivan Malov
2021-05-24 11:48 ` [dpdk-dev] [PATCH v4 0/3] Match On VLAN Presence In Transfer Flows Ivan Malov
2021-05-24 11:48 ` [dpdk-dev] [PATCH v4 1/3] common/sfc_efx/base: update MCDI headers Ivan Malov
2021-05-24 11:48 ` [dpdk-dev] [PATCH v4 2/3] common/sfc_efx/base: add MAE VLAN presence match bits Ivan Malov
2021-05-24 11:48 ` Ivan Malov [this message]
2021-07-07 10:00 ` [dpdk-dev] [PATCH v4 0/3] Match On VLAN Presence In Transfer Flows David Marchand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210524114833.4056-4-ivan.malov@oktetlabs.ru \
--to=ivan.malov@oktetlabs.ru \
--cc=amoreton@xilinx.com \
--cc=andrew.rybchenko@oktetlabs.ru \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=mdr@ashroe.eu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).