get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 126913,
    "url": "https://patches.dpdk.org/api/patches/126913/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/168431455219.558450.14986601389394385835.stgit@ebuild.local/",
    "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": "<168431455219.558450.14986601389394385835.stgit@ebuild.local>",
    "list_archive_url": "https://inbox.dpdk.org/dev/168431455219.558450.14986601389394385835.stgit@ebuild.local",
    "date": "2023-05-17T09:09:13",
    "name": "[v3,4/4] vhost: add device op to offload the interrupt kick",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "d21ec4a081c17396c2c00ba208bde5ef802dc3f0",
    "submitter": {
        "id": 672,
        "url": "https://patches.dpdk.org/api/people/672/?format=api",
        "name": "Eelco Chaudron",
        "email": "echaudro@redhat.com"
    },
    "delegate": {
        "id": 2642,
        "url": "https://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/168431455219.558450.14986601389394385835.stgit@ebuild.local/mbox/",
    "series": [
        {
            "id": 28022,
            "url": "https://patches.dpdk.org/api/series/28022/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=28022",
            "date": "2023-05-17T09:08:30",
            "name": "vhost: add device op to offload the interrupt kick",
            "version": 3,
            "mbox": "https://patches.dpdk.org/series/28022/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/126913/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/126913/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 A621942B2A;\n\tWed, 17 May 2023 11:09:22 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 2F2A142D42;\n\tWed, 17 May 2023 11:09:19 +0200 (CEST)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by mails.dpdk.org (Postfix) with ESMTP id 1947E42D3A\n for <dev@dpdk.org>; Wed, 17 May 2023 11:09:18 +0200 (CEST)",
            "from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com\n [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n us-mta-414-XsoAaRK0P5Ozaqly7QqM8Q-1; Wed, 17 May 2023 05:09:16 -0400",
            "from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com\n [10.11.54.7])\n (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n (No client certificate requested)\n by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0177184AF31;\n Wed, 17 May 2023 09:09:16 +0000 (UTC)",
            "from ebuild.redhat.com (unknown [10.39.195.120])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 3778C14171C0;\n Wed, 17 May 2023 09:09:15 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1684314557;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=ZDF3QMO8cn3elD20Y0P+iBVGYCEI/QDhL/8POYxdPnM=;\n b=ATEfUD2AvpMCb3RUOLusdqU+S61qYsBU2wG1UBy55JKuK/Dip1UJtfuWqwJi09Hjdp/Z2K\n RKh6WS6vHRbYSACcEWLWf7bCUfEQgpQEiCHLFRmdFqHD1qiAuQVQCO8F7sk0sYLRkukrji\n 3iqLNjM6bUee/5J2N3J+hkycLl3pg/o=",
        "X-MC-Unique": "XsoAaRK0P5Ozaqly7QqM8Q-1",
        "From": "Eelco Chaudron <echaudro@redhat.com>",
        "To": "maxime.coquelin@redhat.com, chenbo.xia@intel.com,\n david.marchand@redhat.com",
        "Cc": "dev@dpdk.org",
        "Subject": "[PATCH v3 4/4] vhost: add device op to offload the interrupt kick",
        "Date": "Wed, 17 May 2023 11:09:13 +0200",
        "Message-Id": "<168431455219.558450.14986601389394385835.stgit@ebuild.local>",
        "In-Reply-To": "<168431450017.558450.16680518469610688737.stgit@ebuild.local>",
        "References": "<168431450017.558450.16680518469610688737.stgit@ebuild.local>",
        "User-Agent": "StGit/1.5",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.1 on 10.11.54.7",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "8bit",
        "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"
    },
    "content": "This patch adds an operation callback which gets called every time the\nlibrary wants to call eventfd_write(). This eventfd_write() call could\nresult in a system call, which could potentially block the PMD thread.\n\nThe callback function can decide whether it's ok to handle the\neventfd_write() now or have the newly introduced function,\nrte_vhost_notify_guest(), called at a later time.\n\nThis can be used by 3rd party applications, like OVS, to avoid system\ncalls being called as part of the PMD threads.\n\nSigned-off-by: Eelco Chaudron <echaudro@redhat.com>\n---\n lib/vhost/meson.build |    2 ++\n lib/vhost/rte_vhost.h |   23 +++++++++++++++++-\n lib/vhost/socket.c    |   63 ++++++++++++++++++++++++++++++++++++++++++++++---\n lib/vhost/version.map |    9 +++++++\n lib/vhost/vhost.c     |   38 ++++++++++++++++++++++++++++++\n lib/vhost/vhost.h     |   58 ++++++++++++++++++++++++++++++++-------------\n 6 files changed, 171 insertions(+), 22 deletions(-)",
    "diff": "diff --git a/lib/vhost/meson.build b/lib/vhost/meson.build\nindex 0d1abf6283..05679447db 100644\n--- a/lib/vhost/meson.build\n+++ b/lib/vhost/meson.build\n@@ -38,3 +38,5 @@ driver_sdk_headers = files(\n         'vdpa_driver.h',\n )\n deps += ['ethdev', 'cryptodev', 'hash', 'pci', 'dmadev']\n+\n+use_function_versioning = true\ndiff --git a/lib/vhost/rte_vhost.h b/lib/vhost/rte_vhost.h\nindex 58a5d4be92..7a10bc36cf 100644\n--- a/lib/vhost/rte_vhost.h\n+++ b/lib/vhost/rte_vhost.h\n@@ -298,7 +298,13 @@ struct rte_vhost_device_ops {\n \t */\n \tvoid (*guest_notified)(int vid);\n \n-\tvoid *reserved[1]; /**< Reserved for future extension */\n+\t/**\n+\t * If this callback is registered, notification to the guest can\n+\t * be handled by the front-end calling rte_vhost_notify_guest().\n+\t * If it's not handled, 'false' should be returned. This can be used\n+\t * to remove the \"slow\" eventfd_write() syscall from the datapath.\n+\t */\n+\tbool (*guest_notify)(int vid, uint16_t queue_id);\n };\n \n /**\n@@ -433,6 +439,21 @@ void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,\n \n int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice.\n+ *\n+ * Inject the offloaded interrupt into the vhost device's queue. For more\n+ * details see the 'guest_notify' vhost device operation.\n+ *\n+ * @param vid\n+ *  vhost device ID\n+ * @param queue_id\n+ *  virtio queue index\n+ */\n+__rte_experimental\n+void rte_vhost_notify_guest(int vid, uint16_t queue_id);\n+\n /**\n  * Register vhost driver. path could be different for multiple\n  * instance support.\ndiff --git a/lib/vhost/socket.c b/lib/vhost/socket.c\nindex 669c322e12..f2c02075fe 100644\n--- a/lib/vhost/socket.c\n+++ b/lib/vhost/socket.c\n@@ -15,6 +15,7 @@\n #include <fcntl.h>\n #include <pthread.h>\n \n+#include <rte_function_versioning.h>\n #include <rte_log.h>\n \n #include \"fd_man.h\"\n@@ -59,6 +60,7 @@ struct vhost_user_socket {\n \tstruct rte_vdpa_device *vdpa_dev;\n \n \tstruct rte_vhost_device_ops const *notify_ops;\n+\tstruct rte_vhost_device_ops *malloc_notify_ops;\n };\n \n struct vhost_user_connection {\n@@ -846,6 +848,11 @@ vhost_user_socket_mem_free(struct vhost_user_socket *vsocket)\n \t\tvsocket->path = NULL;\n \t}\n \n+\tif (vsocket && vsocket->malloc_notify_ops) {\n+\t\tfree(vsocket->malloc_notify_ops);\n+\t\tvsocket->malloc_notify_ops = NULL;\n+\t}\n+\n \tif (vsocket) {\n \t\tfree(vsocket);\n \t\tvsocket = NULL;\n@@ -1099,21 +1106,69 @@ rte_vhost_driver_unregister(const char *path)\n /*\n  * Register ops so that we can add/remove device to data core.\n  */\n-int\n-rte_vhost_driver_callback_register(const char *path,\n-\tstruct rte_vhost_device_ops const * const ops)\n+static int\n+vhost_driver_callback_register(const char *path,\n+\tstruct rte_vhost_device_ops const * const ops,\n+\tstruct rte_vhost_device_ops *malloc_ops)\n {\n \tstruct vhost_user_socket *vsocket;\n \n \tpthread_mutex_lock(&vhost_user.mutex);\n \tvsocket = find_vhost_user_socket(path);\n-\tif (vsocket)\n+\tif (vsocket) {\n \t\tvsocket->notify_ops = ops;\n+\t\tfree(vsocket->malloc_notify_ops);\n+\t\tvsocket->malloc_notify_ops = malloc_ops;\n+\t}\n \tpthread_mutex_unlock(&vhost_user.mutex);\n \n \treturn vsocket ? 0 : -1;\n }\n \n+int __vsym\n+rte_vhost_driver_callback_register_v24(const char *path,\n+\tstruct rte_vhost_device_ops const * const ops)\n+{\n+\treturn vhost_driver_callback_register(path, ops, NULL);\n+}\n+\n+int __vsym\n+rte_vhost_driver_callback_register_v23(const char *path,\n+\tstruct rte_vhost_device_ops const * const ops)\n+{\n+\tint ret;\n+\n+\t/*\n+\t * Although the ops structure is a const structure, we do need to\n+\t * override the guest_notify operation. This is because with the\n+\t * previous APIs it was \"reserved\" and if any garbage value was passed,\n+\t * it could crash the application.\n+\t */\n+\tif (ops && !ops->guest_notify) {\n+\t\tstruct rte_vhost_device_ops *new_ops;\n+\n+\t\tnew_ops = malloc(sizeof(*new_ops));\n+\t\tif (new_ops == NULL)\n+\t\t\treturn -1;\n+\n+\t\tmemcpy(new_ops, ops, sizeof(*new_ops));\n+\t\tnew_ops->guest_notify = NULL;\n+\n+\t\tret = vhost_driver_callback_register(path, new_ops, new_ops);\n+\t} else {\n+\t\tret = vhost_driver_callback_register(path, ops, NULL);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/* Mark the v23 function as the old version, and v24 as the default version. */\n+VERSION_SYMBOL(rte_vhost_driver_callback_register, _v23, 23);\n+BIND_DEFAULT_SYMBOL(rte_vhost_driver_callback_register, _v24, 24);\n+MAP_STATIC_SYMBOL(int rte_vhost_driver_callback_register(const char *path,\n+\t\tstruct rte_vhost_device_ops const * const ops),\n+\t\trte_vhost_driver_callback_register_v24);\n+\n struct rte_vhost_device_ops const *\n vhost_driver_callback_get(const char *path)\n {\ndiff --git a/lib/vhost/version.map b/lib/vhost/version.map\nindex d322a4a888..7bcbfd12cf 100644\n--- a/lib/vhost/version.map\n+++ b/lib/vhost/version.map\n@@ -64,6 +64,12 @@ DPDK_23 {\n \tlocal: *;\n };\n \n+DPDK_24 {\n+\tglobal:\n+\n+\trte_vhost_driver_callback_register;\n+} DPDK_23;\n+\n EXPERIMENTAL {\n \tglobal:\n \n@@ -98,6 +104,9 @@ EXPERIMENTAL {\n \t# added in 22.11\n \trte_vhost_async_dma_unconfigure;\n \trte_vhost_vring_call_nonblock;\n+\n+        # added in 23.07\n+\trte_vhost_notify_guest;\n };\n \n INTERNAL {\ndiff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c\nindex 8ff6434c93..79e88f986e 100644\n--- a/lib/vhost/vhost.c\n+++ b/lib/vhost/vhost.c\n@@ -44,6 +44,10 @@ static const struct vhost_vq_stats_name_off vhost_vq_stat_strings[] = {\n \t{\"size_1024_1518_packets\", offsetof(struct vhost_virtqueue, stats.size_bins[6])},\n \t{\"size_1519_max_packets\",  offsetof(struct vhost_virtqueue, stats.size_bins[7])},\n \t{\"guest_notifications\",    offsetof(struct vhost_virtqueue, stats.guest_notifications)},\n+\t{\"guest_notifications_offloaded\", offsetof(struct vhost_virtqueue,\n+\t\tstats.guest_notifications_offloaded)},\n+\t{\"guest_notifications_error\", offsetof(struct vhost_virtqueue,\n+\t\tstats.guest_notifications_error)},\n \t{\"iotlb_hits\",             offsetof(struct vhost_virtqueue, stats.iotlb_hits)},\n \t{\"iotlb_misses\",           offsetof(struct vhost_virtqueue, stats.iotlb_misses)},\n \t{\"inflight_submitted\",     offsetof(struct vhost_virtqueue, stats.inflight_submitted)},\n@@ -1467,6 +1471,40 @@ rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable)\n \treturn ret;\n }\n \n+void\n+rte_vhost_notify_guest(int vid, uint16_t queue_id)\n+{\n+\tstruct virtio_net *dev = get_device(vid);\n+\tstruct vhost_virtqueue *vq;\n+\n+\tif (!dev ||  queue_id >= VHOST_MAX_VRING)\n+\t\treturn;\n+\n+\tvq = dev->virtqueue[queue_id];\n+\tif (!vq)\n+\t\treturn;\n+\n+\trte_rwlock_read_lock(&vq->access_lock);\n+\n+\tif (vq->callfd >= 0) {\n+\t\tint ret = eventfd_write(vq->callfd, (eventfd_t)1);\n+\n+\t\tif (ret) {\n+\t\t\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n+\t\t\t\t__atomic_fetch_add(&vq->stats.guest_notifications_error,\n+\t\t\t\t\t1, __ATOMIC_RELAXED);\n+\t\t} else {\n+\t\t\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n+\t\t\t\t__atomic_fetch_add(&vq->stats.guest_notifications,\n+\t\t\t\t\t1, __ATOMIC_RELAXED);\n+\t\t\tif (dev->notify_ops->guest_notified)\n+\t\t\t\tdev->notify_ops->guest_notified(dev->vid);\n+\t\t}\n+\t}\n+\n+\trte_rwlock_read_unlock(&vq->access_lock);\n+}\n+\n void\n rte_vhost_log_write(int vid, uint64_t addr, uint64_t len)\n {\ndiff --git a/lib/vhost/vhost.h b/lib/vhost/vhost.h\nindex 23a4e2b1a7..8ad53e9bb5 100644\n--- a/lib/vhost/vhost.h\n+++ b/lib/vhost/vhost.h\n@@ -141,6 +141,8 @@ struct virtqueue_stats {\n \tuint64_t inflight_completed;\n \t/* Counters below are atomic, and should be incremented as such. */\n \tuint64_t guest_notifications;\n+\tuint64_t guest_notifications_offloaded;\n+\tuint64_t guest_notifications_error;\n };\n \n /**\n@@ -884,6 +886,34 @@ vhost_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)\n \treturn (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);\n }\n \n+static __rte_always_inline void\n+vhost_vring_inject_irq(struct virtio_net *dev, struct vhost_virtqueue *vq)\n+{\n+\tint ret;\n+\n+\tif (dev->notify_ops->guest_notify &&\n+\t    dev->notify_ops->guest_notify(dev->vid, vq->index)) {\n+\t\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n+\t\t\t__atomic_fetch_add(&vq->stats.guest_notifications_offloaded,\n+\t\t\t\t1, __ATOMIC_RELAXED);\n+\t\treturn;\n+\t}\n+\n+\tret = eventfd_write(vq->callfd, (eventfd_t) 1);\n+\tif (ret) {\n+\t\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n+\t\t\t__atomic_fetch_add(&vq->stats.guest_notifications_error,\n+\t\t\t\t1, __ATOMIC_RELAXED);\n+\t\treturn;\n+\t}\n+\n+\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n+\t\t__atomic_fetch_add(&vq->stats.guest_notifications,\n+\t\t\t1, __ATOMIC_RELAXED);\n+\tif (dev->notify_ops->guest_notified)\n+\t\tdev->notify_ops->guest_notified(dev->vid);\n+}\n+\n static __rte_always_inline void\n vhost_vring_call_split(struct virtio_net *dev, struct vhost_virtqueue *vq)\n {\n@@ -906,23 +936,13 @@ vhost_vring_call_split(struct virtio_net *dev, struct vhost_virtqueue *vq)\n \t\tif ((vhost_need_event(vhost_used_event(vq), new, old) ||\n \t\t\t\t\tunlikely(!signalled_used_valid)) &&\n \t\t\t\tvq->callfd >= 0) {\n-\t\t\teventfd_write(vq->callfd, (eventfd_t) 1);\n-\t\t\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n-\t\t\t\t__atomic_fetch_add(&vq->stats.guest_notifications,\n-\t\t\t\t\t1, __ATOMIC_RELAXED);\n-\t\t\tif (dev->notify_ops->guest_notified)\n-\t\t\t\tdev->notify_ops->guest_notified(dev->vid);\n+\t\t\tvhost_vring_inject_irq(dev, vq);\n \t\t}\n \t} else {\n \t\t/* Kick the guest if necessary. */\n \t\tif (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)\n \t\t\t\t&& (vq->callfd >= 0)) {\n-\t\t\teventfd_write(vq->callfd, (eventfd_t)1);\n-\t\t\tif (dev->flags & VIRTIO_DEV_STATS_ENABLED)\n-\t\t\t\t__atomic_fetch_add(&vq->stats.guest_notifications,\n-\t\t\t\t\t1, __ATOMIC_RELAXED);\n-\t\t\tif (dev->notify_ops->guest_notified)\n-\t\t\t\tdev->notify_ops->guest_notified(dev->vid);\n+\t\t\tvhost_vring_inject_irq(dev, vq);\n \t\t}\n \t}\n }\n@@ -974,11 +994,8 @@ vhost_vring_call_packed(struct virtio_net *dev, struct vhost_virtqueue *vq)\n \tif (vhost_need_event(off, new, old))\n \t\tkick = true;\n kick:\n-\tif (kick && vq->callfd >= 0) {\n-\t\teventfd_write(vq->callfd, (eventfd_t)1);\n-\t\tif (dev->notify_ops->guest_notified)\n-\t\t\tdev->notify_ops->guest_notified(dev->vid);\n-\t}\n+\tif (kick && vq->callfd >= 0)\n+\t\tvhost_vring_inject_irq(dev, vq);\n }\n \n static __rte_always_inline void\n@@ -1017,4 +1034,11 @@ mbuf_is_consumed(struct rte_mbuf *m)\n \n uint64_t hua_to_alignment(struct rte_vhost_memory *mem, void *ptr);\n void mem_set_dump(void *ptr, size_t size, bool enable, uint64_t alignment);\n+\n+/* Versioned functions */\n+int rte_vhost_driver_callback_register_v23(const char *path,\n+\tstruct rte_vhost_device_ops const * const ops);\n+int rte_vhost_driver_callback_register_v24(const char *path,\n+\tstruct rte_vhost_device_ops const * const ops);\n+\n #endif /* _VHOST_NET_CDEV_H_ */\n",
    "prefixes": [
        "v3",
        "4/4"
    ]
}