get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2215697,
    "url": "http://patchwork.ozlabs.org/api/patches/2215697/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/0e187083845cb83ee1be52bf44bc293b3b918e26.1774410440.git.lucien.xin@gmail.com/",
    "project": {
        "id": 12,
        "url": "http://patchwork.ozlabs.org/api/projects/12/?format=api",
        "name": "Linux CIFS Client",
        "link_name": "linux-cifs-client",
        "list_id": "linux-cifs.vger.kernel.org",
        "list_email": "linux-cifs@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<0e187083845cb83ee1be52bf44bc293b3b918e26.1774410440.git.lucien.xin@gmail.com>",
    "list_archive_url": null,
    "date": "2026-03-25T03:47:19",
    "name": "[net-next,v11,14/15] quic: add packet builder base",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "82bfaa3476ea37d49d2e63d738c2b5946af532fb",
    "submitter": {
        "id": 61073,
        "url": "http://patchwork.ozlabs.org/api/people/61073/?format=api",
        "name": "Xin Long",
        "email": "lucien.xin@gmail.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/0e187083845cb83ee1be52bf44bc293b3b918e26.1774410440.git.lucien.xin@gmail.com/mbox/",
    "series": [
        {
            "id": 497380,
            "url": "http://patchwork.ozlabs.org/api/series/497380/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=497380",
            "date": "2026-03-25T03:47:06",
            "name": "net: introduce QUIC infrastructure and core subcomponents",
            "version": 11,
            "mbox": "http://patchwork.ozlabs.org/series/497380/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2215697/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2215697/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-cifs+bounces-10516-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-cifs@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=MSc7dZx2;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=104.64.211.4; helo=sin.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10516-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"MSc7dZx2\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.160.178",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com"
        ],
        "Received": [
            "from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fgY1W5CKbz1y1G\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 14:54:07 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sin.lore.kernel.org (Postfix) with ESMTP id 52CF630462F8\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 03:50:08 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 4A4202DC76F;\n\tWed, 25 Mar 2026 03:50:03 +0000 (UTC)",
            "from mail-qt1-f178.google.com (mail-qt1-f178.google.com\n [209.85.160.178])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 3183D2EB878\n\tfor <linux-cifs@vger.kernel.org>; Wed, 25 Mar 2026 03:50:00 +0000 (UTC)",
            "by mail-qt1-f178.google.com with SMTP id\n d75a77b69052e-50b68a86ca5so27772001cf.3\n        for <linux-cifs@vger.kernel.org>;\n Tue, 24 Mar 2026 20:50:00 -0700 (PDT)",
            "from wsfd-netdev58.anl.eng.rdu2.dc.redhat.com ([66.187.232.140])\n        by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-50b36cb2e29sm150093001cf.1.2026.03.24.20.49.56\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Tue, 24 Mar 2026 20:49:58 -0700 (PDT)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774410603; cv=none;\n b=YX+W8aYUKz3+a0zGIGaONCw4m9bup1zRo+7Zdl3r9c3pedrNxRKdshA8CU9crkbi0lkLMOSaSft9IQsvqJso/iqX9YhSk6g+dpo2r4PX3EjPeotFyqYHeZN9mKH+wNzGipGUHM+v51PTGMdBoL4Grgqga3MTrmnWO3ZDPWxrJAU=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774410603; c=relaxed/simple;\n\tbh=ZfksrAT35SGjh9S69PtDz1n30eMUvXAa6Z6E76Byvl8=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=dM0tAX4SSBboasaMuRPRsk90Lj8+aZVfm5xx5pcADJJEcByM6oaxSwp8Qb4I4EMUZpSHyn7t4bFt2hZ38+sfLxFsj/Lxy7dtC6p65E35CApNccGgVFS6meYRbaMeoX0gnh8FuhV+Jqb5HVz8A8Fuo/4DkEVHQi7hdp7NjYg3Xw8=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=MSc7dZx2; arc=none smtp.client-ip=209.85.160.178",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20251104; t=1774410599; x=1775015399;\n darn=vger.kernel.org;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n         :message-id:reply-to;\n        bh=3DlVwh603yhSMh+vfT6AQhDGntunvnIOcbWXqmoMRzk=;\n        b=MSc7dZx2PfQryGadn5sbRQSLmwDsLNUOPfl/7JRK6UbKO3wEm3EejrA2FcBUpc0+UV\n         NqUg7ClWZgJ3Wn+K6zuqpD/ll6/++WU/uVIzXVsEMIwBNKXGffFmQ7PsTB6inElt3e0u\n         TirtHl7swDRXRt3268hVQnnOzPSC7fqIe3BZavrx0xgqytQUUF0FzukUkWK/Co7A1Rn1\n         b80wNXlYdO64ahUN5T2OCUg9MXr3igTiUzcHPCYEeEUPLLPkRECwxWPfloHSVbotdqsX\n         7hQ/x0yBM26dhBv0FlmbJAKIjdJ+sXwo5jo3J0rxs2MW7N9Dzj4Q1N4LfF+8kilmzAF3\n         K1UQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20251104; t=1774410599; x=1775015399;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n         :to:cc:subject:date:message-id:reply-to;\n        bh=3DlVwh603yhSMh+vfT6AQhDGntunvnIOcbWXqmoMRzk=;\n        b=DffW2pZgWu/IVYgh/cICemjVgngghW8AOtxA9f38Gdi9p+lWLmBF7thmnQulLPpwbc\n         EGkOaK2WjHVnpsI/GQUeJrvBA8NLLdrGHq+ek9rD71kL2sD767KNQxLtX5oLrEDFXLWb\n         oz+7fEL2V+ttrbyJFvblPYERRyPrO8g7ScGim+K4NZxRHHX4c8yosOpSp122UPltChP5\n         hx9i5hIreC4/3/uTBq3i4QtcT23VVzyuUoNxUtNN/QqUFls6wIpm6NtSoGUu5FyPJXU+\n         N0HpRBhYIZlfMawbWI+bG8N2FNoQPtJ6DTFuVfUpG9qlbvSgia3oOz3I8IY7PuHVumyD\n         B3NA==",
        "X-Forwarded-Encrypted": "i=1;\n AJvYcCUB58W8DJ7gMENGnm7OmUQfoILAAYaMBnJ0+HVg88IbQMBLrfl1sNrgoQNtcm0TDZYYQg1CEA7GU2Nb@vger.kernel.org",
        "X-Gm-Message-State": "AOJu0YzPSLKxxUNB72aGMBodQcnQgNdIanoovP1NehrefoHV9VjxjjQ0\n\tM7OPTrsJfgBvatZ/7/dWm0JKxPypTz6LhrVvoqweMfFjR6M3Z3fSVN+Q",
        "X-Gm-Gg": "ATEYQzyleJZl/X/nZh9QbYl1wOCxuagly93EcFViU1HPoQ8b+S/gWx2ti5yajF/GtPk\n\txz7lhTKebN1JJ/2WAA97PfqxsDDPgIl3pq9XGgCrdjf1vG6NYqC99SZYhhG4Xv86mXIMc3a/Qss\n\tvf72XWXLtqiOVDw22F2oEnfPrzLZTDfB8tMhLbNE3ZuP8i6sa2iF59tsqZg/U1CaFr0ak8ne+Ik\n\ttojCxOh7w5gsPhj36rhwer/7d4vRFz/pf5Ryj+nWI0rzXN1ZHmvNxGoe2tFuV5C3QhMbQM0YnEI\n\twBfoivgoE6wzHgPwPEc9kDieD6IkD8437UFZCdV4TiVd7cphijbzKZdRbpiL5xDO3jlpp4eZaur\n\toIORODvsIydlsoCtFDUk0FHZHTVVYErj/aUXeLf3AYGW4UY3OrGvRpUr0UxQ42OLKewRCtVHB/T\n\t/aba5DAPl58SnXsn3HOgTHNvXxBKnCxi/HaScazKPm/pbnRfWecxUtrgP22AG0lPO7KvVlcS6Vc\n\tGFgFmvoohzYmr2LNK/XNiKnhgq636C8tpawsF843RjAgLVXIOugA16OFdOTNf8qEATITept6l1v",
        "X-Received": "by 2002:ac8:5a11:0:b0:50b:346a:d253 with SMTP id\n d75a77b69052e-50b80e0be45mr32332201cf.43.1774410599030;\n        Tue, 24 Mar 2026 20:49:59 -0700 (PDT)",
        "From": "Xin Long <lucien.xin@gmail.com>",
        "To": "network dev <netdev@vger.kernel.org>,\n\tquic@lists.linux.dev",
        "Cc": "davem@davemloft.net,\n\tkuba@kernel.org,\n\tEric Dumazet <edumazet@google.com>,\n\tPaolo Abeni <pabeni@redhat.com>,\n\tSimon Horman <horms@kernel.org>,\n\tStefan Metzmacher <metze@samba.org>,\n\tMoritz Buhl <mbuhl@openbsd.org>,\n\tTyler Fanelli <tfanelli@redhat.com>,\n\tPengtao He <hepengtao@xiaomi.com>,\n\tThomas Dreibholz <dreibh@simula.no>,\n\tlinux-cifs@vger.kernel.org,\n\tSteve French <smfrench@gmail.com>,\n\tNamjae Jeon <linkinjeon@kernel.org>,\n\tPaulo Alcantara <pc@manguebit.com>,\n\tTom Talpey <tom@talpey.com>,\n\tkernel-tls-handshake@lists.linux.dev,\n\tChuck Lever <chuck.lever@oracle.com>,\n\tJeff Layton <jlayton@kernel.org>,\n\tSteve Dickson <steved@redhat.com>,\n\tHannes Reinecke <hare@suse.de>,\n\tAlexander Aring <aahringo@redhat.com>,\n\tDavid Howells <dhowells@redhat.com>,\n\tMatthieu Baerts <matttbe@kernel.org>,\n\tJohn Ericson <mail@johnericson.me>,\n\tCong Wang <xiyou.wangcong@gmail.com>,\n\t\"D . Wythe\" <alibuda@linux.alibaba.com>,\n\tJason Baron <jbaron@akamai.com>,\n\tilliliti <illiliti@protonmail.com>,\n\tSabrina Dubroca <sd@queasysnail.net>,\n\tMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>,\n\tDaniel Stenberg <daniel@haxx.se>,\n\tAndy Gospodarek <andrew.gospodarek@broadcom.com>,\n\t\"Marc E . Fiuczynski\" <marc@fiuczynski.com>",
        "Subject": "[PATCH net-next v11 14/15] quic: add packet builder base",
        "Date": "Tue, 24 Mar 2026 23:47:19 -0400",
        "Message-ID": "\n <0e187083845cb83ee1be52bf44bc293b3b918e26.1774410440.git.lucien.xin@gmail.com>",
        "X-Mailer": "git-send-email 2.47.1",
        "In-Reply-To": "<cover.1774410440.git.lucien.xin@gmail.com>",
        "References": "<cover.1774410440.git.lucien.xin@gmail.com>",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-cifs@vger.kernel.org",
        "List-Id": "<linux-cifs.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-cifs+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-cifs+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit"
    },
    "content": "This patch introduces 'quic_packet' to handle packing of QUIC packets on\nthe transmit (TX) path.\n\nIt provides functionality for frame packing and packet construction. The\npacket configuration includes setting the path, calculating overhead,\nand verifying routing. Frames are appended to the packet before it is\ncreated with the queued frames.\n\nOnce assembled, the packet is encrypted, bundled, and sent out. There\nis also support to flush the packet when no additional frames remain.\nFunctions to create application (short) and handshake (long) packets\nare currently placeholders for future implementation.\n\n- quic_packet_config(): Set the path, compute overhead, and verify routing.\n\n- quic_packet_create_and_xmit(): Create and send the packet with the queued\n  frames.\n\n- quic_packet_xmit(): Encrypt, bundle, and send out the packet.\n\n- quic_packet_flush(): Send the packet if there's nothing left to bundle.\n\nSigned-off-by: Xin Long <lucien.xin@gmail.com>\n---\nv3:\n  - Adjust global connection and listen socket hashtable operations\n    based on the new hashtable type.\n  - Introduce quic_packet_backlog_schedule() to enqueue Initial packets\n    to quic_net.backlog_list and defer their decryption for ALPN demux\n    to quic_packet_backlog_work() on quic_net.work, since\n    quic_crypto_initial_keys_install()/crypto_aead_setkey() must run\n    in process context.\nv4:\n  - Update quic_(listen_)sock_lookup() to support lockless socket\n    lookup using hlist_nulls_node APIs.\n  - Use quic_wq for QUIC packet backlog processing work.\nv5:\n  - Rename quic_packet_create() to quic_packet_create_and_xmit()\n    (suggested by Paolo).\n  - Move the packet parser base code to a separate patch, keeping only\n    the packet builder base in this patch (suggested by Paolo).\n  - Change sent_time timestamp from u32 to u64 to improve accuracy.\nv8:\n  - Remove the dependency on struct quic_frame by returning NULL in\n    quic_packet_handshake/app_create() and dropping quic_packet_tail()\n    and struct quic_packet_sent. This effectively strips out patch 14\n    (suggested by Paolo).\nv9:\n  - Warn on oversized header length in quic_packet_config() (suggested by\n    Paolo).\n  - Factor bundle initialization into a common 'init' goto label in\n    quic_packet_bundle() (suggested by Paolo).\n  - Clarify comment for packet->ipfragok in quic_packet_config().\nv10:\n  - Set MSS to QUIC_MIN_UDP_PAYLOAD in quic_packet_init(); it serves only\n    as a default for procfs dumps before a connection exists.\n  - Introduce QUIC_PACKET_INVALID as a return value for invalid packet\n    types used in the later patch.\n  - quic_sock.config.plpmtud_probe_interval has been moved to\n    quic_path_group.plpmtud_interval, so update its usage in\n    quic_packet_route() and quic_packet_config() accordingly.\nv11:\n  - Set maximum line length to 80 characters.\n  - Change return type of quic_packet_empty() to bool.\n  - Propagate errors from quic_packet_route() in quic_packet_config()\n    (noted by AI review).\n  - Use quic_packet_taglen() instead of open-coded logic in\n    quic_packet_mss(), quic_packet_max_payload(), and\n    quic_packet_max_payload_dgram() (noted by AI review).\n  - Replace some magic numbers with QUIC_PACKET_FORM_SHORT/LONG and\n    QUIC_PACKET_MSS_NORMAL/DGRAM (noted by Paolo).\n  - Use WARN_ON_ONCE() instead of WARN_ON() in quic_packet_xmit().\n    skb_set_owner_w/r() cannot be used here because it performs memory\n    accounting, which is not desired in this context (noted by Paolo).\n---\n net/quic/Makefile |   2 +-\n net/quic/packet.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++\n net/quic/packet.h | 117 ++++++++++++++++++++\n net/quic/socket.c |   1 +\n net/quic/socket.h |   8 ++\n 5 files changed, 395 insertions(+), 1 deletion(-)\n create mode 100644 net/quic/packet.c\n create mode 100644 net/quic/packet.h",
    "diff": "diff --git a/net/quic/Makefile b/net/quic/Makefile\nindex 2ccf01ad9e22..0f903f4a7ff1 100644\n--- a/net/quic/Makefile\n+++ b/net/quic/Makefile\n@@ -6,4 +6,4 @@\n obj-$(CONFIG_IP_QUIC) += quic.o\n \n quic-y := common.o family.o protocol.o socket.o stream.o connid.o path.o \\\n-\t  cong.o pnspace.o crypto.o timer.o\n+\t  cong.o pnspace.o crypto.o timer.o packet.o\ndiff --git a/net/quic/packet.c b/net/quic/packet.c\nnew file mode 100644\nindex 000000000000..0805bc77c2a2\n--- /dev/null\n+++ b/net/quic/packet.c\n@@ -0,0 +1,268 @@\n+// SPDX-License-Identifier: GPL-2.0-or-later\n+/* QUIC kernel implementation\n+ * (C) Copyright Red Hat Corp. 2023\n+ *\n+ * This file is part of the QUIC kernel implementation\n+ *\n+ * Initialization/cleanup for QUIC protocol support.\n+ *\n+ * Written or modified by:\n+ *    Xin Long <lucien.xin@gmail.com>\n+ */\n+\n+#include \"socket.h\"\n+\n+#define QUIC_HLEN\t\t1\n+\n+/* Make these fixed for easy coding. */\n+#define QUIC_PACKET_NUMBER_LEN\tQUIC_PN_MAX_LEN\n+#define QUIC_PACKET_LENGTH_LEN\t4\n+\n+static struct sk_buff *quic_packet_handshake_create(struct sock *sk)\n+{\n+\treturn NULL;\n+}\n+\n+static int quic_packet_number_check(struct sock *sk)\n+{\n+\treturn 0;\n+}\n+\n+static struct sk_buff *quic_packet_app_create(struct sock *sk)\n+{\n+\treturn NULL;\n+}\n+\n+/* Update the MSS and inform congestion control. */\n+void quic_packet_mss_update(struct sock *sk, u32 mss)\n+{\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\tstruct quic_cong *cong = quic_cong(sk);\n+\n+\tpacket->mss[QUIC_PACKET_MSS_NORMAL] = (u16)mss;\n+\tquic_cong_set_mss(cong, packet->mss[QUIC_PACKET_MSS_NORMAL] -\n+\t\t\t\tpacket->taglen[QUIC_PACKET_FORM_SHORT]);\n+}\n+\n+/* Perform routing for the QUIC packet on the specified path, update header\n+ * length and MSS accordingly, reset path and start PMTU timer.\n+ */\n+int quic_packet_route(struct sock *sk)\n+{\n+\tstruct quic_path_group *paths = quic_paths(sk);\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\tunion quic_addr *sa, *da;\n+\tu32 pmtu;\n+\tint err;\n+\n+\tda = quic_path_daddr(paths, packet->path);\n+\tsa = quic_path_saddr(paths, packet->path);\n+\terr = quic_flow_route(sk, da, sa, &paths->fl);\n+\tif (err)\n+\t\treturn err < 0 ? err : 0;\n+\n+\tpacket->hlen = quic_encap_len(da);\n+\tpmtu = min_t(u32, dst_mtu(__sk_dst_get(sk)), QUIC_PATH_MAX_PMTU);\n+\tquic_packet_mss_update(sk, pmtu - packet->hlen);\n+\n+\tquic_path_pl_reset(paths);\n+\tquic_timer_reset(sk, QUIC_TIMER_PMTU, paths->plpmtud_interval);\n+\treturn 0;\n+}\n+\n+/* Configure the QUIC packet header and routing based on encryption level and\n+ * path.\n+ */\n+int quic_packet_config(struct sock *sk, u8 level, u8 path)\n+{\n+\tstruct quic_conn_id_set *source = quic_source(sk);\n+\tstruct quic_conn_id_set *dest = quic_dest(sk);\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\tu32 hlen = QUIC_HLEN;\n+\n+\t/* If packet already has data, no need to reconfigure. */\n+\tif (!quic_packet_empty(packet))\n+\t\treturn 0;\n+\n+\tpacket->ack_eliciting = 0;\n+\tpacket->frame_len = 0;\n+\tpacket->ipfragok = 0;\n+\tpacket->padding = 0;\n+\tpacket->frames = 0;\n+\thlen += QUIC_PACKET_NUMBER_LEN; /* Packet number length. */\n+\thlen += quic_conn_id_choose(dest, path)->len; /* DCID length. */\n+\tif (level) {\n+\t\thlen += 1; /* Length byte for DCID. */\n+\t\t/* Length byte + SCID length. */\n+\t\thlen += 1 + quic_conn_id_active(source)->len;\n+\t\t/* Include token for Initial packets. */\n+\t\tif (level == QUIC_CRYPTO_INITIAL)\n+\t\t\thlen += quic_var_len(quic_token(sk)->len) +\n+\t\t\t\tquic_token(sk)->len;\n+\t\thlen += QUIC_VERSION_LEN; /* Version length. */\n+\t\thlen += QUIC_PACKET_LENGTH_LEN; /* Packet length field. */\n+\t\t/* Allow fragmentation for handshake packets before PLPMTUD\n+\t\t * probing starts.  MTU discovery does not rely on ICMP Packet\n+\t\t * Too Big once PLPMTUD is enabled.\n+\t\t */\n+\t\tpacket->ipfragok = !!quic_paths(sk)->plpmtud_interval;\n+\t}\n+\tpacket->level = level;\n+\tpacket->len = (u16)hlen;\n+\tpacket->overhead = (u8)hlen;\n+\tDEBUG_NET_WARN_ON_ONCE(hlen > 255);\n+\n+\tif (packet->path != path) {\n+\t\t/* Path changed; update and reset routing cache */\n+\t\tpacket->path = path;\n+\t\t__sk_dst_reset(sk);\n+\t}\n+\n+\t/* Perform routing and MSS update for the configured packet. */\n+\treturn quic_packet_route(sk);\n+}\n+\n+static void quic_packet_encrypt_done(struct sk_buff *skb, int err)\n+{\n+\t/* Free it for now, future patches will implement the actual deferred\n+\t * transmission logic.\n+\t */\n+\tkfree_skb(skb);\n+}\n+\n+/* Coalescing Packets. */\n+static int quic_packet_bundle(struct sock *sk, struct sk_buff *skb)\n+{\n+\tstruct quic_skb_cb *head_cb, *cb = QUIC_SKB_CB(skb);\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\tstruct sk_buff *p;\n+\n+\tif (!packet->head) /* First packet to bundle: initialize the head. */\n+\t\tgoto init;\n+\n+\t/* If bundling would exceed MSS, flush the current bundle. */\n+\tif (packet->head->len + skb->len >=\n+\t    packet->mss[QUIC_PACKET_MSS_NORMAL]) {\n+\t\tquic_packet_flush(sk);\n+\t\tgoto init;\n+\t}\n+\t/* Bundle it and update metadata for the aggregate skb. */\n+\tp = packet->head;\n+\thead_cb = QUIC_SKB_CB(p);\n+\tif (head_cb->last == p)\n+\t\tskb_shinfo(p)->frag_list = skb;\n+\telse\n+\t\thead_cb->last->next = skb;\n+\tp->data_len += skb->len;\n+\tp->truesize += skb->truesize;\n+\tp->len += skb->len;\n+\thead_cb->last = skb;\n+\thead_cb->ecn |= cb->ecn;  /* Merge ECN flags. */\n+\n+out:\n+\t/* rfc9000#section-12.2: Packets with a short header (Section 17.3) do\n+\t * not contain a Length field and so cannot be followed by other\n+\t * packets in the same UDP datagram.\n+\t *\n+\t * so Return 1 to flush if it is a Short header packet.\n+\t */\n+\treturn !cb->level;\n+init:\n+\tpacket->head = skb;\n+\tcb->last = skb;\n+\tgoto out;\n+}\n+\n+/* Transmit a QUIC packet, possibly encrypting and bundling it. */\n+int quic_packet_xmit(struct sock *sk, struct sk_buff *skb)\n+{\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\tstruct quic_skb_cb *cb = QUIC_SKB_CB(skb);\n+\tstruct net *net = sock_net(sk);\n+\tint err;\n+\n+\t/* Skip encryption if taglen == 0 (e.g., disable_1rtt_encryption). */\n+\tif (!packet->taglen[quic_hdr(skb)->form])\n+\t\tgoto xmit;\n+\n+\tcb->crypto_done = quic_packet_encrypt_done;\n+\t/* Associate skb with sk to ensure sk is valid during async encryption\n+\t * completion.\n+\t */\n+\tWARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));\n+\terr = quic_crypto_encrypt(quic_crypto(sk, packet->level), skb);\n+\tif (err) {\n+\t\tif (err != -EINPROGRESS) {\n+\t\t\tQUIC_INC_STATS(net, QUIC_MIB_PKT_ENCDROP);\n+\t\t\tkfree_skb(skb);\n+\t\t\treturn err;\n+\t\t}\n+\t\tQUIC_INC_STATS(net, QUIC_MIB_PKT_ENCBACKLOGS);\n+\t\treturn err;\n+\t}\n+\tif (!cb->resume) /* Encryption completes synchronously. */\n+\t\tQUIC_INC_STATS(net, QUIC_MIB_PKT_ENCFASTPATHS);\n+\n+xmit:\n+\tif (quic_packet_bundle(sk, skb))\n+\t\tquic_packet_flush(sk);\n+\treturn 0;\n+}\n+\n+/* Create and transmit a new QUIC packet. */\n+int quic_packet_create_and_xmit(struct sock *sk)\n+{\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\tstruct sk_buff *skb;\n+\tint err;\n+\n+\terr = quic_packet_number_check(sk);\n+\tif (err)\n+\t\tgoto err;\n+\n+\tif (packet->level)\n+\t\tskb = quic_packet_handshake_create(sk);\n+\telse\n+\t\tskb = quic_packet_app_create(sk);\n+\tif (!skb) {\n+\t\terr = -ENOMEM;\n+\t\tgoto err;\n+\t}\n+\n+\terr = quic_packet_xmit(sk, skb);\n+\tif (err && err != -EINPROGRESS)\n+\t\tgoto err;\n+\n+\t/* Return 1 if at least one ACK-eliciting (non-PING) frame was sent. */\n+\treturn !!packet->frames;\n+err:\n+\tpr_debug(\"%s: err: %d\\n\", __func__, err);\n+\treturn 0;\n+}\n+\n+/* Flush any coalesced/bundled QUIC packets. */\n+void quic_packet_flush(struct sock *sk)\n+{\n+\tstruct quic_path_group *paths = quic_paths(sk);\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\n+\tif (packet->head) {\n+\t\tquic_lower_xmit(sk, packet->head,\n+\t\t\t\tquic_path_daddr(paths, packet->path),\n+\t\t\t\t&paths->fl);\n+\t\tpacket->head = NULL;\n+\t}\n+}\n+\n+void quic_packet_init(struct sock *sk)\n+{\n+\tstruct quic_packet *packet = quic_packet(sk);\n+\n+\tINIT_LIST_HEAD(&packet->frame_list);\n+\tpacket->taglen[QUIC_PACKET_FORM_SHORT] = QUIC_TAG_LEN;\n+\tpacket->taglen[QUIC_PACKET_FORM_LONG] = QUIC_TAG_LEN;\n+\tpacket->mss[QUIC_PACKET_MSS_NORMAL] = QUIC_MIN_UDP_PAYLOAD;\n+\tpacket->mss[QUIC_PACKET_MSS_DGRAM] = QUIC_MIN_UDP_PAYLOAD;\n+\n+\tpacket->version = QUIC_VERSION_V1;\n+}\ndiff --git a/net/quic/packet.h b/net/quic/packet.h\nnew file mode 100644\nindex 000000000000..834c4f72271b\n--- /dev/null\n+++ b/net/quic/packet.h\n@@ -0,0 +1,117 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/* QUIC kernel implementation\n+ * (C) Copyright Red Hat Corp. 2023\n+ *\n+ * This file is part of the QUIC kernel implementation\n+ *\n+ * Written or modified by:\n+ *    Xin Long <lucien.xin@gmail.com>\n+ */\n+\n+struct quic_packet {\n+\tstruct quic_conn_id dcid; /* Dest Conn ID from received packet */\n+\tstruct quic_conn_id scid; /* Source Conn ID from received packet */\n+\tunion quic_addr daddr;    /* Dest address from received packet */\n+\tunion quic_addr saddr;    /* Source address from received packet */\n+\n+\tstruct list_head frame_list; /* Frames to pack into packet for send */\n+\tstruct sk_buff *head;        /* Head skb for packet bundling on send */\n+\tu16 frame_len; /* Length of all ack-eliciting frames excluding PING */\n+\tu8 taglen[2];  /* Tag length for short and long packets */\n+\tu32 version;   /* QUIC version used/selected during handshake */\n+\tu8 errframe;   /* Frame type causing packet processing failure */\n+\tu8 overhead;   /* QUIC header length excluding frames */\n+\tu16 errcode;   /* Error code on packet processing failure */\n+\tu16 frames;    /* Number of ack-eliciting frames excluding PING */\n+\tu16 mss[2];    /* MSS for datagram and non-datagram packets */\n+\tu16 hlen;      /* UDP + IP header length for sending */\n+\tu16 len;       /* QUIC packet length excluding taglen for sending */\n+\n+\tu8 ack_eliciting:1; /* Packet contains ack-eliciting frames to send */\n+\tu8 ack_requested:1; /* Packet contains ack-eliciting frames received */\n+\tu8 ack_immediate:1; /* Send ACK immediately (skip ack_delay timer) */\n+\tu8 non_probing:1;   /* Ack-eliciting packet (excl. NEW_CONNECTION_ID) */\n+\tu8 has_sack:1;      /* Packet has ACK frames received */\n+\tu8 ipfragok:1;      /* Allow IP fragmentation */\n+\tu8 padding:1;       /* Packet has padding frames */\n+\tu8 path:1;          /* Path identifier used to send this packet */\n+\tu8 level;           /* Encryption level used */\n+};\n+\n+#define QUIC_PACKET_INITIAL_V1\t\t0\n+#define QUIC_PACKET_0RTT_V1\t\t1\n+#define QUIC_PACKET_HANDSHAKE_V1\t2\n+#define QUIC_PACKET_RETRY_V1\t\t3\n+\n+#define QUIC_PACKET_INITIAL_V2\t\t1\n+#define QUIC_PACKET_0RTT_V2\t\t2\n+#define QUIC_PACKET_HANDSHAKE_V2\t3\n+#define QUIC_PACKET_RETRY_V2\t\t0\n+\n+#define QUIC_PACKET_INITIAL\t\tQUIC_PACKET_INITIAL_V1\n+#define QUIC_PACKET_0RTT\t\tQUIC_PACKET_0RTT_V1\n+#define QUIC_PACKET_HANDSHAKE\t\tQUIC_PACKET_HANDSHAKE_V1\n+#define QUIC_PACKET_RETRY\t\tQUIC_PACKET_RETRY_V1\n+\n+#define QUIC_PACKET_INVALID\t\t0xff\n+\n+#define QUIC_VERSION_LEN\t\t4\n+\n+#define QUIC_PACKET_MSS_NORMAL\t\t0\n+#define QUIC_PACKET_MSS_DGRAM\t\t1\n+\n+#define QUIC_PACKET_FORM_SHORT\t\t0\n+#define QUIC_PACKET_FORM_LONG\t\t1\n+\n+static inline u8 quic_packet_taglen(struct quic_packet *packet)\n+{\n+\treturn packet->taglen[packet->level != QUIC_CRYPTO_APP];\n+}\n+\n+static inline void quic_packet_set_taglen(struct quic_packet *packet, u8 taglen)\n+{\n+\tpacket->taglen[QUIC_PACKET_FORM_SHORT] = taglen;\n+}\n+\n+static inline u32 quic_packet_mss(struct quic_packet *packet)\n+{\n+\treturn packet->mss[QUIC_PACKET_MSS_NORMAL] - quic_packet_taglen(packet);\n+}\n+\n+static inline u32 quic_packet_max_payload(struct quic_packet *packet)\n+{\n+\treturn packet->mss[QUIC_PACKET_MSS_NORMAL] - packet->overhead -\n+\t       quic_packet_taglen(packet);\n+}\n+\n+static inline u32 quic_packet_max_payload_dgram(struct quic_packet *packet)\n+{\n+\treturn packet->mss[QUIC_PACKET_MSS_DGRAM] - packet->overhead -\n+\t       quic_packet_taglen(packet);\n+}\n+\n+static inline bool quic_packet_empty(struct quic_packet *packet)\n+{\n+\treturn list_empty(&packet->frame_list);\n+}\n+\n+static inline void quic_packet_reset(struct quic_packet *packet)\n+{\n+\tpacket->level = 0;\n+\tpacket->errcode = 0;\n+\tpacket->errframe = 0;\n+\tpacket->has_sack = 0;\n+\tpacket->non_probing = 0;\n+\tpacket->ack_requested = 0;\n+\tpacket->ack_immediate = 0;\n+}\n+\n+int quic_packet_config(struct sock *sk, u8 level, u8 path);\n+\n+int quic_packet_xmit(struct sock *sk, struct sk_buff *skb);\n+int quic_packet_create_and_xmit(struct sock *sk);\n+int quic_packet_route(struct sock *sk);\n+\n+void quic_packet_mss_update(struct sock *sk, u32 mss);\n+void quic_packet_flush(struct sock *sk);\n+void quic_packet_init(struct sock *sk);\ndiff --git a/net/quic/socket.c b/net/quic/socket.c\nindex c37cc1522254..b9fbc33c0f79 100644\n--- a/net/quic/socket.c\n+++ b/net/quic/socket.c\n@@ -52,6 +52,7 @@ static int quic_init_sock(struct sock *sk)\n \tquic_cong_init(quic_cong(sk));\n \n \tquic_timer_init(sk);\n+\tquic_packet_init(sk);\n \n \tif (quic_stream_init(quic_streams(sk)))\n \t\treturn -ENOMEM;\ndiff --git a/net/quic/socket.h b/net/quic/socket.h\nindex c5654fdc06b5..1efc76ec2033 100644\n--- a/net/quic/socket.h\n+++ b/net/quic/socket.h\n@@ -20,6 +20,8 @@\n #include \"path.h\"\n #include \"cong.h\"\n \n+#include \"packet.h\"\n+\n #include \"protocol.h\"\n #include \"timer.h\"\n \n@@ -74,6 +76,7 @@ struct quic_sock {\n \tstruct quic_pnspace\t\tspace[QUIC_PNSPACE_MAX];\n \tstruct quic_crypto\t\tcrypto[QUIC_CRYPTO_MAX];\n \n+\tstruct quic_packet\t\tpacket;\n \tstruct quic_timer\t\ttimers[QUIC_TIMER_MAX];\n };\n \n@@ -147,6 +150,11 @@ static inline struct quic_crypto *quic_crypto(const struct sock *sk, u8 level)\n \treturn &quic_sk(sk)->crypto[level];\n }\n \n+static inline struct quic_packet *quic_packet(const struct sock *sk)\n+{\n+\treturn &quic_sk(sk)->packet;\n+}\n+\n static inline void *quic_timer(const struct sock *sk, u8 type)\n {\n \treturn (void *)&quic_sk(sk)->timers[type];\n",
    "prefixes": [
        "net-next",
        "v11",
        "14/15"
    ]
}