get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/93518/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 93518,
    "url": "https://patches.dpdk.org/api/patches/93518/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210527152510.1551026-21-andrew.rybchenko@oktetlabs.ru/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210527152510.1551026-21-andrew.rybchenko@oktetlabs.ru>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210527152510.1551026-21-andrew.rybchenko@oktetlabs.ru",
    "date": "2021-05-27T15:25:10",
    "name": "[20/20] net/sfc: support flow API query for count actions",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "873d61cdd6068812f562a3027e2fd3ea6ca7c6bc",
    "submitter": {
        "id": 2013,
        "url": "https://patches.dpdk.org/api/people/2013/?format=api",
        "name": "Andrew Rybchenko",
        "email": "Andrew.Rybchenko@oktetlabs.ru"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210527152510.1551026-21-andrew.rybchenko@oktetlabs.ru/mbox/",
    "series": [
        {
            "id": 17144,
            "url": "https://patches.dpdk.org/api/series/17144/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=17144",
            "date": "2021-05-27T15:24:50",
            "name": "net/sfc: support flow API COUNT action",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/17144/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/93518/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/93518/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id CC16DA0546;\n\tThu, 27 May 2021 17:27:58 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id C775241167;\n\tThu, 27 May 2021 17:26:29 +0200 (CEST)",
            "from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113])\n by mails.dpdk.org (Postfix) with ESMTP id 1A36341163\n for <dev@dpdk.org>; Thu, 27 May 2021 17:26:28 +0200 (CEST)",
            "by shelob.oktetlabs.ru (Postfix, from userid 122)\n id DEADC7F606; Thu, 27 May 2021 18:26:27 +0300 (MSK)",
            "from aros.oktetlabs.ru (aros.oktetlabs.ru [192.168.38.17])\n by shelob.oktetlabs.ru (Postfix) with ESMTP id C95A37F60F;\n Thu, 27 May 2021 18:25:43 +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,\n DKIM_ADSP_DISCARD,\n URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2",
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru C95A37F60F",
        "Authentication-Results": "shelob.oktetlabs.ru/C95A37F60F; dkim=none;\n dkim-atps=neutral",
        "From": "Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>",
        "To": "dev@dpdk.org",
        "Cc": "Igor Romanov <igor.romanov@oktetlabs.ru>,\n Andy Moreton <amoreton@xilinx.com>, Ivan Malov <ivan.malov@oktetlabs.ru>",
        "Date": "Thu, 27 May 2021 18:25:10 +0300",
        "Message-Id": "<20210527152510.1551026-21-andrew.rybchenko@oktetlabs.ru>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20210527152510.1551026-1-andrew.rybchenko@oktetlabs.ru>",
        "References": "<20210527152510.1551026-1-andrew.rybchenko@oktetlabs.ru>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH 20/20] net/sfc: support flow API query for count\n actions",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Igor Romanov <igor.romanov@oktetlabs.ru>\n\nThe query reports the number of hits for a counter associated\nwith a flow rule.\n\nSigned-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>\nSigned-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>\nReviewed-by: Andy Moreton <amoreton@xilinx.com>\nReviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>\n---\n drivers/net/sfc/sfc_flow.c        | 40 ++++++++++++++++++-\n drivers/net/sfc/sfc_flow.h        |  6 +++\n drivers/net/sfc/sfc_mae.c         | 64 +++++++++++++++++++++++++++++++\n drivers/net/sfc/sfc_mae.h         |  1 +\n drivers/net/sfc/sfc_mae_counter.c | 32 ++++++++++++++++\n drivers/net/sfc/sfc_mae_counter.h |  3 ++\n 6 files changed, 145 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c\nindex 1294dbd3a7..d00d3a2363 100644\n--- a/drivers/net/sfc/sfc_flow.c\n+++ b/drivers/net/sfc/sfc_flow.c\n@@ -32,6 +32,7 @@ struct sfc_flow_ops_by_spec {\n \tsfc_flow_cleanup_cb_t\t*cleanup;\n \tsfc_flow_insert_cb_t\t*insert;\n \tsfc_flow_remove_cb_t\t*remove;\n+\tsfc_flow_query_cb_t\t*query;\n };\n \n static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter;\n@@ -45,6 +46,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {\n \t.cleanup = NULL,\n \t.insert = sfc_flow_filter_insert,\n \t.remove = sfc_flow_filter_remove,\n+\t.query = NULL,\n };\n \n static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {\n@@ -53,6 +55,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {\n \t.cleanup = sfc_mae_flow_cleanup,\n \t.insert = sfc_mae_flow_insert,\n \t.remove = sfc_mae_flow_remove,\n+\t.query = sfc_mae_flow_query,\n };\n \n static const struct sfc_flow_ops_by_spec *\n@@ -2788,6 +2791,41 @@ sfc_flow_flush(struct rte_eth_dev *dev,\n \treturn -ret;\n }\n \n+static int\n+sfc_flow_query(struct rte_eth_dev *dev,\n+\t       struct rte_flow *flow,\n+\t       const struct rte_flow_action *action,\n+\t       void *data,\n+\t       struct rte_flow_error *error)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tconst struct sfc_flow_ops_by_spec *ops;\n+\tint ret;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tops = sfc_flow_get_ops_by_spec(flow);\n+\tif (ops == NULL || ops->query == NULL) {\n+\t\tret = rte_flow_error_set(error, ENOTSUP,\n+\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\"No backend to handle this flow\");\n+\t\tgoto fail_no_backend;\n+\t}\n+\n+\tret = ops->query(dev, flow, action, data, error);\n+\tif (ret != 0)\n+\t\tgoto fail_query;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn 0;\n+\n+fail_query:\n+fail_no_backend:\n+\tsfc_adapter_unlock(sa);\n+\treturn ret;\n+}\n+\n static int\n sfc_flow_isolate(struct rte_eth_dev *dev, int enable,\n \t\t struct rte_flow_error *error)\n@@ -2814,7 +2852,7 @@ const struct rte_flow_ops sfc_flow_ops = {\n \t.create = sfc_flow_create,\n \t.destroy = sfc_flow_destroy,\n \t.flush = sfc_flow_flush,\n-\t.query = NULL,\n+\t.query = sfc_flow_query,\n \t.isolate = sfc_flow_isolate,\n };\n \ndiff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h\nindex bd3b374d68..99e5cf9cff 100644\n--- a/drivers/net/sfc/sfc_flow.h\n+++ b/drivers/net/sfc/sfc_flow.h\n@@ -181,6 +181,12 @@ typedef int (sfc_flow_insert_cb_t)(struct sfc_adapter *sa,\n typedef int (sfc_flow_remove_cb_t)(struct sfc_adapter *sa,\n \t\t\t\t   struct rte_flow *flow);\n \n+typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,\n+\t\t\t\t  struct rte_flow *flow,\n+\t\t\t\t  const struct rte_flow_action *action,\n+\t\t\t\t  void *data,\n+\t\t\t\t  struct rte_flow_error *error);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c\nindex 370a39da1d..ee1188bc1e 100644\n--- a/drivers/net/sfc/sfc_mae.c\n+++ b/drivers/net/sfc/sfc_mae.c\n@@ -3277,3 +3277,67 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,\n \n \treturn 0;\n }\n+\n+static int\n+sfc_mae_query_counter(struct sfc_adapter *sa,\n+\t\t      struct sfc_flow_spec_mae *spec,\n+\t\t      const struct rte_flow_action *action,\n+\t\t      struct rte_flow_query_count *data,\n+\t\t      struct rte_flow_error *error)\n+{\n+\tstruct sfc_mae_action_set *action_set = spec->action_set;\n+\tconst struct rte_flow_action_count *conf = action->conf;\n+\tunsigned int i;\n+\tint rc;\n+\n+\tif (action_set->n_counters == 0) {\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, action,\n+\t\t\t\"Queried flow rule does not have count actions\");\n+\t}\n+\n+\tfor (i = 0; i < action_set->n_counters; i++) {\n+\t\t/*\n+\t\t * Get the first available counter of the flow rule if\n+\t\t * counter ID is not specified.\n+\t\t */\n+\t\tif (conf != NULL && action_set->counters[i].rte_id != conf->id)\n+\t\t\tcontinue;\n+\n+\t\trc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,\n+\t\t\t\t\t &action_set->counters[i], data);\n+\t\tif (rc != 0) {\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, action,\n+\t\t\t\t\"Queried flow rule counter action is invalid\");\n+\t\t}\n+\n+\t\treturn 0;\n+\t}\n+\n+\treturn rte_flow_error_set(error, ENOENT,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n+\t\t\t\t  \"No such flow rule action count ID\");\n+}\n+\n+int\n+sfc_mae_flow_query(struct rte_eth_dev *dev,\n+\t\t   struct rte_flow *flow,\n+\t\t   const struct rte_flow_action *action,\n+\t\t   void *data,\n+\t\t   struct rte_flow_error *error)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tstruct sfc_flow_spec *spec = &flow->spec;\n+\tstruct sfc_flow_spec_mae *spec_mae = &spec->mae;\n+\n+\tswitch (action->type) {\n+\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\treturn sfc_mae_query_counter(sa, spec_mae, action,\n+\t\t\t\t\t     data, error);\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, NULL,\n+\t\t\t\"Query for action of this type is not supported\");\n+\t}\n+}\ndiff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h\nindex 15fe5ebca5..7e3b6a7a97 100644\n--- a/drivers/net/sfc/sfc_mae.h\n+++ b/drivers/net/sfc/sfc_mae.h\n@@ -304,6 +304,7 @@ int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n sfc_flow_verify_cb_t sfc_mae_flow_verify;\n sfc_flow_insert_cb_t sfc_mae_flow_insert;\n sfc_flow_remove_cb_t sfc_mae_flow_remove;\n+sfc_flow_query_cb_t sfc_mae_flow_query;\n \n #ifdef __cplusplus\n }\ndiff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c\nindex 3aeb37f7ec..c758b74b9b 100644\n--- a/drivers/net/sfc/sfc_mae_counter.c\n+++ b/drivers/net/sfc/sfc_mae_counter.c\n@@ -793,3 +793,35 @@ sfc_mae_counter_start(struct sfc_adapter *sa)\n \n \treturn rc;\n }\n+\n+int\n+sfc_mae_counter_get(struct sfc_mae_counters *counters,\n+\t\t    const struct sfc_mae_counter_id *counter,\n+\t\t    struct rte_flow_query_count *data)\n+{\n+\tstruct sfc_mae_counter *p;\n+\tunion sfc_pkts_bytes value;\n+\n+\tSFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);\n+\tp = &counters->mae_counters[counter->mae_id.id];\n+\n+\t/*\n+\t * Ordering is relaxed since it is the only operation on counter value.\n+\t * And it does not depend on different stores/loads in other threads.\n+\t * Paired with relaxed ordering in counter increment.\n+\t */\n+\tvalue.pkts_bytes.int128 = __atomic_load_n(&p->value.pkts_bytes.int128,\n+\t\t\t\t\t\t  __ATOMIC_RELAXED);\n+\n+\tdata->hits_set = 1;\n+\tdata->bytes_set = 1;\n+\tdata->hits = value.pkts - p->reset.pkts;\n+\tdata->bytes = value.bytes - p->reset.bytes;\n+\n+\tif (data->reset != 0) {\n+\t\tp->reset.pkts = value.pkts;\n+\t\tp->reset.bytes = value.bytes;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h\nindex f61a6b59cb..2c953c2968 100644\n--- a/drivers/net/sfc/sfc_mae_counter.h\n+++ b/drivers/net/sfc/sfc_mae_counter.h\n@@ -45,6 +45,9 @@ int sfc_mae_counter_enable(struct sfc_adapter *sa,\n \t\t\t   struct sfc_mae_counter_id *counterp);\n int sfc_mae_counter_disable(struct sfc_adapter *sa,\n \t\t\t    struct sfc_mae_counter_id *counter);\n+int sfc_mae_counter_get(struct sfc_mae_counters *counters,\n+\t\t\tconst struct sfc_mae_counter_id *counter,\n+\t\t\tstruct rte_flow_query_count *data);\n \n int sfc_mae_counter_start(struct sfc_adapter *sa);\n void sfc_mae_counter_stop(struct sfc_adapter *sa);\n",
    "prefixes": [
        "20/20"
    ]
}