X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_flow.c;h=4f5993a68d23b19d13303b8b8d765b3e4fc40186;hb=6065f4cdc31ba83e41688691b61f025c03edb1c6;hp=ab1d2cc595d0c8e835ecd87b9a885644e675410b;hpb=df96fd0d73955bdc7ca3909e772ff2ad903249c6;p=dpdk.git diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index ab1d2cc595..4f5993a68d 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2019-2020 Xilinx, Inc. + * Copyright(c) 2019-2021 Xilinx, Inc. * Copyright(c) 2017-2019 Solarflare Communications Inc. * * This software was jointly developed between OKTET Labs (under contract @@ -24,6 +24,7 @@ #include "sfc_flow.h" #include "sfc_log.h" #include "sfc_dp_rx.h" +#include "sfc_mae_counter.h" struct sfc_flow_ops_by_spec { sfc_flow_parse_cb_t *parse; @@ -31,6 +32,7 @@ struct sfc_flow_ops_by_spec { sfc_flow_cleanup_cb_t *cleanup; sfc_flow_insert_cb_t *insert; sfc_flow_remove_cb_t *remove; + sfc_flow_query_cb_t *query; }; static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter; @@ -44,6 +46,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = { .cleanup = NULL, .insert = sfc_flow_filter_insert, .remove = sfc_flow_filter_remove, + .query = NULL, }; static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = { @@ -52,6 +55,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = { .cleanup = sfc_mae_flow_cleanup, .insert = sfc_mae_flow_insert, .remove = sfc_mae_flow_remove, + .query = sfc_mae_flow_query, }; static const struct sfc_flow_ops_by_spec * @@ -96,6 +100,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,9 +1068,67 @@ 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, + .name = "VOID", .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, .layer = SFC_FLOW_ITEM_ANY_LAYER, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1073,6 +1136,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_ETH, + .name = "ETH", .prev_layer = SFC_FLOW_ITEM_START_LAYER, .layer = SFC_FLOW_ITEM_L2, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1080,13 +1144,31 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_VLAN, + .name = "VLAN", .prev_layer = SFC_FLOW_ITEM_L2, .layer = SFC_FLOW_ITEM_L2, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_vlan, }, + { + .type = RTE_FLOW_ITEM_TYPE_PPPOED, + .name = "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, + .name = "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, + .name = "IPV4", .prev_layer = SFC_FLOW_ITEM_L2, .layer = SFC_FLOW_ITEM_L3, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1094,6 +1176,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_IPV6, + .name = "IPV6", .prev_layer = SFC_FLOW_ITEM_L2, .layer = SFC_FLOW_ITEM_L3, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1101,6 +1184,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_TCP, + .name = "TCP", .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_L4, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1108,6 +1192,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_UDP, + .name = "UDP", .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_L4, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1115,6 +1200,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_VXLAN, + .name = "VXLAN", .prev_layer = SFC_FLOW_ITEM_L4, .layer = SFC_FLOW_ITEM_START_LAYER, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1122,6 +1208,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_GENEVE, + .name = "GENEVE", .prev_layer = SFC_FLOW_ITEM_L4, .layer = SFC_FLOW_ITEM_START_LAYER, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1129,6 +1216,7 @@ static const struct sfc_flow_item sfc_flow_items[] = { }, { .type = RTE_FLOW_ITEM_TYPE_NVGRE, + .name = "NVGRE", .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_START_LAYER, .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, @@ -1224,7 +1312,8 @@ sfc_flow_get_item(const struct sfc_flow_item *items, } int -sfc_flow_parse_pattern(const struct sfc_flow_item *flow_items, +sfc_flow_parse_pattern(struct sfc_adapter *sa, + const struct sfc_flow_item *flow_items, unsigned int nb_flow_items, const struct rte_flow_item pattern[], struct sfc_flow_parse_ctx *parse_ctx, @@ -1308,8 +1397,11 @@ sfc_flow_parse_pattern(const struct sfc_flow_item *flow_items, } rc = item->parse(pattern, parse_ctx, error); - if (rc != 0) + if (rc != 0) { + sfc_err(sa, "failed to parse item %s: %s", + item->name, strerror(-rc)); return rc; + } if (item->layer != SFC_FLOW_ITEM_ANY_LAYER) prev_layer = item->layer; @@ -1328,10 +1420,10 @@ sfc_flow_parse_queue(struct sfc_adapter *sa, struct sfc_rxq *rxq; struct sfc_rxq_info *rxq_info; - if (queue->index >= sfc_sa2shared(sa)->rxq_count) + if (queue->index >= sfc_sa2shared(sa)->ethdev_rxq_count) return -EINVAL; - rxq = &sa->rxq_ctrl[queue->index]; + rxq = sfc_rxq_ctrl_by_ethdev_qid(sa, queue->index); spec_filter->template.efs_dmaq_id = (uint16_t)rxq->hw_index; rxq_info = &sfc_sa2shared(sa)->rxq_info[queue->index]; @@ -1348,7 +1440,7 @@ sfc_flow_parse_rss(struct sfc_adapter *sa, { struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); struct sfc_rss *rss = &sas->rss; - unsigned int rxq_sw_index; + sfc_ethdev_qid_t ethdev_qid; struct sfc_rxq *rxq; unsigned int rxq_hw_index_min; unsigned int rxq_hw_index_max; @@ -1362,18 +1454,19 @@ sfc_flow_parse_rss(struct sfc_adapter *sa, if (action_rss->queue_num == 0) return -EINVAL; - rxq_sw_index = sfc_sa2shared(sa)->rxq_count - 1; - rxq = &sa->rxq_ctrl[rxq_sw_index]; + ethdev_qid = sfc_sa2shared(sa)->ethdev_rxq_count - 1; + rxq = sfc_rxq_ctrl_by_ethdev_qid(sa, ethdev_qid); rxq_hw_index_min = rxq->hw_index; rxq_hw_index_max = 0; for (i = 0; i < action_rss->queue_num; ++i) { - rxq_sw_index = action_rss->queue[i]; + ethdev_qid = action_rss->queue[i]; - if (rxq_sw_index >= sfc_sa2shared(sa)->rxq_count) + if ((unsigned int)ethdev_qid >= + sfc_sa2shared(sa)->ethdev_rxq_count) return -EINVAL; - rxq = &sa->rxq_ctrl[rxq_sw_index]; + rxq = sfc_rxq_ctrl_by_ethdev_qid(sa, ethdev_qid); if (rxq->hw_index < rxq_hw_index_min) rxq_hw_index_min = rxq->hw_index; @@ -1437,9 +1530,10 @@ sfc_flow_parse_rss(struct sfc_adapter *sa, for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) { unsigned int nb_queues = action_rss->queue_num; - unsigned int rxq_sw_index = action_rss->queue[i % nb_queues]; - struct sfc_rxq *rxq = &sa->rxq_ctrl[rxq_sw_index]; + struct sfc_rxq *rxq; + ethdev_qid = action_rss->queue[i % nb_queues]; + rxq = sfc_rxq_ctrl_by_ethdev_qid(sa, ethdev_qid); sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min; } @@ -2405,7 +2499,7 @@ sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev, ctx.type = SFC_FLOW_PARSE_CTX_FILTER; ctx.filter = &spec_filter->template; - rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items), + rc = sfc_flow_parse_pattern(sa, sfc_flow_items, RTE_DIM(sfc_flow_items), pattern, &ctx, error); if (rc != 0) goto fail_bad_value; @@ -2440,8 +2534,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev, if (rc != 0) return rc; - rc = sfc_mae_rule_parse_actions(sa, actions, &spec_mae->action_set, - error); + rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error); if (rc != 0) return rc; @@ -2714,6 +2807,49 @@ sfc_flow_flush(struct rte_eth_dev *dev, return -ret; } +static int +sfc_flow_query(struct rte_eth_dev *dev, + struct rte_flow *flow, + const struct rte_flow_action *action, + void *data, + struct rte_flow_error *error) +{ + struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); + const struct sfc_flow_ops_by_spec *ops; + int ret; + + sfc_adapter_lock(sa); + + ops = sfc_flow_get_ops_by_spec(flow); + if (ops == NULL || ops->query == NULL) { + ret = rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "No backend to handle this flow"); + goto fail_no_backend; + } + + if (sa->state != SFC_ADAPTER_STARTED) { + ret = rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Can't query the flow: the adapter is not started"); + goto fail_not_started; + } + + ret = ops->query(dev, flow, action, data, error); + if (ret != 0) + goto fail_query; + + sfc_adapter_unlock(sa); + + return 0; + +fail_query: +fail_not_started: +fail_no_backend: + sfc_adapter_unlock(sa); + return ret; +} + static int sfc_flow_isolate(struct rte_eth_dev *dev, int enable, struct rte_flow_error *error) @@ -2740,7 +2876,7 @@ const struct rte_flow_ops sfc_flow_ops = { .create = sfc_flow_create, .destroy = sfc_flow_destroy, .flush = sfc_flow_flush, - .query = NULL, + .query = sfc_flow_query, .isolate = sfc_flow_isolate, }; @@ -2781,6 +2917,12 @@ sfc_flow_stop(struct sfc_adapter *sa) efx_rx_scale_context_free(sa->nic, rss->dummy_rss_context); rss->dummy_rss_context = EFX_RSS_CONTEXT_DEFAULT; } + + /* + * MAE counter service is not stopped on flow rule remove to avoid + * extra work. Make sure that it is stopped here. + */ + sfc_mae_counter_stop(sa); } int