X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_flow.c;h=c8e6fb8bce2284cb4f7cf257392d002a6c01c0ba;hb=d789705873d47d70a3ba0a6a4dfb83fb629d3464;hp=ed91c3cefe833df0006c7d389d57b11e31ce6e78;hpb=5b2b9236aacc5d4fcc4e950177ce5f4d32780c46;p=dpdk.git diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index ed91c3cefe..c8e6fb8bce 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2017-2018 Solarflare Communications Inc. - * All rights reserved. + * Copyright(c) 2019-2020 Xilinx, Inc. + * Copyright(c) 2017-2019 Solarflare Communications Inc. * * This software was jointly developed between OKTET Labs (under contract * for Solarflare) and Solarflare Communications, Inc. @@ -26,12 +26,18 @@ struct sfc_flow_ops_by_spec { sfc_flow_parse_cb_t *parse; + sfc_flow_insert_cb_t *insert; + sfc_flow_remove_cb_t *remove; }; static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter; +static sfc_flow_insert_cb_t sfc_flow_filter_insert; +static sfc_flow_remove_cb_t sfc_flow_filter_remove; static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = { .parse = sfc_flow_parse_rte_to_filter, + .insert = sfc_flow_filter_insert, + .remove = sfc_flow_filter_remove, }; static const struct sfc_flow_ops_by_spec * @@ -63,25 +69,6 @@ sfc_flow_get_ops_by_spec(struct rte_flow *flow) * of such a field. */ -enum sfc_flow_item_layers { - SFC_FLOW_ITEM_ANY_LAYER, - SFC_FLOW_ITEM_START_LAYER, - SFC_FLOW_ITEM_L2, - SFC_FLOW_ITEM_L3, - SFC_FLOW_ITEM_L4, -}; - -typedef int (sfc_flow_item_parse)(const struct rte_flow_item *item, - efx_filter_spec_t *spec, - struct rte_flow_error *error); - -struct sfc_flow_item { - enum rte_flow_item_type type; /* Type of item */ - enum sfc_flow_item_layers layer; /* Layer of item */ - enum sfc_flow_item_layers prev_layer; /* Previous layer of item */ - sfc_flow_item_parse *parse; /* Parsing function */ -}; - static sfc_flow_item_parse sfc_flow_parse_void; static sfc_flow_item_parse sfc_flow_parse_eth; static sfc_flow_item_parse sfc_flow_parse_vlan; @@ -138,7 +125,7 @@ sfc_flow_is_zero(const uint8_t *buf, unsigned int size) /* * Validate item and prepare structures spec and mask for parsing */ -static int +int sfc_flow_parse_init(const struct rte_flow_item *item, const void **spec_ptr, const void **mask_ptr, @@ -237,7 +224,7 @@ exit: static int sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item, - __rte_unused efx_filter_spec_t *efx_spec, + __rte_unused struct sfc_flow_parse_ctx *parse_ctx, __rte_unused struct rte_flow_error *error) { return 0; @@ -259,10 +246,11 @@ sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item, */ static int sfc_flow_parse_eth(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_eth *spec = NULL; const struct rte_flow_item_eth *mask = NULL; const struct rte_flow_item_eth supp_mask = { @@ -371,11 +359,12 @@ fail_bad_mask: */ static int sfc_flow_parse_vlan(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; uint16_t vid; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_vlan *spec = NULL; const struct rte_flow_item_vlan *mask = NULL; const struct rte_flow_item_vlan supp_mask = { @@ -457,10 +446,11 @@ sfc_flow_parse_vlan(const struct rte_flow_item *item, */ static int sfc_flow_parse_ipv4(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_ipv4 *spec = NULL; const struct rte_flow_item_ipv4 *mask = NULL; const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4); @@ -547,10 +537,11 @@ fail_bad_mask: */ static int sfc_flow_parse_ipv6(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_ipv6 *spec = NULL; const struct rte_flow_item_ipv6 *mask = NULL; const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6); @@ -655,10 +646,11 @@ fail_bad_mask: */ static int sfc_flow_parse_tcp(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_tcp *spec = NULL; const struct rte_flow_item_tcp *mask = NULL; const struct rte_flow_item_tcp supp_mask = { @@ -736,10 +728,11 @@ fail_bad_mask: */ static int sfc_flow_parse_udp(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_udp *spec = NULL; const struct rte_flow_item_udp *mask = NULL; const struct rte_flow_item_udp supp_mask = { @@ -894,10 +887,11 @@ sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec, */ static int sfc_flow_parse_vxlan(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_vxlan *spec = NULL; const struct rte_flow_item_vxlan *mask = NULL; const struct rte_flow_item_vxlan supp_mask = { @@ -946,10 +940,11 @@ sfc_flow_parse_vxlan(const struct rte_flow_item *item, */ static int sfc_flow_parse_geneve(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_geneve *spec = NULL; const struct rte_flow_item_geneve *mask = NULL; const struct rte_flow_item_geneve supp_mask = { @@ -1013,10 +1008,11 @@ sfc_flow_parse_geneve(const struct rte_flow_item *item, */ static int sfc_flow_parse_nvgre(const struct rte_flow_item *item, - efx_filter_spec_t *efx_spec, + struct sfc_flow_parse_ctx *parse_ctx, struct rte_flow_error *error) { int rc; + efx_filter_spec_t *efx_spec = parse_ctx->filter; const struct rte_flow_item_nvgre *spec = NULL; const struct rte_flow_item_nvgre *mask = NULL; const struct rte_flow_item_nvgre supp_mask = { @@ -1055,60 +1051,70 @@ static const struct sfc_flow_item sfc_flow_items[] = { .type = RTE_FLOW_ITEM_TYPE_VOID, .prev_layer = SFC_FLOW_ITEM_ANY_LAYER, .layer = SFC_FLOW_ITEM_ANY_LAYER, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_void, }, { .type = RTE_FLOW_ITEM_TYPE_ETH, .prev_layer = SFC_FLOW_ITEM_START_LAYER, .layer = SFC_FLOW_ITEM_L2, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_eth, }, { .type = RTE_FLOW_ITEM_TYPE_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_IPV4, .prev_layer = SFC_FLOW_ITEM_L2, .layer = SFC_FLOW_ITEM_L3, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_ipv4, }, { .type = RTE_FLOW_ITEM_TYPE_IPV6, .prev_layer = SFC_FLOW_ITEM_L2, .layer = SFC_FLOW_ITEM_L3, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_ipv6, }, { .type = RTE_FLOW_ITEM_TYPE_TCP, .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_L4, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_tcp, }, { .type = RTE_FLOW_ITEM_TYPE_UDP, .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_L4, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_udp, }, { .type = RTE_FLOW_ITEM_TYPE_VXLAN, .prev_layer = SFC_FLOW_ITEM_L4, .layer = SFC_FLOW_ITEM_START_LAYER, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_vxlan, }, { .type = RTE_FLOW_ITEM_TYPE_GENEVE, .prev_layer = SFC_FLOW_ITEM_L4, .layer = SFC_FLOW_ITEM_START_LAYER, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_geneve, }, { .type = RTE_FLOW_ITEM_TYPE_NVGRE, .prev_layer = SFC_FLOW_ITEM_L3, .layer = SFC_FLOW_ITEM_START_LAYER, + .ctx_type = SFC_FLOW_PARSE_CTX_FILTER, .parse = sfc_flow_parse_nvgre, }, }; @@ -1158,6 +1164,7 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr, spec->type = SFC_FLOW_SPEC_FILTER; spec_filter->template.efs_flags |= EFX_FILTER_FLAG_RX; spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL; } else { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr, @@ -1170,28 +1177,30 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr, /* Get item from array sfc_flow_items */ static const struct sfc_flow_item * -sfc_flow_get_item(enum rte_flow_item_type type) +sfc_flow_get_item(const struct sfc_flow_item *items, + unsigned int nb_items, + enum rte_flow_item_type type) { unsigned int i; - for (i = 0; i < RTE_DIM(sfc_flow_items); i++) - if (sfc_flow_items[i].type == type) - return &sfc_flow_items[i]; + for (i = 0; i < nb_items; i++) + if (items[i].type == type) + return &items[i]; return NULL; } -static int -sfc_flow_parse_pattern(const struct rte_flow_item pattern[], - struct rte_flow *flow, +int +sfc_flow_parse_pattern(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, struct rte_flow_error *error) { int rc; unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER; boolean_t is_ifrm = B_FALSE; const struct sfc_flow_item *item; - struct sfc_flow_spec *spec = &flow->spec; - struct sfc_flow_spec_filter *spec_filter = &spec->filter; if (pattern == NULL) { rte_flow_error_set(error, EINVAL, @@ -1201,7 +1210,8 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], } for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { - item = sfc_flow_get_item(pattern->type); + item = sfc_flow_get_item(flow_items, nb_flow_items, + pattern->type); if (item == NULL) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, pattern, @@ -1256,7 +1266,14 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; } - rc = item->parse(pattern, &spec_filter->template, error); + if (parse_ctx->type != item->ctx_type) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, pattern, + "Parse context type mismatch"); + return -rte_errno; + } + + rc = item->parse(pattern, parse_ctx, error); if (rc != 0) return rc; @@ -2312,9 +2329,16 @@ sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); + struct sfc_flow_spec *spec = &flow->spec; + struct sfc_flow_spec_filter *spec_filter = &spec->filter; + struct sfc_flow_parse_ctx ctx; int rc; - rc = sfc_flow_parse_pattern(pattern, flow, error); + 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), + pattern, &ctx, error); if (rc != 0) goto fail_bad_value; @@ -2379,6 +2403,54 @@ sfc_flow_free(__rte_unused struct sfc_adapter *sa, struct rte_flow *flow) rte_free(flow); } +static int +sfc_flow_insert(struct sfc_adapter *sa, struct rte_flow *flow, + struct rte_flow_error *error) +{ + const struct sfc_flow_ops_by_spec *ops; + int rc; + + ops = sfc_flow_get_ops_by_spec(flow); + if (ops == NULL || ops->insert == NULL) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "No backend to handle this flow"); + return rte_errno; + } + + rc = ops->insert(sa, flow); + if (rc != 0) { + rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Failed to insert the flow rule"); + } + + return rc; +} + +static int +sfc_flow_remove(struct sfc_adapter *sa, struct rte_flow *flow, + struct rte_flow_error *error) +{ + const struct sfc_flow_ops_by_spec *ops; + int rc; + + ops = sfc_flow_get_ops_by_spec(flow); + if (ops == NULL || ops->remove == NULL) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "No backend to handle this flow"); + return rte_errno; + } + + rc = ops->remove(sa, flow); + if (rc != 0) { + rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "Failed to remove the flow rule"); + } + + return rc; +} + static int sfc_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, @@ -2425,20 +2497,16 @@ sfc_flow_create(struct rte_eth_dev *dev, TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries); if (sa->state == SFC_ADAPTER_STARTED) { - rc = sfc_flow_filter_insert(sa, flow); - if (rc != 0) { - rte_flow_error_set(error, rc, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "Failed to insert filter"); - goto fail_filter_insert; - } + rc = sfc_flow_insert(sa, flow, error); + if (rc != 0) + goto fail_flow_insert; } sfc_adapter_unlock(sa); return flow; -fail_filter_insert: +fail_flow_insert: TAILQ_REMOVE(&sa->flow_list, flow, entries); fail_bad_value: @@ -2449,29 +2517,6 @@ fail_no_mem: return NULL; } -static int -sfc_flow_remove(struct sfc_adapter *sa, - struct rte_flow *flow, - struct rte_flow_error *error) -{ - int rc = 0; - - SFC_ASSERT(sfc_adapter_is_locked(sa)); - - if (sa->state == SFC_ADAPTER_STARTED) { - rc = sfc_flow_filter_remove(sa, flow); - if (rc != 0) - rte_flow_error_set(error, rc, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "Failed to destroy flow rule"); - } - - TAILQ_REMOVE(&sa->flow_list, flow, entries); - sfc_flow_free(sa, flow); - - return rc; -} - static int sfc_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, @@ -2494,7 +2539,11 @@ sfc_flow_destroy(struct rte_eth_dev *dev, goto fail_bad_value; } - rc = sfc_flow_remove(sa, flow, error); + if (sa->state == SFC_ADAPTER_STARTED) + rc = sfc_flow_remove(sa, flow, error); + + TAILQ_REMOVE(&sa->flow_list, flow, entries); + sfc_flow_free(sa, flow); fail_bad_value: sfc_adapter_unlock(sa); @@ -2508,15 +2557,21 @@ sfc_flow_flush(struct rte_eth_dev *dev, { struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); struct rte_flow *flow; - int rc = 0; int ret = 0; sfc_adapter_lock(sa); while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) { - rc = sfc_flow_remove(sa, flow, error); - if (rc != 0) - ret = rc; + if (sa->state == SFC_ADAPTER_STARTED) { + int rc; + + rc = sfc_flow_remove(sa, flow, error); + if (rc != 0) + ret = rc; + } + + TAILQ_REMOVE(&sa->flow_list, flow, entries); + sfc_flow_free(sa, flow); } sfc_adapter_unlock(sa); @@ -2583,7 +2638,7 @@ sfc_flow_stop(struct sfc_adapter *sa) SFC_ASSERT(sfc_adapter_is_locked(sa)); TAILQ_FOREACH(flow, &sa->flow_list, entries) - sfc_flow_filter_remove(sa, flow); + sfc_flow_remove(sa, flow, NULL); } int @@ -2597,7 +2652,7 @@ sfc_flow_start(struct sfc_adapter *sa) SFC_ASSERT(sfc_adapter_is_locked(sa)); TAILQ_FOREACH(flow, &sa->flow_list, entries) { - rc = sfc_flow_filter_insert(sa, flow); + rc = sfc_flow_insert(sa, flow, NULL); if (rc != 0) goto fail_bad_flow; }