get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1525720,
    "url": "http://patchwork.ozlabs.org/api/patches/1525720/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/2417516d527007c83a7983041813947124b9c40b.1631094144.git.grive@u256.net/",
    "project": {
        "id": 47,
        "url": "http://patchwork.ozlabs.org/api/projects/47/?format=api",
        "name": "Open vSwitch",
        "link_name": "openvswitch",
        "list_id": "ovs-dev.openvswitch.org",
        "list_email": "ovs-dev@openvswitch.org",
        "web_url": "http://openvswitch.org/",
        "scm_url": "git@github.com:openvswitch/ovs.git",
        "webscm_url": "https://github.com/openvswitch/ovs",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<2417516d527007c83a7983041813947124b9c40b.1631094144.git.grive@u256.net>",
    "list_archive_url": null,
    "date": "2021-09-08T09:47:38",
    "name": "[ovs-dev,v5,14/27] netdev-offload: Add multi-thread API",
    "commit_ref": "62c2d8a67543c8694dde828a2dc813105d973c23",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "67e624a2f936f059a19faa1640534060c2f0152e",
    "submitter": {
        "id": 78795,
        "url": "http://patchwork.ozlabs.org/api/people/78795/?format=api",
        "name": "Gaetan Rivet",
        "email": "grive@u256.net"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/2417516d527007c83a7983041813947124b9c40b.1631094144.git.grive@u256.net/mbox/",
    "series": [
        {
            "id": 261424,
            "url": "http://patchwork.ozlabs.org/api/series/261424/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=261424",
            "date": "2021-09-08T09:47:24",
            "name": "dpif-netdev: Parallel offload processing",
            "version": 5,
            "mbox": "http://patchwork.ozlabs.org/series/261424/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1525720/comments/",
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/1525720/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "ovs-dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "ovs-dev@lists.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=u256.net header.i=@u256.net header.a=rsa-sha256\n header.s=fm2 header.b=J1tJSd23;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=messagingengine.com header.i=@messagingengine.com\n header.a=rsa-sha256 header.s=fm3 header.b=G984bcLJ;\n\tdkim-atps=neutral",
            "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN>)",
            "smtp2.osuosl.org (amavisd-new);\n dkim=pass (2048-bit key) header.d=u256.net header.b=\"J1tJSd23\";\n dkim=pass (2048-bit key) header.d=messagingengine.com\n header.b=\"G984bcLJ\""
        ],
        "Received": [
            "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4H4HQj4wVsz9sW8\n\tfor <incoming@patchwork.ozlabs.org>; Wed,  8 Sep 2021 19:49:01 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 58A5E613C6;\n\tWed,  8 Sep 2021 09:48:59 +0000 (UTC)",
            "from smtp3.osuosl.org ([127.0.0.1])\n\tby localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id GTbQcbCOUkBh; Wed,  8 Sep 2021 09:48:58 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 69E81613BA;\n\tWed,  8 Sep 2021 09:48:57 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 4E068C001C;\n\tWed,  8 Sep 2021 09:48:57 +0000 (UTC)",
            "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 07596C000D\n for <ovs-dev@openvswitch.org>; Wed,  8 Sep 2021 09:48:56 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 51CB1404DB\n for <ovs-dev@openvswitch.org>; Wed,  8 Sep 2021 09:48:25 +0000 (UTC)",
            "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id eOcEpFDjxY-r for <ovs-dev@openvswitch.org>;\n Wed,  8 Sep 2021 09:48:24 +0000 (UTC)",
            "from wout3-smtp.messagingengine.com (wout3-smtp.messagingengine.com\n [64.147.123.19])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 5CA2D406C7\n for <ovs-dev@openvswitch.org>; Wed,  8 Sep 2021 09:48:24 +0000 (UTC)",
            "from compute5.internal (compute5.nyi.internal [10.202.2.45])\n by mailout.west.internal (Postfix) with ESMTP id C1E3032009DD;\n Wed,  8 Sep 2021 05:48:23 -0400 (EDT)",
            "from mailfrontend2 ([10.202.2.163])\n by compute5.internal (MEProxy); Wed, 08 Sep 2021 05:48:24 -0400",
            "by mail.messagingengine.com (Postfix) with ESMTPA; Wed,\n 8 Sep 2021 05:48:22 -0400 (EDT)"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "from auto-whitelisted by SQLgrey-1.8.0",
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=u256.net; h=from\n :to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding; s=fm2; bh=SgCWR/u0RXg8h\n UGBAzMEITPCzlScpYGPNHI0iB2sGks=; b=J1tJSd231ygekBKRK2BV4SNWaxgKX\n b3Mw8jNVA3BMTWmFcrhSFd0yV33nyEQCGQYdAnzEEGK2IZNEpr+dxf+JzcymCqAP\n HufA1kFu06pPCDBjekuOuznzZLcmWipr/qy2p3LQLLNxo7mN5w5Q/tmgymP73WtI\n abTSqme+medMgIQKd5r8c8kqhckULMycwTz0lrpF9KxPWtySMkshnogia34mh3b1\n h+lOw5X/qF3WTWcJcGwbf/AXGutjzpGx92BGb9dgSS3XK47bvbCxWQVJCNVt9H5g\n LoospdoekPtYqwc7eznIkM9u8vofu8BifwQ31FFac5Vspl/Q0RkirCHdA==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=\n messagingengine.com; h=cc:content-transfer-encoding:date:from\n :in-reply-to:message-id:mime-version:references:subject:to\n :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=\n fm3; bh=SgCWR/u0RXg8hUGBAzMEITPCzlScpYGPNHI0iB2sGks=; b=G984bcLJ\n GNS9KjpUHzTaGxV39rCIc17Ee5sj5Jc5cd7Ok4adnDCFoa1n+wySdOZ5R1p4ANPG\n Zm2hIVk9bVfQUM90iNRqLcxgZ29pXC/PVBybKzOj1XiqhnZEAbTdV0bwSCJ2PSMC\n 90gfJzI4C7c4Js9zi8Q34cdyUomJWsIbqhGn1/x51HJoO9pTt8TGdYt+rQ0/plo6\n Mxzu8kpLJ+78Dz9/abMEvkFialZP5xzbLSYMTZF1j+tUp32AvD5rZTLRTY/NKPpd\n DSmd2OLKPHqpRK7Y8wRyvgpr7C6vB3406Fi0dtVQr9YXiLqgLhRObIYRKYEQNhks\n LjfhliDkJ76ZzQ=="
        ],
        "X-ME-Sender": "<xms:54Y4YR7dNE_GqIcPh6GGNtiRCzaTHQ5eiufBhz3HbQrtXXvuHmr7Jw>\n <xme:54Y4Ye41yVtUDEj0aGx21kGrCPFwG4UgA1G3XEIN5eu0vdkY4eHVp5BHBSmG1z2Lb\n 5k6odz2BXI6kItuiVw>",
        "X-ME-Received": "\n <xmr:54Y4YYci6O1EZjf679zlBgl9lywpE73tyPcrFiybuKFZjPeJkJD2ZWgbeSkiWtFkUZl4mik-HzmsyGIN2luXGr6jcw>",
        "X-ME-Proxy-Cause": "\n gggruggvucftvghtrhhoucdtuddrgedvtddrudefjedgudekucetufdoteggodetrfdotf\n fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen\n uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne\n cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefirggvthgr\n nhcutfhivhgvthcuoehgrhhivhgvsehuvdehiedrnhgvtheqnecuggftrfgrthhtvghrnh\n ephefgveffkeetheetfeeifedvheelfeejfeehveduteejhfekuedtkeeiuedvteehnecu\n vehluhhsthgvrhfuihiivgepvdenucfrrghrrghmpehmrghilhhfrhhomhepghhrihhvvg\n esuhdvheeirdhnvght",
        "X-ME-Proxy": "<xmx:54Y4YaJpMwZttidIomb_g8z9hdTN9ZgWydE6B3laZUwt5KkXV8CizA>\n <xmx:54Y4YVJKZ-5Bu47owo6JjJRiddISTyDMCN1fezYJRFm90hCu4eN0Fw>\n <xmx:54Y4YTztPm8Jh5W2ZoJx5Xv2LakcQqLRyKzGcNpfnDAvu2I3OJ1jgw>\n <xmx:54Y4YThH_bj1NtY2Th8S_6An7exd6XwzRHKOvLNeuyFKFKwSOMKlvA>",
        "From": "Gaetan Rivet <grive@u256.net>",
        "To": "ovs-dev@openvswitch.org",
        "Date": "Wed,  8 Sep 2021 11:47:38 +0200",
        "Message-Id": "\n <2417516d527007c83a7983041813947124b9c40b.1631094144.git.grive@u256.net>",
        "X-Mailer": "git-send-email 2.31.1",
        "In-Reply-To": "<cover.1631094144.git.grive@u256.net>",
        "References": "<cover.1631094144.git.grive@u256.net>",
        "MIME-Version": "1.0",
        "Cc": "Eli Britstein <elibr@nvidia.com>,\n Maxime Coquelin <maxime.coquelin@redhat.com>",
        "Subject": "[ovs-dev] [PATCH v5 14/27] netdev-offload: Add multi-thread API",
        "X-BeenThere": "ovs-dev@openvswitch.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "<ovs-dev.openvswitch.org>",
        "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>",
        "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>",
        "List-Post": "<mailto:ovs-dev@openvswitch.org>",
        "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>",
        "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "Expose functions reporting user configuration of offloading threads, as\nwell as utility functions for multithreading.\n\nThis will only expose the configuration knob to the user, while no\ndatapath will implement the multiple thread request.\n\nThis will allow implementations to use this API for offload thread\nmanagement in relevant layers before enabling the actual dataplane\nimplementation.\n\nThe offload thread ID is lazily allocated and can as such be in a\ndifferent order than the offload thread start sequence.\n\nThe RCU thread will sometime access hardware-offload objects from\na provider for reclamation purposes.  In such case, it will get\na default offload thread ID of 0. Care must be taken that using\nthis thread ID is safe concurrently with the offload threads.\n\nSigned-off-by: Gaetan Rivet <grive@u256.net>\nReviewed-by: Eli Britstein <elibr@nvidia.com>\nReviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>\n---\n lib/netdev-offload-provider.h |  1 +\n lib/netdev-offload.c          | 88 ++++++++++++++++++++++++++++++++++-\n lib/netdev-offload.h          | 19 ++++++++\n vswitchd/vswitch.xml          | 16 +++++++\n 4 files changed, 122 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h\nindex bc52a3f61..8ff2de983 100644\n--- a/lib/netdev-offload-provider.h\n+++ b/lib/netdev-offload-provider.h\n@@ -84,6 +84,7 @@ struct netdev_flow_api {\n                     struct dpif_flow_stats *);\n \n     /* Get the number of flows offloaded to netdev.\n+     * 'n_flows' is an array of counters, one per offload thread.\n      * Return 0 if successful, otherwise returns a positive errno value. */\n     int (*flow_get_n_flows)(struct netdev *, uint64_t *n_flows);\n \ndiff --git a/lib/netdev-offload.c b/lib/netdev-offload.c\nindex 5ddd4d01d..fc5f815d0 100644\n--- a/lib/netdev-offload.c\n+++ b/lib/netdev-offload.c\n@@ -60,6 +60,12 @@ VLOG_DEFINE_THIS_MODULE(netdev_offload);\n \n static bool netdev_flow_api_enabled = false;\n \n+#define DEFAULT_OFFLOAD_THREAD_NB 1\n+#define MAX_OFFLOAD_THREAD_NB 10\n+\n+static unsigned int offload_thread_nb = DEFAULT_OFFLOAD_THREAD_NB;\n+DEFINE_EXTERN_PER_THREAD_DATA(netdev_offload_thread_id, OVSTHREAD_ID_UNSET);\n+\n /* Protects 'netdev_flow_apis'.  */\n static struct ovs_mutex netdev_flow_api_provider_mutex = OVS_MUTEX_INITIALIZER;\n \n@@ -448,6 +454,64 @@ netdev_is_flow_api_enabled(void)\n     return netdev_flow_api_enabled;\n }\n \n+unsigned int\n+netdev_offload_thread_nb(void)\n+{\n+    return offload_thread_nb;\n+}\n+\n+unsigned int\n+netdev_offload_ufid_to_thread_id(const ovs_u128 ufid)\n+{\n+    uint32_t ufid_hash;\n+\n+    if (netdev_offload_thread_nb() == 1) {\n+        return 0;\n+    }\n+\n+    ufid_hash = hash_words64_inline(\n+            (const uint64_t [2]){ ufid.u64.lo,\n+                                  ufid.u64.hi }, 2, 1);\n+    return ufid_hash % netdev_offload_thread_nb();\n+}\n+\n+unsigned int\n+netdev_offload_thread_init(void)\n+{\n+    static atomic_count next_id = ATOMIC_COUNT_INIT(0);\n+    bool thread_is_hw_offload;\n+    bool thread_is_rcu;\n+\n+    thread_is_hw_offload = !strncmp(get_subprogram_name(),\n+                                    \"hw_offload\", strlen(\"hw_offload\"));\n+    thread_is_rcu = !strncmp(get_subprogram_name(), \"urcu\", strlen(\"urcu\"));\n+\n+    /* Panic if any other thread besides offload and RCU tries\n+     * to initialize their thread ID. */\n+    ovs_assert(thread_is_hw_offload || thread_is_rcu);\n+\n+    if (*netdev_offload_thread_id_get() == OVSTHREAD_ID_UNSET) {\n+        unsigned int id;\n+\n+        if (thread_is_rcu) {\n+            /* RCU will compete with other threads for shared object access.\n+             * Reclamation functions using a thread ID must be thread-safe.\n+             * For that end, and because RCU must consider all potential shared\n+             * objects anyway, its thread-id can be whichever, so return 0.\n+             */\n+            id = 0;\n+        } else {\n+            /* Only the actual offload threads have their own ID. */\n+            id = atomic_count_inc(&next_id);\n+        }\n+        /* Panic if any offload thread is getting a spurious ID. */\n+        ovs_assert(id < netdev_offload_thread_nb());\n+        return *netdev_offload_thread_id_get() = id;\n+    } else {\n+        return *netdev_offload_thread_id_get();\n+    }\n+}\n+\n void\n netdev_ports_flow_flush(const char *dpif_type)\n {\n@@ -660,7 +724,16 @@ netdev_ports_get_n_flows(const char *dpif_type, odp_port_t port_no,\n     ovs_rwlock_rdlock(&netdev_hmap_rwlock);\n     data = netdev_ports_lookup(port_no, dpif_type);\n     if (data) {\n-        ret = netdev_flow_get_n_flows(data->netdev, n_flows);\n+        uint64_t thread_n_flows[MAX_OFFLOAD_THREAD_NB] = {0};\n+        unsigned int tid;\n+\n+        ret = netdev_flow_get_n_flows(data->netdev, thread_n_flows);\n+        *n_flows = 0;\n+        if (!ret) {\n+            for (tid = 0; tid < netdev_offload_thread_nb(); tid++) {\n+                *n_flows += thread_n_flows[tid];\n+            }\n+        }\n     }\n     ovs_rwlock_unlock(&netdev_hmap_rwlock);\n     return ret;\n@@ -713,7 +786,18 @@ netdev_set_flow_api_enabled(const struct smap *ovs_other_config)\n         if (ovsthread_once_start(&once)) {\n             netdev_flow_api_enabled = true;\n \n-            VLOG_INFO(\"netdev: Flow API Enabled\");\n+            offload_thread_nb = smap_get_ullong(ovs_other_config,\n+                                                \"n-offload-threads\",\n+                                                DEFAULT_OFFLOAD_THREAD_NB);\n+            if (offload_thread_nb > MAX_OFFLOAD_THREAD_NB) {\n+                VLOG_WARN(\"netdev: Invalid number of threads requested: %u\",\n+                          offload_thread_nb);\n+                offload_thread_nb = DEFAULT_OFFLOAD_THREAD_NB;\n+            }\n+\n+            VLOG_INFO(\"netdev: Flow API Enabled, using %u thread%s\",\n+                      offload_thread_nb,\n+                      offload_thread_nb > 1 ? \"s\" : \"\");\n \n #ifdef __linux__\n             tc_set_policy(smap_get_def(ovs_other_config, \"tc-policy\",\ndiff --git a/lib/netdev-offload.h b/lib/netdev-offload.h\nindex b0a0ead0f..b281d69c9 100644\n--- a/lib/netdev-offload.h\n+++ b/lib/netdev-offload.h\n@@ -21,6 +21,7 @@\n #include \"openvswitch/netdev.h\"\n #include \"openvswitch/types.h\"\n #include \"ovs-rcu.h\"\n+#include \"ovs-thread.h\"\n #include \"packets.h\"\n #include \"flow.h\"\n \n@@ -81,6 +82,24 @@ struct offload_info {\n     odp_port_t orig_in_port; /* Originating in_port for tnl flows. */\n };\n \n+DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, netdev_offload_thread_id);\n+\n+unsigned int netdev_offload_thread_nb(void);\n+unsigned int netdev_offload_thread_init(void);\n+unsigned int netdev_offload_ufid_to_thread_id(const ovs_u128 ufid);\n+\n+static inline unsigned int\n+netdev_offload_thread_id(void)\n+{\n+    unsigned int id = *netdev_offload_thread_id_get();\n+\n+    if (OVS_UNLIKELY(id == OVSTHREAD_ID_UNSET)) {\n+        id = netdev_offload_thread_init();\n+    }\n+\n+    return id;\n+}\n+\n int netdev_flow_flush(struct netdev *);\n int netdev_flow_dump_create(struct netdev *, struct netdev_flow_dump **dump,\n                             bool terse);\ndiff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml\nindex 026b5e2ca..1e7444920 100644\n--- a/vswitchd/vswitch.xml\n+++ b/vswitchd/vswitch.xml\n@@ -247,6 +247,22 @@\n         </p>\n       </column>\n \n+      <column name=\"other_config\" key=\"n-offload-threads\"\n+              type='{\"type\": \"integer\", \"minInteger\": 1, \"maxInteger\": 10}'>\n+        <p>\n+          Set this value to the number of threads created to manage hardware\n+          offloads.\n+        </p>\n+        <p>\n+          The default value is <code>1</code>. Changing this value requires\n+          restarting the daemon.\n+        </p>\n+        <p>\n+          This is only relevant if\n+          <ref column=\"other_config\" key=\"hw-offload\"/> is enabled.\n+        </p>\n+      </column>\n+\n       <column name=\"other_config\" key=\"tc-policy\"\n               type='{\"type\": \"string\",\n                      \"enum\": [\"set\", [\"none\", \"skip_sw\", \"skip_hw\"]]}'>\n",
    "prefixes": [
        "ovs-dev",
        "v5",
        "14/27"
    ]
}