Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/26612/?format=api
https://patches.dpdk.org/api/patches/26612/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/patch/a58bc82fb1f2fc2743aaa370a79f7a159a618ee2.1499384906.git.gaetan.rivet@6wind.com/", "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": "<a58bc82fb1f2fc2743aaa370a79f7a159a618ee2.1499384906.git.gaetan.rivet@6wind.com>", "list_archive_url": "https://inbox.dpdk.org/dev/a58bc82fb1f2fc2743aaa370a79f7a159a618ee2.1499384906.git.gaetan.rivet@6wind.com", "date": "2017-07-07T00:09:32", "name": "[dpdk-dev,v6,18/23] net/failsafe: support flow API", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "c697eb3bee36722c99e88cd076494e103d17391b", "submitter": { "id": 269, "url": "https://patches.dpdk.org/api/people/269/?format=api", "name": "Gaëtan Rivet", "email": "gaetan.rivet@6wind.com" }, "delegate": null, "mbox": "https://patches.dpdk.org/project/dpdk/patch/a58bc82fb1f2fc2743aaa370a79f7a159a618ee2.1499384906.git.gaetan.rivet@6wind.com/mbox/", "series": [], "comments": "https://patches.dpdk.org/api/patches/26612/comments/", "check": "fail", "checks": "https://patches.dpdk.org/api/patches/26612/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@dpdk.org", "Delivered-To": "patchwork@dpdk.org", "Received": [ "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 994507D21;\n\tFri, 7 Jul 2017 02:11:02 +0200 (CEST)", "from mail-wr0-f178.google.com (mail-wr0-f178.google.com\n\t[209.85.128.178]) by dpdk.org (Postfix) with ESMTP id 221917CC6\n\tfor <dev@dpdk.org>; Fri, 7 Jul 2017 02:10:24 +0200 (CEST)", "by mail-wr0-f178.google.com with SMTP id r103so24429416wrb.0\n\tfor <dev@dpdk.org>; Thu, 06 Jul 2017 17:10:24 -0700 (PDT)", "from bidouze.dev.6wind.com (host.78.145.23.62.rev.coltfrance.com.\n\t[62.23.145.78]) by smtp.gmail.com with ESMTPSA id\n\tf45sm2391166wrf.2.2017.07.06.17.10.22\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tThu, 06 Jul 2017 17:10:22 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:in-reply-to:references;\n\tbh=6o7m7kxBdpLhMTlxOFLH8aYOEoD492O9r+haQ1heD3E=;\n\tb=KDJhyM1slDkJ1mi6iwJxX6kQhV8rwiAZSIYCbLgGBHSZbjw2r3oqzlXJEODB1h9DSP\n\tKf//xYrBQPaEebr5J1M+ERsGmVOTxY0KMED8YTWtaHGK7yTayenVOEVxO9Fy/wnnA5ni\n\tYDEimnJMIpg0z5NbDzkRE7i+foS2ntTPlODS+hNu8yW6hXoIVYjU5HDjokBXWIb9AQov\n\tw15q66pwcqPpVNPcPf2ruvdxbf2SXVXXYy5J5sPlGKwDQbkTi3ursjYj5SxboXJXcy8X\n\tBiBVmpO9uGrAFJYa0kMve05NyQahW28TcOnpmTJ1cSpqcl55Y37BCeMnh8Gr47xGM4iT\n\tmsgg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:in-reply-to:references;\n\tbh=6o7m7kxBdpLhMTlxOFLH8aYOEoD492O9r+haQ1heD3E=;\n\tb=kBf4BBw0+hiky0cXH6CYaJLfB0OUSL2qhUutSUythE2ckcsoiEE77PxFVIBx3z+v5I\n\tOt8OUb6efIpzoxpdOH5nggbgigvVfE12QCBegkWWPOSjDVxTQCwPYN9ZCkCI4elI2v0T\n\tLjWcubgc4LebxiDMHfLjeuNkbMHJIfPIEixKoKB2jupAbOgG805sH7bo2yIids3oTcAG\n\tkK+wjsVhJFpRWeNY++1xxx62R+mi8DtD59UdHeznNBPfZLw/cUsmK8QI4dhq2ycX0nHW\n\thmuIc11MnGFrauSGeil94oYDy955jdCQ/rMePN74yCooBFSdDtnJkCwwc4uLKzynsqTG\n\t7ADw==", "X-Gm-Message-State": "AIVw110cXKMlYWfIWp+k1OlFuDheVlGrokLjrdrfYuUmxDWdt28Puefj\n\tFuSW1jL4OgjlLF4XBMg=", "X-Received": "by 10.28.66.67 with SMTP id p64mr267006wma.93.1499386223280;\n\tThu, 06 Jul 2017 17:10:23 -0700 (PDT)", "From": "Gaetan Rivet <gaetan.rivet@6wind.com>", "To": "dev@dpdk.org", "Cc": "Gaetan Rivet <gaetan.rivet@6wind.com>", "Date": "Fri, 7 Jul 2017 02:09:32 +0200", "Message-Id": "<a58bc82fb1f2fc2743aaa370a79f7a159a618ee2.1499384906.git.gaetan.rivet@6wind.com>", "X-Mailer": "git-send-email 2.1.4", "In-Reply-To": [ "<cover.1499385281.git.gaetan.rivet@6wind.com>", "<cover.1499384906.git.gaetan.rivet@6wind.com>" ], "References": [ "<cover.1496877105.git.gaetan.rivet@6wind.com>\n\t<cover.1499385281.git.gaetan.rivet@6wind.com>", "<cover.1499384906.git.gaetan.rivet@6wind.com>" ], "Subject": "[dpdk-dev] [PATCH v6 18/23] net/failsafe: support flow API", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.15", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://dpdk.org/ml/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org", "Sender": "\"dev\" <dev-bounces@dpdk.org>" }, "content": "Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>\nAcked-by: Olga Shern <olgas@mellanox.com>\n---\n doc/guides/nics/features/failsafe.ini | 1 +\n drivers/net/failsafe/Makefile | 1 +\n drivers/net/failsafe/failsafe.c | 1 +\n drivers/net/failsafe/failsafe_eal.c | 1 +\n drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++\n drivers/net/failsafe/failsafe_flow.c | 216 ++++++++++++++++++++++++++++++++\n drivers/net/failsafe/failsafe_ops.c | 29 +++++\n drivers/net/failsafe/failsafe_private.h | 18 +++\n 8 files changed, 337 insertions(+)\n create mode 100644 drivers/net/failsafe/failsafe_flow.c", "diff": "diff --git a/doc/guides/nics/features/failsafe.ini b/doc/guides/nics/features/failsafe.ini\nindex 3c52823..9167b59 100644\n--- a/doc/guides/nics/features/failsafe.ini\n+++ b/doc/guides/nics/features/failsafe.ini\n@@ -13,6 +13,7 @@ Allmulticast mode = Y\n Unicast MAC filter = Y\n Multicast MAC filter = Y\n VLAN filter = Y\n+Flow API = Y\n Packet type parsing = Y\n Basic stats = Y\n Stats per queue = Y\ndiff --git a/drivers/net/failsafe/Makefile b/drivers/net/failsafe/Makefile\nindex e27bfc0..3cccfe0 100644\n--- a/drivers/net/failsafe/Makefile\n+++ b/drivers/net/failsafe/Makefile\n@@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c\n \n # No exported include files\n \ndiff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c\nindex 888f07b..6557255 100644\n--- a/drivers/net/failsafe/failsafe.c\n+++ b/drivers/net/failsafe/failsafe.c\n@@ -177,6 +177,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev)\n \tdev->data->mac_addrs = &PRIV(dev)->mac_addrs[0];\n \tdev->data->dev_link = eth_link;\n \tPRIV(dev)->nb_mac_addr = 1;\n+\tTAILQ_INIT(&PRIV(dev)->flow_list);\n \tdev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst;\n \tdev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst;\n \tif (params == NULL) {\ndiff --git a/drivers/net/failsafe/failsafe_eal.c b/drivers/net/failsafe/failsafe_eal.c\nindex 16871df..86e16a6 100644\n--- a/drivers/net/failsafe/failsafe_eal.c\n+++ b/drivers/net/failsafe/failsafe_eal.c\n@@ -78,6 +78,7 @@ fs_bus_init(struct rte_eth_dev *dev)\n \t\t\tERROR(\"sub_device %d init went wrong\", i);\n \t\t\treturn -ENODEV;\n \t\t}\n+\t\tSUB_ID(sdev) = i;\n \t\tsdev->dev = ETH(sdev)->device;\n \t\tETH(sdev)->state = RTE_ETH_DEV_DEFERRED;\n \t\tsdev->state = DEV_PROBED;\ndiff --git a/drivers/net/failsafe/failsafe_ether.c b/drivers/net/failsafe/failsafe_ether.c\nindex 2a1535e..2958207 100644\n--- a/drivers/net/failsafe/failsafe_ether.c\n+++ b/drivers/net/failsafe/failsafe_ether.c\n@@ -33,8 +33,46 @@\n \n #include <unistd.h>\n \n+#include <rte_flow.h>\n+#include <rte_flow_driver.h>\n+\n #include \"failsafe_private.h\"\n \n+/** Print a message out of a flow error. */\n+static int\n+fs_flow_complain(struct rte_flow_error *error)\n+{\n+\tstatic const char *const errstrlist[] = {\n+\t\t[RTE_FLOW_ERROR_TYPE_NONE] = \"no error\",\n+\t\t[RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = \"cause unspecified\",\n+\t\t[RTE_FLOW_ERROR_TYPE_HANDLE] = \"flow rule (handle)\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = \"group field\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = \"priority field\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = \"ingress field\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = \"egress field\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ATTR] = \"attributes structure\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ITEM_NUM] = \"pattern length\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ITEM] = \"specific pattern item\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ACTION_NUM] = \"number of actions\",\n+\t\t[RTE_FLOW_ERROR_TYPE_ACTION] = \"specific action\",\n+\t};\n+\tconst char *errstr;\n+\tchar buf[32];\n+\tint err = rte_errno;\n+\n+\tif ((unsigned int)error->type >= RTE_DIM(errstrlist) ||\n+\t\t\t!errstrlist[error->type])\n+\t\terrstr = \"unknown type\";\n+\telse\n+\t\terrstr = errstrlist[error->type];\n+\tERROR(\"Caught error type %d (%s): %s%s\\n\",\n+\t\terror->type, errstr,\n+\t\terror->cause ? (snprintf(buf, sizeof(buf), \"cause: %p, \",\n+\t\t\t\terror->cause), buf) : \"\",\n+\t\terror->message ? error->message : \"(no stated reason)\");\n+\treturn -err;\n+}\n+\n static int\n fs_eth_dev_conf_apply(struct rte_eth_dev *dev,\n \t\tstruct sub_device *sdev)\n@@ -42,6 +80,8 @@ fs_eth_dev_conf_apply(struct rte_eth_dev *dev,\n \tstruct rte_eth_dev *edev;\n \tstruct rte_vlan_filter_conf *vfc1;\n \tstruct rte_vlan_filter_conf *vfc2;\n+\tstruct rte_flow *flow;\n+\tstruct rte_flow_error ferror;\n \tuint32_t i;\n \tint ret;\n \n@@ -177,6 +217,36 @@ fs_eth_dev_conf_apply(struct rte_eth_dev *dev,\n \t} else {\n \t\tDEBUG(\"VLAN filter already set\");\n \t}\n+\t/* rte_flow */\n+\tif (TAILQ_EMPTY(&PRIV(dev)->flow_list)) {\n+\t\tDEBUG(\"rte_flow already set\");\n+\t} else {\n+\t\tDEBUG(\"Resetting rte_flow configuration\");\n+\t\tret = rte_flow_flush(PORT_ID(sdev), &ferror);\n+\t\tif (ret) {\n+\t\t\tfs_flow_complain(&ferror);\n+\t\t\treturn ret;\n+\t\t}\n+\t\ti = 0;\n+\t\trte_errno = 0;\n+\t\tDEBUG(\"Configuring rte_flow\");\n+\t\tTAILQ_FOREACH(flow, &PRIV(dev)->flow_list, next) {\n+\t\t\tDEBUG(\"Creating flow #%\" PRIu32, i++);\n+\t\t\tflow->flows[SUB_ID(sdev)] =\n+\t\t\t\trte_flow_create(PORT_ID(sdev),\n+\t\t\t\t\t\t&flow->fd->attr,\n+\t\t\t\t\t\tflow->fd->items,\n+\t\t\t\t\t\tflow->fd->actions,\n+\t\t\t\t\t\t&ferror);\n+\t\t\tret = rte_errno;\n+\t\t\tif (ret)\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tif (ret) {\n+\t\t\tfs_flow_complain(&ferror);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n \treturn 0;\n }\n \ndiff --git a/drivers/net/failsafe/failsafe_flow.c b/drivers/net/failsafe/failsafe_flow.c\nnew file mode 100644\nindex 0000000..d8f59a1\n--- /dev/null\n+++ b/drivers/net/failsafe/failsafe_flow.c\n@@ -0,0 +1,216 @@\n+/*-\n+ * BSD LICENSE\n+ *\n+ * Copyright 2017 6WIND S.A.\n+ * Copyright 2017 Mellanox.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions\n+ * are met:\n+ *\n+ * * Redistributions of source code must retain the above copyright\n+ * notice, this list of conditions and the following disclaimer.\n+ * * Redistributions in binary form must reproduce the above copyright\n+ * notice, this list of conditions and the following disclaimer in\n+ * the documentation and/or other materials provided with the\n+ * distribution.\n+ * * Neither the name of 6WIND S.A. nor the names of its\n+ * contributors may be used to endorse or promote products derived\n+ * from this software without specific prior written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <sys/queue.h>\n+\n+#include <rte_malloc.h>\n+#include <rte_tailq.h>\n+#include <rte_flow.h>\n+#include <rte_flow_driver.h>\n+\n+#include \"failsafe_private.h\"\n+\n+static struct rte_flow *\n+fs_flow_allocate(const struct rte_flow_attr *attr,\n+\t\t const struct rte_flow_item *items,\n+\t\t const struct rte_flow_action *actions)\n+{\n+\tstruct rte_flow *flow;\n+\tsize_t fdsz;\n+\n+\tfdsz = rte_flow_copy(NULL, 0, attr, items, actions);\n+\tflow = rte_zmalloc(NULL,\n+\t\t\t sizeof(struct rte_flow) + fdsz,\n+\t\t\t RTE_CACHE_LINE_SIZE);\n+\tif (flow == NULL) {\n+\t\tERROR(\"Could not allocate new flow\");\n+\t\treturn NULL;\n+\t}\n+\tflow->fd = (void *)((uintptr_t)flow + sizeof(*flow));\n+\tif (rte_flow_copy(flow->fd, fdsz, attr, items, actions) != fdsz) {\n+\t\tERROR(\"Failed to copy flow description\");\n+\t\trte_free(flow);\n+\t\treturn NULL;\n+\t}\n+\treturn flow;\n+}\n+\n+static void\n+fs_flow_release(struct rte_flow **flow)\n+{\n+\trte_free((*flow)->fd);\n+\trte_free(*flow);\n+\t*flow = NULL;\n+}\n+\n+static int\n+fs_flow_validate(struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_attr *attr,\n+\t\t const struct rte_flow_item patterns[],\n+\t\t const struct rte_flow_action actions[],\n+\t\t struct rte_flow_error *error)\n+{\n+\tstruct sub_device *sdev;\n+\tuint8_t i;\n+\tint ret;\n+\n+\tFOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {\n+\t\tDEBUG(\"Calling rte_flow_validate on sub_device %d\", i);\n+\t\tret = rte_flow_validate(PORT_ID(sdev),\n+\t\t\t\tattr, patterns, actions, error);\n+\t\tif (ret) {\n+\t\t\tERROR(\"Operation rte_flow_validate failed for sub_device %d\"\n+\t\t\t \" with error %d\", i, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static struct rte_flow *\n+fs_flow_create(struct rte_eth_dev *dev,\n+\t const struct rte_flow_attr *attr,\n+\t const struct rte_flow_item patterns[],\n+\t const struct rte_flow_action actions[],\n+\t struct rte_flow_error *error)\n+{\n+\tstruct sub_device *sdev;\n+\tstruct rte_flow *flow;\n+\tuint8_t i;\n+\n+\tflow = fs_flow_allocate(attr, patterns, actions);\n+\tFOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {\n+\t\tflow->flows[i] = rte_flow_create(PORT_ID(sdev),\n+\t\t\t\tattr, patterns, actions, error);\n+\t\tif (flow->flows[i] == NULL) {\n+\t\t\tERROR(\"Failed to create flow on sub_device %d\",\n+\t\t\t\ti);\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\tTAILQ_INSERT_TAIL(&PRIV(dev)->flow_list, flow, next);\n+\treturn flow;\n+err:\n+\tFOREACH_SUBDEV(sdev, i, dev) {\n+\t\tif (flow->flows[i] != NULL)\n+\t\t\trte_flow_destroy(PORT_ID(sdev),\n+\t\t\t\tflow->flows[i], error);\n+\t}\n+\tfs_flow_release(&flow);\n+\treturn NULL;\n+}\n+\n+static int\n+fs_flow_destroy(struct rte_eth_dev *dev,\n+\t\tstruct rte_flow *flow,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tstruct sub_device *sdev;\n+\tuint8_t i;\n+\tint ret;\n+\n+\tif (flow == NULL) {\n+\t\tERROR(\"Invalid flow\");\n+\t\treturn -EINVAL;\n+\t}\n+\tret = 0;\n+\tFOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {\n+\t\tint local_ret;\n+\n+\t\tif (flow->flows[i] == NULL)\n+\t\t\tcontinue;\n+\t\tlocal_ret = rte_flow_destroy(PORT_ID(sdev),\n+\t\t\t\tflow->flows[i], error);\n+\t\tif (local_ret) {\n+\t\t\tERROR(\"Failed to destroy flow on sub_device %d: %d\",\n+\t\t\t\t\ti, local_ret);\n+\t\t\tif (ret == 0)\n+\t\t\t\tret = local_ret;\n+\t\t}\n+\t}\n+\tTAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);\n+\trte_free(flow);\n+\treturn ret;\n+}\n+\n+static int\n+fs_flow_flush(struct rte_eth_dev *dev,\n+\t struct rte_flow_error *error)\n+{\n+\tstruct sub_device *sdev;\n+\tstruct rte_flow *flow;\n+\tvoid *tmp;\n+\tuint8_t i;\n+\tint ret;\n+\n+\tFOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {\n+\t\tDEBUG(\"Calling rte_flow_flush on sub_device %d\", i);\n+\t\tret = rte_flow_flush(PORT_ID(sdev), error);\n+\t\tif (ret) {\n+\t\t\tERROR(\"Operation rte_flow_flush failed for sub_device %d\"\n+\t\t\t \" with error %d\", i, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\tTAILQ_FOREACH_SAFE(flow, &PRIV(dev)->flow_list, next, tmp) {\n+\t\tTAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);\n+\t\tfs_flow_release(&flow);\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+fs_flow_query(struct rte_eth_dev *dev,\n+\t struct rte_flow *flow,\n+\t enum rte_flow_action_type type,\n+\t void *arg,\n+\t struct rte_flow_error *error)\n+{\n+\tstruct sub_device *sdev;\n+\n+\tsdev = TX_SUBDEV(dev);\n+\tif (sdev != NULL) {\n+\t\treturn rte_flow_query(PORT_ID(sdev),\n+\t\t\t\tflow->flows[SUB_ID(sdev)], type, arg, error);\n+\t}\n+\tWARN(\"No active sub_device to query about its flow\");\n+\treturn -1;\n+}\n+\n+const struct rte_flow_ops fs_flow_ops = {\n+\t.validate = fs_flow_validate,\n+\t.create = fs_flow_create,\n+\t.destroy = fs_flow_destroy,\n+\t.flush = fs_flow_flush,\n+\t.query = fs_flow_query,\n+};\ndiff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c\nindex 4044473..4cb2e90 100644\n--- a/drivers/net/failsafe/failsafe_ops.c\n+++ b/drivers/net/failsafe/failsafe_ops.c\n@@ -35,6 +35,7 @@\n #include <stdint.h>\n #include <rte_ethdev.h>\n #include <rte_malloc.h>\n+#include <rte_flow.h>\n \n #include \"failsafe_private.h\"\n \n@@ -628,6 +629,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)\n \t\trte_eth_dev_default_mac_addr_set(PORT_ID(sdev), mac_addr);\n }\n \n+static int\n+fs_filter_ctrl(struct rte_eth_dev *dev,\n+\t\tenum rte_filter_type type,\n+\t\tenum rte_filter_op op,\n+\t\tvoid *arg)\n+{\n+\tstruct sub_device *sdev;\n+\tuint8_t i;\n+\tint ret;\n+\n+\tif (type == RTE_ETH_FILTER_GENERIC &&\n+\t op == RTE_ETH_FILTER_GET) {\n+\t\t*(const void **)arg = &fs_flow_ops;\n+\t\treturn 0;\n+\t}\n+\tFOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {\n+\t\tDEBUG(\"Calling rte_eth_dev_filter_ctrl on sub_device %d\", i);\n+\t\tret = rte_eth_dev_filter_ctrl(PORT_ID(sdev), type, op, arg);\n+\t\tif (ret) {\n+\t\t\tERROR(\"Operation rte_eth_dev_filter_ctrl failed for sub_device %d\"\n+\t\t\t \" with error %d\", i, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n const struct eth_dev_ops failsafe_ops = {\n \t.dev_configure = fs_dev_configure,\n \t.dev_start = fs_dev_start,\n@@ -655,4 +683,5 @@ const struct eth_dev_ops failsafe_ops = {\n \t.mac_addr_remove = fs_mac_addr_remove,\n \t.mac_addr_add = fs_mac_addr_add,\n \t.mac_addr_set = fs_mac_addr_set,\n+\t.filter_ctrl = fs_filter_ctrl,\n };\ndiff --git a/drivers/net/failsafe/failsafe_private.h b/drivers/net/failsafe/failsafe_private.h\nindex 554d7a3..f40ea2f 100644\n--- a/drivers/net/failsafe/failsafe_private.h\n+++ b/drivers/net/failsafe/failsafe_private.h\n@@ -34,6 +34,8 @@\n #ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_\n #define _RTE_ETH_FAILSAFE_PRIVATE_H_\n \n+#include <sys/queue.h>\n+\n #include <rte_dev.h>\n #include <rte_ethdev.h>\n #include <rte_devargs.h>\n@@ -72,6 +74,14 @@ struct txq {\n \tstruct rte_eth_txq_info info;\n };\n \n+struct rte_flow {\n+\tTAILQ_ENTRY(rte_flow) next;\n+\t/* sub_flows */\n+\tstruct rte_flow *flows[FAILSAFE_MAX_ETHPORTS];\n+\t/* flow description for synchronization */\n+\tstruct rte_flow_desc *fd;\n+};\n+\n enum dev_state {\n \tDEV_UNDEFINED = 0,\n \tDEV_PARSED,\n@@ -86,6 +96,7 @@ struct sub_device {\n \tstruct rte_bus *bus;\n \tstruct rte_device *dev;\n \tstruct rte_eth_dev *edev;\n+\tuint8_t sid;\n \t/* Device state machine */\n \tenum dev_state state;\n \t/* Some device are defined as a command line */\n@@ -104,6 +115,8 @@ struct fs_priv {\n \tuint8_t subs_tail; /* first invalid */\n \tuint8_t subs_tx; /* current emitting device */\n \tuint8_t current_probed;\n+\t/* flow mapping */\n+\tTAILQ_HEAD(sub_flows, rte_flow) flow_list;\n \t/* current number of mac_addr slots allocated. */\n \tuint32_t nb_mac_addr;\n \tstruct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR];\n@@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);\n \n extern const char pmd_failsafe_driver_name[];\n extern const struct eth_dev_ops failsafe_ops;\n+extern const struct rte_flow_ops fs_flow_ops;\n extern uint64_t hotplug_poll;\n extern int mac_from_arg;\n \n@@ -170,6 +184,10 @@ extern int mac_from_arg;\n #define PORT_ID(sdev) \\\n \t(ETH(sdev)->data->port_id)\n \n+/* sdev: (struct sub_device *) */\n+#define SUB_ID(sdev) \\\n+\t((sdev)->sid)\n+\n /**\n * Stateful iterator construct over fail-safe sub-devices:\n * s: (struct sub_device *), iterator\n", "prefixes": [ "dpdk-dev", "v6", "18/23" ] }{ "id": 26612, "url": "