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 B4A26A0A0C; Fri, 2 Jul 2021 10:42:31 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 03B60413CE; Fri, 2 Jul 2021 10:41:17 +0200 (CEST) Received: from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113]) by mails.dpdk.org (Postfix) with ESMTP id 63DD6413C3 for ; Fri, 2 Jul 2021 10:41:15 +0200 (CEST) Received: by shelob.oktetlabs.ru (Postfix, from userid 122) id 31ACC7F6C4; Fri, 2 Jul 2021 11:41:15 +0300 (MSK) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shelob.oktetlabs.ru X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=ALL_TRUSTED, DKIM_ADSP_DISCARD, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from aros.oktetlabs.ru (aros.oktetlabs.ru [192.168.38.17]) by shelob.oktetlabs.ru (Postfix) with ESMTP id 9EE207F6D2; Fri, 2 Jul 2021 11:40:19 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru 9EE207F6D2 Authentication-Results: shelob.oktetlabs.ru/9EE207F6D2; dkim=none; dkim-atps=neutral From: Andrew Rybchenko To: dev@dpdk.org Cc: David Marchand , Igor Romanov , Andy Moreton , Ivan Malov Date: Fri, 2 Jul 2021 11:39:48 +0300 Message-Id: <20210702083948.546667-21-andrew.rybchenko@oktetlabs.ru> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210702083948.546667-1-andrew.rybchenko@oktetlabs.ru> References: <20210527152510.1551026-1-andrew.rybchenko@oktetlabs.ru> <20210702083948.546667-1-andrew.rybchenko@oktetlabs.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v4 20/20] net/sfc: support flow API query for count actions 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" From: Igor Romanov The query reports the number of hits for a counter associated with a flow rule. Signed-off-by: Igor Romanov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton Reviewed-by: Ivan Malov --- drivers/net/sfc/sfc_flow.c | 48 ++++++++++++++++++++++- drivers/net/sfc/sfc_flow.h | 6 +++ drivers/net/sfc/sfc_mae.c | 64 +++++++++++++++++++++++++++++++ drivers/net/sfc/sfc_mae.h | 1 + drivers/net/sfc/sfc_mae_counter.c | 32 ++++++++++++++++ drivers/net/sfc/sfc_mae_counter.h | 3 ++ 6 files changed, 153 insertions(+), 1 deletion(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 1294dbd3a7..af7f5df4bf 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -32,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; @@ -45,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 = { @@ -53,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 * @@ -2788,6 +2791,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) @@ -2814,7 +2860,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, }; diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index bd3b374d68..99e5cf9cff 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -181,6 +181,12 @@ typedef int (sfc_flow_insert_cb_t)(struct sfc_adapter *sa, typedef int (sfc_flow_remove_cb_t)(struct sfc_adapter *sa, struct rte_flow *flow); +typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev, + struct rte_flow *flow, + const struct rte_flow_action *action, + void *data, + struct rte_flow_error *error); + #ifdef __cplusplus } #endif diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index c3efd5b407..a4eab30dec 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -3187,3 +3187,67 @@ sfc_mae_flow_remove(struct sfc_adapter *sa, return 0; } + +static int +sfc_mae_query_counter(struct sfc_adapter *sa, + struct sfc_flow_spec_mae *spec, + const struct rte_flow_action *action, + struct rte_flow_query_count *data, + struct rte_flow_error *error) +{ + struct sfc_mae_action_set *action_set = spec->action_set; + const struct rte_flow_action_count *conf = action->conf; + unsigned int i; + int rc; + + if (action_set->n_counters == 0) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "Queried flow rule does not have count actions"); + } + + for (i = 0; i < action_set->n_counters; i++) { + /* + * Get the first available counter of the flow rule if + * counter ID is not specified. + */ + if (conf != NULL && action_set->counters[i].rte_id != conf->id) + continue; + + rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters, + &action_set->counters[i], data); + if (rc != 0) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "Queried flow rule counter action is invalid"); + } + + return 0; + } + + return rte_flow_error_set(error, ENOENT, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "No such flow rule action count ID"); +} + +int +sfc_mae_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); + struct sfc_flow_spec *spec = &flow->spec; + struct sfc_flow_spec_mae *spec_mae = &spec->mae; + + switch (action->type) { + case RTE_FLOW_ACTION_TYPE_COUNT: + return sfc_mae_query_counter(sa, spec_mae, action, + data, error); + default: + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "Query for action of this type is not supported"); + } +} diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h index 2cc4334890..6bfc8afb82 100644 --- a/drivers/net/sfc/sfc_mae.h +++ b/drivers/net/sfc/sfc_mae.h @@ -291,6 +291,7 @@ int sfc_mae_rule_parse_actions(struct sfc_adapter *sa, sfc_flow_verify_cb_t sfc_mae_flow_verify; sfc_flow_insert_cb_t sfc_mae_flow_insert; sfc_flow_remove_cb_t sfc_mae_flow_remove; +sfc_flow_query_cb_t sfc_mae_flow_query; #ifdef __cplusplus } diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c index b0cb8157aa..5afd450a11 100644 --- a/drivers/net/sfc/sfc_mae_counter.c +++ b/drivers/net/sfc/sfc_mae_counter.c @@ -793,3 +793,35 @@ sfc_mae_counter_start(struct sfc_adapter *sa) return rc; } + +int +sfc_mae_counter_get(struct sfc_mae_counters *counters, + const struct sfc_mae_counter_id *counter, + struct rte_flow_query_count *data) +{ + struct sfc_mae_counter *p; + union sfc_pkts_bytes value; + + SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters); + p = &counters->mae_counters[counter->mae_id.id]; + + /* + * Ordering is relaxed since it is the only operation on counter value. + * And it does not depend on different stores/loads in other threads. + * Paired with relaxed ordering in counter increment. + */ + value.pkts_bytes.int128 = __atomic_load_n(&p->value.pkts_bytes.int128, + __ATOMIC_RELAXED); + + data->hits_set = 1; + data->bytes_set = 1; + data->hits = value.pkts - p->reset.pkts; + data->bytes = value.bytes - p->reset.bytes; + + if (data->reset != 0) { + p->reset.pkts = value.pkts; + p->reset.bytes = value.bytes; + } + + return 0; +} diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h index f61a6b59cb..2c953c2968 100644 --- a/drivers/net/sfc/sfc_mae_counter.h +++ b/drivers/net/sfc/sfc_mae_counter.h @@ -45,6 +45,9 @@ int sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter_id *counterp); int sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter_id *counter); +int sfc_mae_counter_get(struct sfc_mae_counters *counters, + const struct sfc_mae_counter_id *counter, + struct rte_flow_query_count *data); int sfc_mae_counter_start(struct sfc_adapter *sa); void sfc_mae_counter_stop(struct sfc_adapter *sa); -- 2.30.2