From patchwork Tue Mar 6 15:24:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Rybchenko X-Patchwork-Id: 35696 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3F5DA5F69; Tue, 6 Mar 2018 16:27:27 +0100 (CET) Received: from dispatch1-us1.ppe-hosted.com (dispatch1-us1.ppe-hosted.com [148.163.129.52]) by dpdk.org (Postfix) with ESMTP id 0E7375F2C for ; Tue, 6 Mar 2018 16:27:26 +0100 (CET) X-Virus-Scanned: Proofpoint Essentials engine Received: from webmail.solarflare.com (webmail.solarflare.com [12.187.104.26]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1-us4.ppe-hosted.com (Proofpoint Essentials ESMTP Server) with ESMTPS id B75BD4C008B; Tue, 6 Mar 2018 15:27:24 +0000 (UTC) Received: from sfocexch01r.SolarFlarecom.com (10.20.40.34) by ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id 15.0.1044.25; Tue, 6 Mar 2018 07:27:22 -0800 Received: from ocex03.SolarFlarecom.com (10.20.40.36) by sfocexch01r.SolarFlarecom.com (10.20.40.34) with Microsoft SMTP Server (TLS) id 15.0.1044.25; Tue, 6 Mar 2018 07:27:12 -0800 Received: from opal.uk.solarflarecom.com (10.17.10.1) by ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id 15.0.1044.25 via Frontend Transport; Tue, 6 Mar 2018 07:27:11 -0800 Received: from uklogin.uk.solarflarecom.com (uklogin.uk.solarflarecom.com [10.17.10.10]) by opal.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id w26FRA6F021707; Tue, 6 Mar 2018 15:27:10 GMT Received: from uklogin.uk.solarflarecom.com (localhost.localdomain [127.0.0.1]) by uklogin.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id w26FR9BL000659; Tue, 6 Mar 2018 15:27:10 GMT From: Andrew Rybchenko To: CC: Roman Zhukov Date: Tue, 6 Mar 2018 15:24:54 +0000 Message-ID: <1520349899-31810-10-git-send-email-arybchenko@solarflare.com> X-Mailer: git-send-email 1.8.2.3 In-Reply-To: <1520349899-31810-1-git-send-email-arybchenko@solarflare.com> References: <1519735526-2259-1-git-send-email-arybchenko@solarflare.com> <1520349899-31810-1-git-send-email-arybchenko@solarflare.com> MIME-Version: 1.0 X-MDID: 1520350045-2B6ubrOl5mLh Subject: [dpdk-dev] [PATCH v2 09/14] net/sfc: add infrastructure to make many filters from flow X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 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" From: Roman Zhukov Not all flow rules can be expressed in one hardware filter, so some flow rules have to be expressed in terms of multiple hardware filters. This patch provides a means to produce a filter spec template from the flow rule which then can be used to produce a set of fully elaborated specs to be inserted. Signed-off-by: Roman Zhukov Signed-off-by: Andrew Rybchenko Reviewed-by: Ivan Malov --- drivers/net/sfc/sfc_flow.c | 118 ++++++++++++++++++++++++++++++++++++--------- drivers/net/sfc/sfc_flow.h | 19 +++++++- 2 files changed, 114 insertions(+), 23 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index c942a36..a432936 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -25,10 +25,13 @@ /* * At now flow API is implemented in such a manner that each - * flow rule is converted to a hardware filter. + * flow rule is converted to one or more hardware filters. * All elements of flow rule (attributes, pattern items, actions) * correspond to one or more fields in the efx_filter_spec_s structure * that is responsible for the hardware filter. + * If some required field is unset in the flow rule, then a handful + * of filter copies will be created to cover all possible values + * of such a field. */ enum sfc_flow_item_layers { @@ -1095,8 +1098,8 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr, return -rte_errno; } - flow->spec.efs_flags |= EFX_FILTER_FLAG_RX; - flow->spec.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + flow->spec.template.efs_flags |= EFX_FILTER_FLAG_RX; + flow->spec.template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; return 0; } @@ -1187,7 +1190,7 @@ sfc_flow_parse_pattern(const struct rte_flow_item pattern[], break; } - rc = item->parse(pattern, &flow->spec, error); + rc = item->parse(pattern, &flow->spec.template, error); if (rc != 0) return rc; @@ -1209,7 +1212,7 @@ sfc_flow_parse_queue(struct sfc_adapter *sa, return -EINVAL; rxq = sa->rxq_info[queue->index].rxq; - flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index; + flow->spec.template.efs_dmaq_id = (uint16_t)rxq->hw_index; return 0; } @@ -1285,13 +1288,57 @@ sfc_flow_parse_rss(struct sfc_adapter *sa, #endif /* EFSYS_OPT_RX_SCALE */ static int +sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec, + unsigned int filters_count) +{ + unsigned int i; + int ret = 0; + + for (i = 0; i < filters_count; i++) { + int rc; + + rc = efx_filter_remove(sa->nic, &spec->filters[i]); + if (ret == 0 && rc != 0) { + sfc_err(sa, "failed to remove filter specification " + "(rc = %d)", rc); + ret = rc; + } + } + + return ret; +} + +static int +sfc_flow_spec_insert(struct sfc_adapter *sa, struct sfc_flow_spec *spec) +{ + unsigned int i; + int rc = 0; + + for (i = 0; i < spec->count; i++) { + rc = efx_filter_insert(sa->nic, &spec->filters[i]); + if (rc != 0) { + sfc_flow_spec_flush(sa, spec, i); + break; + } + } + + return rc; +} + +static int +sfc_flow_spec_remove(struct sfc_adapter *sa, struct sfc_flow_spec *spec) +{ + return sfc_flow_spec_flush(sa, spec, spec->count); +} + +static int sfc_flow_filter_insert(struct sfc_adapter *sa, struct rte_flow *flow) { - efx_filter_spec_t *spec = &flow->spec; - #if EFSYS_OPT_RX_SCALE struct sfc_flow_rss *rss = &flow->rss_conf; + uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT; + unsigned int i; int rc = 0; if (flow->rss) { @@ -1302,27 +1349,38 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, rc = efx_rx_scale_context_alloc(sa->nic, EFX_RX_SCALE_EXCLUSIVE, rss_spread, - &spec->efs_rss_context); + &efs_rss_context); if (rc != 0) goto fail_scale_context_alloc; - rc = efx_rx_scale_mode_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context, EFX_RX_HASHALG_TOEPLITZ, rss->rss_hash_types, B_TRUE); if (rc != 0) goto fail_scale_mode_set; - rc = efx_rx_scale_key_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_key_set(sa->nic, efs_rss_context, rss->rss_key, sizeof(sa->rss_key)); if (rc != 0) goto fail_scale_key_set; - spec->efs_dmaq_id = rss->rxq_hw_index_min; - spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS; + /* + * At this point, fully elaborated filter specifications + * have been produced from the template. To make sure that + * RSS behaviour is consistent between them, set the same + * RSS context value everywhere. + */ + for (i = 0; i < flow->spec.count; i++) { + efx_filter_spec_t *spec = &flow->spec.filters[i]; + + spec->efs_rss_context = efs_rss_context; + spec->efs_dmaq_id = rss->rxq_hw_index_min; + spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS; + } } - rc = efx_filter_insert(sa->nic, spec); + rc = sfc_flow_spec_insert(sa, &flow->spec); if (rc != 0) goto fail_filter_insert; @@ -1335,7 +1393,7 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, * the HW knows all the information needed to verify * the table entries, and the operation will succeed */ - rc = efx_rx_scale_tbl_set(sa->nic, spec->efs_rss_context, + rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context, rss->rss_tbl, RTE_DIM(rss->rss_tbl)); if (rc != 0) goto fail_scale_tbl_set; @@ -1344,18 +1402,18 @@ sfc_flow_filter_insert(struct sfc_adapter *sa, return 0; fail_scale_tbl_set: - efx_filter_remove(sa->nic, spec); + sfc_flow_spec_remove(sa, &flow->spec); fail_filter_insert: fail_scale_key_set: fail_scale_mode_set: - if (flow->rss) - efx_rx_scale_context_free(sa->nic, spec->efs_rss_context); + if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) + efx_rx_scale_context_free(sa->nic, efs_rss_context); fail_scale_context_alloc: return rc; #else /* !EFSYS_OPT_RX_SCALE */ - return efx_filter_insert(sa->nic, spec); + return sfc_flow_spec_insert(sa, &flow->spec); #endif /* EFSYS_OPT_RX_SCALE */ } @@ -1363,16 +1421,23 @@ static int sfc_flow_filter_remove(struct sfc_adapter *sa, struct rte_flow *flow) { - efx_filter_spec_t *spec = &flow->spec; int rc = 0; - rc = efx_filter_remove(sa->nic, spec); + rc = sfc_flow_spec_remove(sa, &flow->spec); if (rc != 0) return rc; #if EFSYS_OPT_RX_SCALE - if (flow->rss) + if (flow->rss) { + /* + * All specifications for a given flow rule have the same RSS + * context, so that RSS context value is taken from the first + * filter specification + */ + efx_filter_spec_t *spec = &flow->spec.filters[0]; + rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context); + } #endif /* EFSYS_OPT_RX_SCALE */ return rc; @@ -1452,6 +1517,8 @@ sfc_flow_parse(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct sfc_adapter *sa = dev->data->dev_private; + efx_filter_match_flags_t match_flags = + flow->spec.template.efs_match_flags; int rc; rc = sfc_flow_parse_attr(attr, flow, error); @@ -1466,13 +1533,20 @@ sfc_flow_parse(struct rte_eth_dev *dev, if (rc != 0) goto fail_bad_value; - if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) { + if (!sfc_filter_is_match_supported(sa, match_flags)) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Flow rule pattern is not supported"); return -rte_errno; } + /* + * At this point, template specification simply becomes the first + * fully elaborated spec + */ + flow->spec.filters[0] = flow->spec.template; + flow->spec.count = 1; + fail_bad_value: return rc; } diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 35472ad..634c310 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -19,6 +19,13 @@ extern "C" { #endif +/* + * The maximum number of fully elaborated hardware filter specifications + * which can be produced from a template by means of multiplication, if + * missing match flags are needed to be taken into account + */ +#define SF_FLOW_SPEC_NB_FILTERS_MAX 1 + #if EFSYS_OPT_RX_SCALE /* RSS configuration storage */ struct sfc_flow_rss { @@ -30,9 +37,19 @@ struct sfc_flow_rss { }; #endif /* EFSYS_OPT_RX_SCALE */ +/* Filter specification storage */ +struct sfc_flow_spec { + /* partial specification from flow rule */ + efx_filter_spec_t template; + /* fully elaborated hardware filters specifications */ + efx_filter_spec_t filters[SF_FLOW_SPEC_NB_FILTERS_MAX]; + /* number of complete specifications */ + unsigned int count; +}; + /* PMD-specific definition of the opaque type from rte_flow.h */ struct rte_flow { - efx_filter_spec_t spec; /* filter specification */ + struct sfc_flow_spec spec; /* flow spec for hardware filter(s) */ #if EFSYS_OPT_RX_SCALE boolean_t rss; /* RSS toggle */ struct sfc_flow_rss rss_conf; /* RSS configuration */