From ad5750a7744b864a940a6e9cb6efb730231b5aaf Mon Sep 17 00:00:00 2001 From: Viacheslav Galaktionov Date: Tue, 16 Mar 2021 15:51:44 +0300 Subject: [PATCH] net/sfc: allow PPPoE flow pattern items These items allow the user to avoid having to set the EtherType field in an ETH item to match PPPoE traffic. Using a PPPoED (PPPoE discovery) or PPPoES (PPPoE session) item will lead to EtherType filter being set up with a corresponding value. If an ETH item provides its own EtherType value, it will be checked for correctness. Matching on PPPoE fields is not supported. Signed-off-by: Viacheslav Galaktionov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton --- drivers/net/sfc/sfc_flow.c | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 848669cb8e..0bfd284c9e 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -96,6 +96,7 @@ static sfc_flow_item_parse sfc_flow_parse_udp; static sfc_flow_item_parse sfc_flow_parse_vxlan; static sfc_flow_item_parse sfc_flow_parse_geneve; static sfc_flow_item_parse sfc_flow_parse_nvgre; +static sfc_flow_item_parse sfc_flow_parse_pppoex; typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec, unsigned int filters_count_for_one_val, @@ -1063,6 +1064,63 @@ sfc_flow_parse_nvgre(const struct rte_flow_item *item, return rc; } +/** + * Convert PPPoEx item to EFX filter specification. + * + * @param item[in] + * Item specification. + * Matching on PPPoEx fields is not supported. + * This item can only be used to set or validate the EtherType filter. + * Only zero masks are allowed. + * Ranging is not supported. + * @param efx_spec[in, out] + * EFX filter specification to update. + * @param[out] error + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_parse_pppoex(const struct rte_flow_item *item, + struct sfc_flow_parse_ctx *parse_ctx, + struct rte_flow_error *error) +{ + efx_filter_spec_t *efx_spec = parse_ctx->filter; + const struct rte_flow_item_pppoe *spec = NULL; + const struct rte_flow_item_pppoe *mask = NULL; + const struct rte_flow_item_pppoe supp_mask = {}; + const struct rte_flow_item_pppoe def_mask = {}; + uint16_t ether_type; + int rc; + + rc = sfc_flow_parse_init(item, + (const void **)&spec, + (const void **)&mask, + &supp_mask, + &def_mask, + sizeof(struct rte_flow_item_pppoe), + error); + if (rc != 0) + return rc; + + if (item->type == RTE_FLOW_ITEM_TYPE_PPPOED) + ether_type = RTE_ETHER_TYPE_PPPOE_DISCOVERY; + else + ether_type = RTE_ETHER_TYPE_PPPOE_SESSION; + + if ((efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE) != 0) { + if (efx_spec->efs_ether_type != ether_type) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Invalid EtherType for a PPPoE flow item"); + return -rte_errno; + } + } else { + efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE; + efx_spec->efs_ether_type = ether_type; + } + + return 0; +} + static const struct sfc_flow_item sfc_flow_items[] = { { .type = RTE_FLOW_ITEM_TYPE_VOID, @@ -1085,6 +1143,20 @@ static const struct sfc_flow_item sfc_flow_items[] = { .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_vlan, }, + { + .type = RTE_FLOW_ITEM_TYPE_PPPOED, + .prev_layer = SFC_FLOW_ITEM_L2, + .layer = SFC_FLOW_ITEM_L2, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, + .parse = sfc_flow_parse_pppoex, + }, + { + .type = RTE_FLOW_ITEM_TYPE_PPPOES, + .prev_layer = SFC_FLOW_ITEM_L2, + .layer = SFC_FLOW_ITEM_L2, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, + .parse = sfc_flow_parse_pppoex, + }, { .type = RTE_FLOW_ITEM_TYPE_IPV4, .prev_layer = SFC_FLOW_ITEM_L2, -- 2.20.1