From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 734DFA0547; Mon, 24 May 2021 13:19:36 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AD2DE41135; Mon, 24 May 2021 13:19:14 +0200 (CEST) Received: from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113]) by mails.dpdk.org (Postfix) with ESMTP id 49D4E41128 for ; Mon, 24 May 2021 13:19:13 +0200 (CEST) Received: from localhost.localdomain (unknown [5.144.120.251]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by shelob.oktetlabs.ru (Postfix) with ESMTPSA id 044F57F5F1; Mon, 24 May 2021 14:19:13 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru 044F57F5F1 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=oktetlabs.ru; s=default; t=1621855153; bh=nulN7ys9bExBpYf3RVAMl5Wa5tKWVHVfaPFDv2UKki4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=wEF9yhm276YR8wH0m963KNaCILg9AfA6DI7MHS1M6Uy24EXoZ/1oGwjNxELPNz4sX Xj6rFU8FJabwzeuFvtB4MTYMpOW66FEFU6U33ppQVQtPHr6r6yHfr9PYzySxoT/NvU PxQpFn8+LQnoToJbIZdhuu7qcOxEcxYUhNtVcmSA= From: Ivan Malov To: dev@dpdk.org Cc: Ray Kinsella , Ferruh Yigit , Andrew Rybchenko , Andy Moreton Date: Mon, 24 May 2021 14:18:44 +0300 Message-Id: <20210524111844.2145-4-ivan.malov@oktetlabs.ru> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210428094926.22185-1-ivan.malov@oktetlabs.ru> References: <20210428094926.22185-1-ivan.malov@oktetlabs.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v3 3/3] net/sfc: support matching on VLAN presence in transfer rules X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 Reviewed-by: Andrew Rybchenko Reviewed-by: Andy Moreton --- 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