get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2217625,
    "url": "http://patchwork.ozlabs.org/api/patches/2217625/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260330090944.1008027-6-lulu@redhat.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260330090944.1008027-6-lulu@redhat.com>",
    "list_archive_url": null,
    "date": "2026-03-30T08:58:13",
    "name": "[RFC,v3,5/7] net/filter-redirector: add AF_PACKET inject path",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "3e6a2b60fa253d4300b37c2edf8892448480c0a0",
    "submitter": {
        "id": 78960,
        "url": "http://patchwork.ozlabs.org/api/people/78960/?format=api",
        "name": "Cindy Lu",
        "email": "lulu@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260330090944.1008027-6-lulu@redhat.com/mbox/",
    "series": [
        {
            "id": 497984,
            "url": "http://patchwork.ozlabs.org/api/series/497984/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=497984",
            "date": "2026-03-30T08:58:09",
            "name": "net/filter: Add AF_PACKET support for vhost-net",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/497984/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2217625/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2217625/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=DKM4I1zy;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fklq91XbCz1xrn\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 30 Mar 2026 20:11:17 +1100 (AEDT)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1w78eO-0006T2-A4; Mon, 30 Mar 2026 05:11:12 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <lulu@redhat.com>) id 1w78dv-00069M-KY\n for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:49 -0400",
            "from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <lulu@redhat.com>) id 1w78dt-0000Q8-0i\n for qemu-devel@nongnu.org; Mon, 30 Mar 2026 05:10:42 -0400",
            "from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-497-OtkyH6U5P6-sJYQu2gy6JQ-1; Mon,\n 30 Mar 2026 05:10:36 -0400",
            "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 9D97A1944EB3; Mon, 30 Mar 2026 09:10:35 +0000 (UTC)",
            "from S2.redhat.com (unknown [10.72.112.39])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 6720B19560AB; Mon, 30 Mar 2026 09:10:32 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1774861840;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=b3CqbJi2MH8xVeq0Ual/M4Y93TyxFUpwdAas+AN4prc=;\n b=DKM4I1zy769AwH66BvsfmfgUS81ovGV0coxaXvskN4xCiWIq9k7avl9MZWwjYv+UoCoerR\n bHSIKJj01UG2W14KubgTbDC4fEcf8KW7op7WnO38zmU332eNEs/KS5xfrN2R98za10seVR\n WNAbapwj3V3rXLEhX5dkJgiJe8T/9BI=",
        "X-MC-Unique": "OtkyH6U5P6-sJYQu2gy6JQ-1",
        "X-Mimecast-MFC-AGG-ID": "OtkyH6U5P6-sJYQu2gy6JQ_1774861835",
        "From": "Cindy Lu <lulu@redhat.com>",
        "To": "lulu@redhat.com, mst@redhat.com, jasowang@redhat.com, zhangckid@gmail.com,\n lizhijian@fujitsu.com, jmarcin@redhat.com, qemu-devel@nongnu.org",
        "Subject": "[RFC v3 5/7] net/filter-redirector: add AF_PACKET inject path",
        "Date": "Mon, 30 Mar 2026 16:58:13 +0800",
        "Message-ID": "<20260330090944.1008027-6-lulu@redhat.com>",
        "In-Reply-To": "<20260330090944.1008027-1-lulu@redhat.com>",
        "References": "<20260330090944.1008027-1-lulu@redhat.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12",
        "Received-SPF": "pass client-ip=170.10.129.124; envelope-from=lulu@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com",
        "X-Spam_score_int": "27",
        "X-Spam_score": "2.7",
        "X-Spam_bar": "++",
        "X-Spam_report": "(2.7 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_SBL_CSS=3.335,\n RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1,\n SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no",
        "X-Spam_action": "no action",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "qemu development <qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "Allow redirector packets to be injected back into a vhost-backed TAP\nbackend without going through the normal peer queue.\n\nExport a redirector helper that sends an iov directly through the\nredirector's AF_PACKET inject socket, and teach qemu_netfilter_pass_to_next()\nto use it when the sender is backed by vhost. This lets the redirector\nreinject traffic into the TAP device even when the regular userspace path\nis bypassed by vhost.\n\nThe redirector chardev transport may carry an empty vnet header wrapper\nbefore the Ethernet frame. Detect the longest supported all-zero wrapper\nand strip it before sendmsg() so the AF_PACKET inject side always writes a\nraw L2 frame back to TAP.\n\nPropagate sendmsg() failures through ssize_t so the caller can report\npartial/failed injection cleanly.\n\nSigned-off-by: Cindy Lu <lulu@redhat.com>\n---\n include/net/filter.h |  6 +++\n net/filter-mirror.c  | 94 ++++++++++++++++++++++++++++++++++++++++++++\n net/filter.c         | 11 +++++-\n 3 files changed, 110 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/include/net/filter.h b/include/net/filter.h\nindex f0673c9163..68076a66ad 100644\n--- a/include/net/filter.h\n+++ b/include/net/filter.h\n@@ -91,6 +91,12 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,\n                                     int iovcnt,\n                                     void *opaque);\n \n+bool qemu_netfilter_redirector_inject_netdev(NetFilterState *nf,\n+                                             NetClientState *sender,\n+                                             const struct iovec *iov,\n+                                             int iovcnt,\n+                                             ssize_t *retp);\n+\n void colo_notify_filters_event(int event, Error **errp);\n \n #endif /* QEMU_NET_FILTER_H */\ndiff --git a/net/filter-mirror.c b/net/filter-mirror.c\nindex e114ddb7d1..165a7ee1ea 100644\n--- a/net/filter-mirror.c\n+++ b/net/filter-mirror.c\n@@ -74,6 +74,100 @@ typedef struct FilterSendCo {\n     int ret;\n } FilterSendCo;\n \n+static size_t filter_redirector_wrapped_vnet_hdr_len(const struct iovec *iov,\n+                                                     int iovcnt)\n+{\n+    static const size_t lens[] = {\n+        sizeof(struct virtio_net_hdr_v1_hash_tunnel),\n+        sizeof(struct virtio_net_hdr_v1_hash),\n+        sizeof(struct virtio_net_hdr_mrg_rxbuf),\n+        sizeof(struct virtio_net_hdr),\n+    };\n+    uint8_t hdr[sizeof(struct virtio_net_hdr_v1_hash_tunnel)] = { 0 };\n+    uint8_t zero[sizeof(hdr)] = { 0 };\n+    size_t total = iov_size(iov, iovcnt);\n+    size_t len;\n+    int i;\n+\n+    for (i = 0; i < ARRAY_SIZE(lens); i++) {\n+        len = lens[i];\n+        if (len >= total) {\n+            continue;\n+        }\n+        if (iov_to_buf(iov, iovcnt, 0, hdr, len) == len &&\n+            !memcmp(hdr, zero, len)) {\n+            return len;\n+        }\n+    }\n+\n+    return 0;\n+}\n+\n+\n+bool qemu_netfilter_redirector_inject_netdev(NetFilterState *nf,\n+                                             NetClientState *sender,\n+                                             const struct iovec *iov,\n+                                             int iovcnt,\n+                                             ssize_t *retp)\n+{\n+    MirrorState *s;\n+    struct iovec local_iov = { 0 };\n+    struct msghdr msg = {\n+        .msg_iov = (struct iovec *)iov,\n+        .msg_iovlen = iovcnt,\n+    };\n+    ssize_t ret;\n+    size_t size;\n+    size_t wrapped_vnet_hdr_len;\n+\n+    if (!object_dynamic_cast(OBJECT(nf), TYPE_FILTER_REDIRECTOR)) {\n+        return false;\n+    }\n+\n+    s = FILTER_REDIRECTOR(nf);\n+    if (s->out_netfd < 0 || !sender || sender != nf->netdev) {\n+        return false;\n+    }\n+\n+    wrapped_vnet_hdr_len = (!s->vnet_hdr && qemu_get_vnet_hdr_len(sender)) ?\n+                           filter_redirector_wrapped_vnet_hdr_len(iov, iovcnt) :\n+                           0;\n+    if (wrapped_vnet_hdr_len) {\n+        /*\n+         * Redirector chardev packets can carry an empty virtio-net header\n+         * before the Ethernet frame. Strip the longest supported wrapped\n+         * header before injecting the packet back to TAP.\n+         */\n+        local_iov.iov_len = iov_size(iov, iovcnt) - wrapped_vnet_hdr_len;\n+        local_iov.iov_base = g_malloc(local_iov.iov_len);\n+        iov_to_buf(iov, iovcnt, wrapped_vnet_hdr_len,\n+                   local_iov.iov_base,\n+                   local_iov.iov_len);\n+        msg.msg_iov = &local_iov;\n+        msg.msg_iovlen = 1;\n+    }\n+\n+    size = iov_size(iov, iovcnt);\n+    if (local_iov.iov_base) {\n+        size = local_iov.iov_len;\n+    }\n+    do {\n+        ret = sendmsg(s->out_netfd, &msg, 0);\n+    } while (ret < 0 && errno == EINTR);\n+\n+    if (ret < 0) {\n+        *retp = -errno;\n+    } else if (ret != size) {\n+        *retp = -EIO;\n+    } else {\n+        *retp = ret;\n+    }\n+\n+    g_free(local_iov.iov_base);\n+\n+    return true;\n+}\n+\n static int _filter_send(MirrorState *s,\n                        char *buf,\n                        ssize_t size)\ndiff --git a/net/filter.c b/net/filter.c\nindex 76345c1a9d..847dd34698 100644\n--- a/net/filter.c\n+++ b/net/filter.c\n@@ -81,7 +81,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,\n                                     int iovcnt,\n                                     void *opaque)\n {\n-    int ret = 0;\n+    ssize_t ret = 0;\n     int direction;\n     NetFilterState *nf = opaque;\n     NetFilterState *next = NULL;\n@@ -124,6 +124,15 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,\n      * deleted while we go through filters.\n      */\n     if (sender && sender->peer) {\n+        if (get_vhost_net(sender) &&\n+            qemu_netfilter_redirector_inject_netdev(nf, sender,\n+                                                    iov, iovcnt, &ret)) {\n+            if (ret < 0) {\n+                error_report(\"filter redirector AF_PACKET send failed(%s)\",\n+                             strerror(-ret));\n+            }\n+            goto out;\n+        }\n         qemu_net_queue_send_iov(sender->peer->incoming_queue,\n                                 sender, flags, iov, iovcnt, NULL);\n     }\n",
    "prefixes": [
        "RFC",
        "v3",
        "5/7"
    ]
}