get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2215688,
    "url": "http://patchwork.ozlabs.org/api/patches/2215688/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/0b019aa9a77bef1d5472da22760443609f402527.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": "<0b019aa9a77bef1d5472da22760443609f402527.1774410440.git.lucien.xin@gmail.com>",
    "list_archive_url": null,
    "date": "2026-03-25T03:47:08",
    "name": "[net-next,v11,03/15] quic: provide common utilities and data structures",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "049bb36038bc47982156e8262a7b8de8cbffb55c",
    "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/0b019aa9a77bef1d5472da22760443609f402527.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/2215688/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2215688/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-cifs+bounces-10505-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=k9Ryoko4;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10505-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=\"k9Ryoko4\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.160.181",
            "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 tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\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 4fgXys3WFNz1y1G\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 14:51:49 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 4491530A4206\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 25 Mar 2026 03:49:37 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 2055D182D0;\n\tWed, 25 Mar 2026 03:49:33 +0000 (UTC)",
            "from mail-qt1-f181.google.com (mail-qt1-f181.google.com\n [209.85.160.181])\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 BDC212E040D\n\tfor <linux-cifs@vger.kernel.org>; Wed, 25 Mar 2026 03:49:30 +0000 (UTC)",
            "by mail-qt1-f181.google.com with SMTP id\n d75a77b69052e-5091d71aa11so6437021cf.1\n        for <linux-cifs@vger.kernel.org>;\n Tue, 24 Mar 2026 20:49:30 -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.26\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Tue, 24 Mar 2026 20:49:28 -0700 (PDT)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774410573; cv=none;\n b=G7d6dvpC+c1VwB+VqQlViVS5WXZezmm3NDgp3yOCHdr3ZQWDtsyBt87b6WUF+UowkJgVNU7mjXug4ptqSUktB/GTZfviiGIl2ZMpqi+k9mMjcZomq3Baok44tuJSeLa/A/4rZnM6AntL82JvSCY2XoSfbBE+adDs5z+KJ3hTy58=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774410573; c=relaxed/simple;\n\tbh=NlkIArFW+1tXDEXfFd2LCO8kAfbQ4PT0y/lf9k0/f+Y=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version:Content-Type;\n b=UlhkIaUiB++OxF2aQEoQXDLT2jzpzXfbf5iYq7Y6zdKA9+eqr83/xyEfvTGKycRgs1kvgEEmOZttPl48L7s2aWdpW63xvKBeeGpfe91MQDtNQl2B3giaZjHItkhbxx6Hhd3QnEy2pOHKDp2uOnw4a83w4b84kL4kTKY/KzA4jBc=",
        "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=k9Ryoko4; arc=none smtp.client-ip=209.85.160.181",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20251104; t=1774410570; x=1775015370;\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=xLp1kyIFf8LL/6Ag2VDieViV+GyuNC8gjTOISGjXuVw=;\n        b=k9Ryoko4W7cfsctLlDwERI7G9KC6OLGn6dbYvlbi4kuQXCFiBWI04fcqDZPHNwBA38\n         XBnqbjAN2ivgGwx5MFl2R9djcy1H6Q1jXcdJ2jhFny+oxovlbp0CuznvqPPY92Hj57h9\n         wS8ZZGzcIOLQ/o3QkEStI4ikKwR9VrVG+3z1bzUyiGU0f/uehjTz2E+E6xtb74BxIgnk\n         avYGZks/wP1EkbD8G7GCfWLP/pQmISPUMicwWgKRzRguV+Up5C395djclhPBrz3kncv+\n         ZCmfuDsWRmL4feS/8ILJ3QIzve5wscXnnTe+vEDh39gHBfea5Dy7nyEhOmD7Fw0JH4Yu\n         Zv/Q==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20251104; t=1774410570; x=1775015370;\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=xLp1kyIFf8LL/6Ag2VDieViV+GyuNC8gjTOISGjXuVw=;\n        b=MmJ4E2R9tVI6NKZGtLBCPToyta4gFirlFK5jZAIcuMM+0GKYrvxfJJoALlZhGN5nhU\n         C1idL/OIxJtxVra8++SB92IF8mNzJMRs153FtNlCAB4p3UO5BEkvfA76uDZyKKq4smOb\n         07clfd9KeDCdqTOUE9inojNLlvZEW7uftNn9QxjVNmJKCEn2MzydSOSObh8KqXkXVWZM\n         zBBc+zKd25dGmLeN0+DHIEICArFsn/NIjSI3Bovw2qdUmB2nR9n9BQnSTySZo5HStHb4\n         OzxBlCDY0YHGezefO90e2KmbSdK3a+A/u9Z7DmrlQDjurQDxMgJws9SP0Tyd68Yt/z7I\n         6UAA==",
        "X-Forwarded-Encrypted": "i=1;\n AJvYcCVi5uI5eUtfHP9bQNfo+9jVKZTUrgN/q2EeLhpJEd3RVuHwefxoIGdhqMpJ7EnvtOYHg+cWONsrxzmw@vger.kernel.org",
        "X-Gm-Message-State": "AOJu0Yx9dIoGPWlBkX6476xZUZz94h29GY7qzQKCnNLbqwQBGo9FwvuE\n\tHZMtmNUi3gF7tw9zjJ5w1eWtRIH78FHSez2rwG3m32M/xaljpduVQG3d",
        "X-Gm-Gg": "ATEYQzzbM+Y3Z1d94uNGO4iMf/xYMj5sbqYRv+OxX5teC0epzQJT2AhOOEmHjLRklgA\n\tKXGzYsN+g2R/I649zwdBtkuLRKu4fBMLJCa9ydecEr8jsytZkqXEVn0G1/sCl9IzO8BcUNPMHSj\n\tMQDeV7MSqTKSaa7rrf0F4mMCyHvU1pFxp4qSjNq/ap3PrbNY41WPNquyynksoApvaoE0BrAWJsx\n\tT+EGAnYMyymZjmJ8rt8PtQh6wuaw9jIGWPyPzIiM+ICIWjVoAm8FaN1W9FCnsfzB/nUaT8ld8l9\n\tmTqIiQHIcxEBhdhXuki3ni1iETCb98RcvprQ/mqE/zoeN1bbelmtupnnnKxy3ihQXrqyZsb4ezF\n\tgysnGgK/6mE7LroPaR3U3sjISpxO4yqR/2OGAlB9NpLFkzxbSfO2jbHWEvDqDHeJutvyIcIPlMa\n\t+B457sVi9zqOkD1cpEuRQ253I9RM13yh3sD/igXT8dfJRqIl2fck5RfVercWFYHxJObi/Lwd6iN\n\tZAO7M03SKCp/JqDBPEi6BCIhEW1rCbLtH36keQq0KXiUysymdEvjuwcbtP2yTxfOA==",
        "X-Received": "by 2002:a05:622a:241:b0:50b:891a:a0d5 with SMTP id\n d75a77b69052e-50b891aa275mr2436391cf.35.1774410569512;\n        Tue, 24 Mar 2026 20:49:29 -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 03/15] quic: provide common utilities and data\n structures",
        "Date": "Tue, 24 Mar 2026 23:47:08 -0400",
        "Message-ID": "\n <0b019aa9a77bef1d5472da22760443609f402527.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-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit"
    },
    "content": "This patch provides foundational data structures and utilities used\nthroughout the QUIC stack.\n\nIt introduces packet header types, connection ID support, and address\nhandling. Hash tables are added to manage socket lookup and connection\nID mapping.\n\nA flexible binary data type is provided, along with helpers for parsing,\nmatching, and memory management. Helpers for encoding and decoding\ntransport parameters and frames are also included.\n\nSigned-off-by: Xin Long <lucien.xin@gmail.com>\nAcked-by: Paolo Abeni <pabeni@redhat.com>\n---\nv3:\n  - Rework hashtables: split into two types and size them based on\n    totalram_pages(), similar to SCTP (reported by Paolo).\n  - struct quic_shash_table: use rwlock instead of spinlock.\n  - quic_data_from/to_string(): add safety and common-case checks\n    (noted by Paolo).\nv4:\n  - Handle the error returned by quic_hash_tables_init() properly\n    (reported by Simon).\n  - Use vmalloc() to simplify hashtable allocations (suggested by Paolo).\n  - Replace rwlock_t with spinlock_t and use hlist_nulls_head in\n    quic_shash_head for lockless lookup/access (suggested by Paolo).\n  - Define QUIC_PN_BITS to replace a magical number in quic_get_num()\n    (reported by Paolo)\n  - Rename several hash-related functions:\n    * quic_(listen_)sock_hash() → quic_(listen_)sock_head()\n    * quic_(listen_)sock_head() → quic_(listen_)sock_hash()\n    * quic_shash() → quic_addr_hash()\n    * quic_ahash() → call its code directly in quic_sock_hash().\n  - Include net in the hash calculations in quic_listen_sock_hash() and\n    quic_udp_sock_head(), and include len in quic_source_conn_id_head().\nv5:\n  - Use u64 for skb_cb->time and u32 for skb_cb->seqno, and introduce\n    quic_ktime_get_us() to obtain timestamps in microseconds.\n  - Remove skb_cb->number_max and reuse number as the largest previously\n    seen, and add skb_cb->crypto_ctx for async crypto context freeing.\n  - Add case 8 to quic_put_int(), which will be used to pack a u64\n    timestamp into the token in a later patch.\nv6:\n  - Since transport_header is no longer set for QUIC, use skb->data\n    instead in quic_hdr() and quic_hshdr(). As the UDP header can now\n    be accessed via udp_hdr(), drop udph_offset from struct quic_skb_cb.\n  - Note for AI reviews: although ticket/token/alpn are not initialized\n    in quic_init_sock(), it is safe to kfree() them in quic_destroy_sock()\n    because they are always set to NULL (via sk_alloc() in inet/6_create()\n    or memset(0) in quic_accept() in a later patchset).\nv7:\n  - Add the missing check len < length in quic_data_has/match() (reported\n    by AI review).\nv9:\n  - Add BUILD_BUG_ON() to check size of struct quic_skb_cb in quic_init()\n    (suggested by Paolo).\nv10:\n  - Add a comment to quic_conn_id_update() to clarify that the caller is\n    responsible for ensuring the connection ID length does not\n    exceed QUIC_CONN_ID_MAX_LEN.\n  - Ensure quic_get_param() validates that the decoded parameter value\n    consumes exactly the expected valuelen in quic_get_param() (noted by\n    AI review).\n  - Replace manual memcpy() + endian conversion and temporary union usage\n    with get_unaligned_beNN() and put_unaligned_beNN() helpers for reading\n    and writing integers in network byte order.\n  - Replace vmalloc(size * sizeof(type)) with vmalloc_array() in hash\n    table allocations.\n  - Move *plen update to after successful parse in quic_get_int().\nv11:\n  - Set maximum line length to 80 characters.\n  - Change return type of quic_data_match() and quic_data_has() to bool.\n  - Add a check for len in quic_conn_id_update().\n  - Avoid roundup_pow_of_two(0) in quic_hash_tables_init().\n---\n net/quic/Makefile   |   2 +-\n net/quic/common.c   | 564 ++++++++++++++++++++++++++++++++++++++++++++\n net/quic/common.h   | 212 +++++++++++++++++\n net/quic/protocol.c |  10 +\n net/quic/socket.c   |   4 +\n net/quic/socket.h   |  21 ++\n 6 files changed, 812 insertions(+), 1 deletion(-)\n create mode 100644 net/quic/common.c\n create mode 100644 net/quic/common.h",
    "diff": "diff --git a/net/quic/Makefile b/net/quic/Makefile\nindex 020e4dd133d8..e0067272de7d 100644\n--- a/net/quic/Makefile\n+++ b/net/quic/Makefile\n@@ -5,4 +5,4 @@\n \n obj-$(CONFIG_IP_QUIC) += quic.o\n \n-quic-y := protocol.o socket.o\n+quic-y := common.o protocol.o socket.o\ndiff --git a/net/quic/common.c b/net/quic/common.c\nnew file mode 100644\nindex 000000000000..7b0d711a8f94\n--- /dev/null\n+++ b/net/quic/common.c\n@@ -0,0 +1,564 @@\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 <linux/unaligned.h>\n+#include <net/netns/hash.h>\n+#include <linux/vmalloc.h>\n+#include <linux/jhash.h>\n+\n+#include \"common.h\"\n+\n+#define QUIC_VARINT_1BYTE_MAX\t\t0x3fULL\n+#define QUIC_VARINT_2BYTE_MAX\t\t0x3fffULL\n+#define QUIC_VARINT_4BYTE_MAX\t\t0x3fffffffULL\n+#define QUIC_VARINT_8BYTE_MAX\t\t0x3fffffffffffffffULL\n+\n+#define QUIC_VARINT_2BYTE_PREFIX\t0x40\n+#define QUIC_VARINT_4BYTE_PREFIX\t0x80\n+#define QUIC_VARINT_8BYTE_PREFIX\t0xc0\n+\n+#define QUIC_VARINT_LENGTH(p)\t\tBIT((*(p)) >> 6)\n+\n+struct quic_hashinfo {\n+\tstruct quic_shash_table shash; /* Source connection ID hashtable */\n+\tstruct quic_shash_table lhash; /* Listening sock hashtable */\n+\tstruct quic_shash_table chash; /* Connection sock hashtable */\n+\tstruct quic_uhash_table uhash; /* UDP sock hashtable */\n+};\n+\n+static struct quic_hashinfo quic_hashinfo;\n+\n+u32 quic_sock_hash_size(void)\n+{\n+\treturn quic_hashinfo.chash.size;\n+}\n+\n+u32 quic_sock_hash(struct net *net, union quic_addr *s, union quic_addr *d)\n+{\n+\tu32 ports = ((__force u32)s->v4.sin_port) << 16 |\n+\t\t    (__force u32)d->v4.sin_port;\n+\tu32 saddr = (s->sa.sa_family == AF_INET6) ?\n+\t\t    jhash(&s->v6.sin6_addr, 16, 0) :\n+\t\t    (__force u32)s->v4.sin_addr.s_addr;\n+\tu32 daddr = (d->sa.sa_family == AF_INET6) ?\n+\t\t    jhash(&d->v6.sin6_addr, 16, 0) :\n+\t\t    (__force u32)d->v4.sin_addr.s_addr;\n+\tu32 hash = jhash_3words(saddr, ports, net_hash_mix(net), daddr);\n+\n+\treturn hash & (quic_sock_hash_size() - 1);\n+}\n+\n+struct quic_shash_head *quic_sock_head(u32 hash)\n+{\n+\treturn &quic_hashinfo.chash.hash[hash];\n+}\n+\n+u32 quic_listen_sock_hash_size(void)\n+{\n+\treturn quic_hashinfo.lhash.size;\n+}\n+\n+u32 quic_listen_sock_hash(struct net *net, u16 port)\n+{\n+\tu32 hash = jhash_2words((__force u32)port, net_hash_mix(net), 0);\n+\n+\treturn hash & (quic_listen_sock_hash_size() - 1);\n+}\n+\n+struct quic_shash_head *quic_listen_sock_head(u32 hash)\n+{\n+\treturn &quic_hashinfo.lhash.hash[hash];\n+}\n+\n+struct quic_shash_head *quic_source_conn_id_head(struct net *net, u8 *scid,\n+\t\t\t\t\t\t u32 len)\n+{\n+\tu32 hash = jhash_2words(jhash(scid, len, 0), net_hash_mix(net), 0);\n+\tstruct quic_shash_table *ht = &quic_hashinfo.shash;\n+\n+\treturn &ht->hash[hash & (ht->size - 1)];\n+}\n+\n+struct quic_uhash_head *quic_udp_sock_head(struct net *net, u16 port)\n+{\n+\tu32 hash = jhash_2words((__force u32)port, net_hash_mix(net), 0);\n+\tstruct quic_uhash_table *ht = &quic_hashinfo.uhash;\n+\n+\treturn &ht->hash[hash & (ht->size - 1)];\n+}\n+\n+u32 quic_addr_hash(struct net *net, union quic_addr *a)\n+{\n+\tu32 addr = (a->sa.sa_family == AF_INET6) ?\n+\t\t   jhash(&a->v6.sin6_addr, 16, 0) :\n+\t\t   (__force u32)a->v4.sin_addr.s_addr;\n+\n+\treturn jhash_3words(addr, (__force u32)a->v4.sin_port,\n+\t\t\t    net_hash_mix(net), 0);\n+}\n+\n+void quic_hash_tables_destroy(void)\n+{\n+\tvfree(quic_hashinfo.shash.hash);\n+\tvfree(quic_hashinfo.lhash.hash);\n+\tvfree(quic_hashinfo.chash.hash);\n+\tvfree(quic_hashinfo.uhash.hash);\n+}\n+\n+static int quic_shash_table_init(struct quic_shash_table *ht, u32 size)\n+{\n+\tint i;\n+\n+\tht->hash = vmalloc_array(size, sizeof(struct quic_shash_head));\n+\tif (!ht->hash)\n+\t\treturn -ENOMEM;\n+\n+\tht->size = size;\n+\tfor (i = 0; i < ht->size; i++) {\n+\t\tspin_lock_init(&ht->hash[i].lock);\n+\t\tINIT_HLIST_NULLS_HEAD(&ht->hash[i].head, i);\n+\t}\n+\treturn 0;\n+}\n+\n+static int quic_uhash_table_init(struct quic_uhash_table *ht, u32 size)\n+{\n+\tint i;\n+\n+\tht->hash = vmalloc_array(size, sizeof(struct quic_uhash_head));\n+\tif (!ht->hash)\n+\t\treturn -ENOMEM;\n+\n+\tht->size = size;\n+\tfor (i = 0; i < ht->size; i++) {\n+\t\tmutex_init(&ht->hash[i].lock);\n+\t\tINIT_HLIST_HEAD(&ht->hash[i].head);\n+\t}\n+\treturn 0;\n+}\n+\n+int quic_hash_tables_init(void)\n+{\n+\tunsigned long nr_pages = totalram_pages();\n+\tu32 limit, size;\n+\tint err;\n+\n+\t/* Scale hash table size based on system memory, similar to SCTP. */\n+\tif (nr_pages >= (128 * 1024))\n+\t\tlimit = nr_pages >> (22 - PAGE_SHIFT);\n+\telse\n+\t\tlimit = nr_pages >> (24 - PAGE_SHIFT);\n+\n+\tlimit = roundup_pow_of_two(limit ?: 1);\n+\n+\t/* Source connection ID table (fast lookup, larger size) */\n+\tsize = min(limit, 64 * 1024U);\n+\terr = quic_shash_table_init(&quic_hashinfo.shash, size);\n+\tif (err)\n+\t\tgoto err;\n+\tsize = min(limit, 16 * 1024U);\n+\terr = quic_shash_table_init(&quic_hashinfo.lhash, size);\n+\tif (err)\n+\t\tgoto err;\n+\terr = quic_shash_table_init(&quic_hashinfo.chash, size);\n+\tif (err)\n+\t\tgoto err;\n+\terr = quic_uhash_table_init(&quic_hashinfo.uhash, size);\n+\tif (err)\n+\t\tgoto err;\n+\treturn 0;\n+err:\n+\tquic_hash_tables_destroy();\n+\treturn err;\n+}\n+\n+/* Returns the number of bytes required to encode a QUIC variable-length\n+ * integer.\n+ */\n+u8 quic_var_len(u64 n)\n+{\n+\tif (n <= QUIC_VARINT_1BYTE_MAX)\n+\t\treturn 1;\n+\tif (n <= QUIC_VARINT_2BYTE_MAX)\n+\t\treturn 2;\n+\tif (n <= QUIC_VARINT_4BYTE_MAX)\n+\t\treturn 4;\n+\treturn 8;\n+}\n+\n+/* Decodes a QUIC variable-length integer from a buffer. */\n+u8 quic_get_var(u8 **pp, u32 *plen, u64 *val)\n+{\n+\tu8 *p = *pp, len;\n+\tu64 v = 0;\n+\n+\tif (!*plen)\n+\t\treturn 0;\n+\n+\tlen = QUIC_VARINT_LENGTH(p);\n+\tif (*plen < len)\n+\t\treturn 0;\n+\n+\tswitch (len) {\n+\tcase 1:\n+\t\tv = *p;\n+\t\tbreak;\n+\tcase 2:\n+\t\tv = get_unaligned_be16(p) & QUIC_VARINT_2BYTE_MAX;\n+\t\tbreak;\n+\tcase 4:\n+\t\tv = get_unaligned_be32(p) & QUIC_VARINT_4BYTE_MAX;\n+\t\tbreak;\n+\tcase 8:\n+\t\tv = get_unaligned_be64(p) & QUIC_VARINT_8BYTE_MAX;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+\n+\t*plen -= len;\n+\t*pp = p + len;\n+\t*val = v;\n+\treturn len;\n+}\n+\n+/* Reads a fixed-length integer from the buffer. */\n+u32 quic_get_int(u8 **pp, u32 *plen, u64 *val, u32 len)\n+{\n+\tu8 *p = *pp;\n+\tu64 v = 0;\n+\n+\tif (*plen < len)\n+\t\treturn 0;\n+\n+\tswitch (len) {\n+\tcase 1:\n+\t\tv = *p;\n+\t\tbreak;\n+\tcase 2:\n+\t\tv = get_unaligned_be16(p);\n+\t\tbreak;\n+\tcase 3:\n+\t\tv = get_unaligned_be24(p);\n+\t\tbreak;\n+\tcase 4:\n+\t\tv = get_unaligned_be32(p);\n+\t\tbreak;\n+\tcase 8:\n+\t\tv = get_unaligned_be64(p);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+\t*plen -= len;\n+\t*pp = p + len;\n+\t*val = v;\n+\treturn len;\n+}\n+\n+u32 quic_get_data(u8 **pp, u32 *plen, u8 *data, u32 len)\n+{\n+\tif (*plen < len)\n+\t\treturn 0;\n+\n+\tmemcpy(data, *pp, len);\n+\t*pp += len;\n+\t*plen -= len;\n+\n+\treturn len;\n+}\n+\n+/* Encodes a value into the QUIC variable-length integer format. */\n+u8 *quic_put_var(u8 *p, u64 num)\n+{\n+\tif (num <= QUIC_VARINT_1BYTE_MAX) {\n+\t\t*p++ = (u8)num;\n+\t\treturn p;\n+\t}\n+\tif (num <= QUIC_VARINT_2BYTE_MAX) {\n+\t\tput_unaligned_be16((u16)num, p);\n+\t\t*p |= QUIC_VARINT_2BYTE_PREFIX;\n+\t\treturn p + 2;\n+\t}\n+\tif (num <= QUIC_VARINT_4BYTE_MAX) {\n+\t\tput_unaligned_be32((u32)num, p);\n+\t\t*p |= QUIC_VARINT_4BYTE_PREFIX;\n+\t\treturn p + 4;\n+\t}\n+\tput_unaligned_be64(num, p);\n+\t*p |= QUIC_VARINT_8BYTE_PREFIX;\n+\treturn p + 8;\n+}\n+\n+/* Writes a fixed-length integer to the buffer in network byte order. */\n+u8 *quic_put_int(u8 *p, u64 num, u8 len)\n+{\n+\tswitch (len) {\n+\tcase 1:\n+\t\t*p++ = (u8)num;\n+\t\treturn p;\n+\tcase 2:\n+\t\tput_unaligned_be16((u16)num, p);\n+\t\treturn p + 2;\n+\tcase 4:\n+\t\tput_unaligned_be32((u32)num, p);\n+\t\treturn p + 4;\n+\tcase 8:\n+\t\tput_unaligned_be64(num, p);\n+\t\treturn p + 8;\n+\tdefault:\n+\t\treturn NULL;\n+\t}\n+}\n+\n+/* Encodes a value as a variable-length integer with explicit length. */\n+u8 *quic_put_varint(u8 *p, u64 num, u8 len)\n+{\n+\tswitch (len) {\n+\tcase 1:\n+\t\t*p++ = (u8)num;\n+\t\treturn p;\n+\tcase 2:\n+\t\tput_unaligned_be16((u16)num, p);\n+\t\t*p |= QUIC_VARINT_2BYTE_PREFIX;\n+\t\treturn p + 2;\n+\tcase 4:\n+\t\tput_unaligned_be32((u32)num, p);\n+\t\t*p |= QUIC_VARINT_4BYTE_PREFIX;\n+\t\treturn p + 4;\n+\tdefault:\n+\t\treturn NULL;\n+\t}\n+}\n+\n+u8 *quic_put_data(u8 *p, u8 *data, u32 len)\n+{\n+\tif (!len)\n+\t\treturn p;\n+\n+\tmemcpy(p, data, len);\n+\treturn p + len;\n+}\n+\n+/* Writes a transport parameter as two varints: ID and value length, followed\n+ * by value.\n+ */\n+u8 *quic_put_param(u8 *p, u16 id, u64 value)\n+{\n+\tp = quic_put_var(p, id);\n+\tp = quic_put_var(p, quic_var_len(value));\n+\treturn quic_put_var(p, value);\n+}\n+\n+/* Reads a QUIC transport parameter value. */\n+u8 quic_get_param(u64 *pdest, u8 **pp, u32 *plen)\n+{\n+\tu64 valuelen;\n+\n+\tif (!quic_get_var(pp, plen, &valuelen))\n+\t\treturn 0;\n+\n+\tif (*plen < valuelen)\n+\t\treturn 0;\n+\n+\tif (quic_get_var(pp, plen, pdest) != valuelen)\n+\t\treturn 0;\n+\n+\treturn (u8)valuelen;\n+}\n+\n+/* rfc9000#section-a.3: DecodePacketNumber()\n+ *\n+ * Reconstructs the full packet number from a truncated one.\n+ */\n+s64 quic_get_num(s64 max_pkt_num, s64 pkt_num, u32 n)\n+{\n+\ts64 expected = max_pkt_num + 1;\n+\ts64 win = BIT_ULL(n * 8);\n+\ts64 hwin = win / 2;\n+\ts64 mask = win - 1;\n+\ts64 cand;\n+\n+\tcand = (expected & ~mask) | pkt_num;\n+\tif (cand <= expected - hwin && cand < BIT_ULL(QUIC_PN_BITS) - win)\n+\t\treturn cand + win;\n+\tif (cand > expected + hwin && cand >= win)\n+\t\treturn cand - win;\n+\treturn cand;\n+}\n+\n+int quic_data_dup(struct quic_data *to, u8 *data, u32 len)\n+{\n+\tif (!len)\n+\t\treturn 0;\n+\n+\tdata = kmemdup(data, len, GFP_ATOMIC);\n+\tif (!data)\n+\t\treturn -ENOMEM;\n+\n+\tkfree(to->data);\n+\tto->data = data;\n+\tto->len = len;\n+\treturn 0;\n+}\n+\n+int quic_data_append(struct quic_data *to, u8 *data, u32 len)\n+{\n+\tu8 *p;\n+\n+\tif (!len)\n+\t\treturn 0;\n+\n+\tp = kzalloc(to->len + len, GFP_ATOMIC);\n+\tif (!p)\n+\t\treturn -ENOMEM;\n+\tp = quic_put_data(p, to->data, to->len);\n+\tp = quic_put_data(p, data, len);\n+\n+\tkfree(to->data);\n+\tto->len = to->len + len;\n+\tto->data = p - to->len;\n+\treturn 0;\n+}\n+\n+/* Check whether 'd2' is equal to any element inside the list 'd1'.\n+ *\n+ * 'd1' is assumed to be a sequence of length-prefixed elements. Each element\n+ * is compared to 'd2' using 'quic_data_cmp()'.\n+ *\n+ * Returns true if a match is found, false otherwise.\n+ */\n+bool quic_data_has(struct quic_data *d1, struct quic_data *d2)\n+{\n+\tstruct quic_data d;\n+\tu64 length;\n+\tu32 len;\n+\tu8 *p;\n+\n+\tfor (p = d1->data, len = d1->len; len; len -= length, p += length) {\n+\t\tif (!quic_get_int(&p, &len, &length, 1) || len < length)\n+\t\t\treturn false;\n+\t\tquic_data(&d, p, length);\n+\t\tif (!quic_data_cmp(&d, d2))\n+\t\t\treturn true;\n+\t}\n+\treturn false;\n+}\n+\n+/* Check if any element of 'd1' is present in the list 'd2'.\n+ *\n+ * Iterates through each element in 'd1', and uses 'quic_data_has()' to check\n+ * for its presence in 'd2'.\n+ *\n+ * Returns true if any match is found, false otherwise.\n+ */\n+bool quic_data_match(struct quic_data *d1, struct quic_data *d2)\n+{\n+\tstruct quic_data d;\n+\tu64 length;\n+\tu32 len;\n+\tu8 *p;\n+\n+\tfor (p = d1->data, len = d1->len; len; len -= length, p += length) {\n+\t\tif (!quic_get_int(&p, &len, &length, 1) || len < length)\n+\t\t\treturn false;\n+\t\tquic_data(&d, p, length);\n+\t\tif (quic_data_has(d2, &d))\n+\t\t\treturn true;\n+\t}\n+\treturn false;\n+}\n+\n+/* Serialize a list of 'quic_data' elements into a comma-separated string.\n+ *\n+ * Each element in 'from' is length-prefixed. This function copies their raw\n+ * content into the output buffer 'to', inserting commas in between. The\n+ * resulting string length is written to '*plen'.\n+ */\n+int quic_data_to_string(u8 *to, u32 *plen, struct quic_data *from)\n+{\n+\tu32 remlen = *plen;\n+\tstruct quic_data d;\n+\tu8 *data = to, *p;\n+\tu64 length;\n+\tu32 len;\n+\n+\tp = from->data;\n+\tlen = from->len;\n+\twhile (len) {\n+\t\tif (!quic_get_int(&p, &len, &length, 1) || len < length)\n+\t\t\treturn -EINVAL;\n+\n+\t\tquic_data(&d, p, length);\n+\t\tif (d.len > remlen)\n+\t\t\treturn -EOVERFLOW;\n+\n+\t\tdata = quic_put_data(data, d.data, d.len);\n+\t\tremlen -= d.len;\n+\t\tp += d.len;\n+\t\tlen -= d.len;\n+\t\tif (len) {\n+\t\t\tif (!remlen)\n+\t\t\t\treturn -EOVERFLOW;\n+\t\t\tdata = quic_put_int(data, ',', 1);\n+\t\t\tremlen--;\n+\t\t}\n+\t}\n+\t*plen = data - to;\n+\treturn 0;\n+}\n+\n+/* Parse a comma-separated string into a 'quic_data' list format.\n+ *\n+ * Each comma-separated token is turned into a length-prefixed element. The\n+ * first byte of each element stores the length. Elements are stored in\n+ * 'to->data', and 'to->len' is updated.\n+ */\n+int quic_data_from_string(struct quic_data *to, u8 *from, u32 len)\n+{\n+\tu32 remlen = to->len;\n+\tstruct quic_data d;\n+\tu8 *p = to->data;\n+\n+\tto->len = 0;\n+\twhile (len) {\n+\t\twhile (len && *from == ' ') {\n+\t\t\tfrom++;\n+\t\t\tlen--;\n+\t\t}\n+\t\tif (!len)\n+\t\t\tbreak;\n+\t\tif (!remlen)\n+\t\t\treturn -EOVERFLOW;\n+\t\td.data = p++;\n+\t\td.len  = 0;\n+\t\tremlen--;\n+\t\twhile (len) {\n+\t\t\tif (*from == ',') {\n+\t\t\t\tfrom++;\n+\t\t\t\tlen--;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tif (!remlen)\n+\t\t\t\treturn -EOVERFLOW;\n+\t\t\t*p++ = *from++;\n+\t\t\tlen--;\n+\t\t\td.len++;\n+\t\t\tremlen--;\n+\t\t}\n+\t\tif (d.len > U8_MAX)\n+\t\t\treturn -EINVAL;\n+\t\t*d.data = (u8)(d.len);\n+\t\tto->len += d.len + 1;\n+\t}\n+\treturn 0;\n+}\ndiff --git a/net/quic/common.h b/net/quic/common.h\nnew file mode 100644\nindex 000000000000..e8aceaecccce\n--- /dev/null\n+++ b/net/quic/common.h\n@@ -0,0 +1,212 @@\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+#include <net/net_namespace.h>\n+\n+#define QUIC_MAX_ACK_DELAY\t(16384 * 1000)\n+#define QUIC_DEF_ACK_DELAY\t25000\n+\n+#define QUIC_STREAM_BIT_FIN\t0x01\n+#define QUIC_STREAM_BIT_LEN\t0x02\n+#define QUIC_STREAM_BIT_OFF\t0x04\n+#define QUIC_STREAM_BIT_MASK\t0x08\n+\n+#define QUIC_CONN_ID_MAX_LEN\t20\n+#define QUIC_CONN_ID_DEF_LEN\t8\n+\n+#define QUIC_PN_MAX_LEN\t\t4 /* For encoded packet number */\n+#define QUIC_PN_BITS\t\t62\n+#define QUIC_PN_MAX\t\t(BIT_ULL(QUIC_PN_BITS) - 1)\n+\n+struct quic_conn_id {\n+\tu8 data[QUIC_CONN_ID_MAX_LEN];\n+\tu8 len;\n+};\n+\n+static inline void quic_conn_id_update(struct quic_conn_id *conn_id, u8 *data,\n+\t\t\t\t       u32 len)\n+{\n+\t/* The caller must ensure len does not exceed QUIC_CONN_ID_MAX_LEN. */\n+\tif (WARN_ON_ONCE(len > QUIC_CONN_ID_MAX_LEN))\n+\t\treturn;\n+\tmemcpy(conn_id->data, data, len);\n+\tconn_id->len = (u8)len;\n+}\n+\n+struct quic_skb_cb {\n+\t/* Callback and temporary context when encryption/decryption completes\n+\t * in async mode\n+\t */\n+\tvoid (*crypto_done)(struct sk_buff *skb, int err);\n+\tvoid *crypto_ctx;\n+\tunion {\n+\t\tstruct sk_buff *last; /* Last packet in bundle on TX */\n+\t\tu64 time; /* Arrival timestamp in UDP tunnel on RX */\n+\t};\n+\ts64 number;  /* Parsed packet number, or the largest previously seen */\n+\tu32 seqno;   /* Dest connection ID number on RX */\n+\tu16 errcode; /* Error code if encryption/decryption fails */\n+\tu16 length;  /* Payload length + packet number length */\n+\n+\tu16 number_offset; /* Offset of packet number field */\n+\tu8 number_len;     /* Length of the packet number field */\n+\tu8 level; /* Encryption level: Initial, Handshake, App, or Early */\n+\n+\tu8 key_update:1; /* Key update triggered by this packet */\n+\tu8 key_phase:1;  /* Key phase used (0 or 1) */\n+\tu8 backlog:1;    /* Enqueued into backlog list */\n+\tu8 resume:1;     /* Crypto already processed (encrypted or decrypted) */\n+\tu8 path:1;       /* Packet arrived from a new or migrating path */\n+\tu8 ecn:2;        /* ECN marking used on TX */\n+};\n+\n+#define QUIC_SKB_CB(skb)\t((struct quic_skb_cb *)&((skb)->cb[0]))\n+\n+struct quichdr {\n+#if defined(__LITTLE_ENDIAN_BITFIELD)\n+\t__u8 pnl:2,\n+\t     key:1,\n+\t     reserved:2,\n+\t     spin:1,\n+\t     fixed:1,\n+\t     form:1;\n+#elif defined(__BIG_ENDIAN_BITFIELD)\n+\t__u8 form:1,\n+\t     fixed:1,\n+\t     spin:1,\n+\t     reserved:2,\n+\t     key:1,\n+\t     pnl:2;\n+#endif\n+};\n+\n+static inline struct quichdr *quic_hdr(struct sk_buff *skb)\n+{\n+\treturn (struct quichdr *)skb->data;\n+}\n+\n+struct quichshdr {\n+#if defined(__LITTLE_ENDIAN_BITFIELD)\n+\t__u8 pnl:2,\n+\t     reserved:2,\n+\t     type:2,\n+\t     fixed:1,\n+\t     form:1;\n+#elif defined(__BIG_ENDIAN_BITFIELD)\n+\t__u8 form:1,\n+\t     fixed:1,\n+\t     type:2,\n+\t     reserved:2,\n+\t     pnl:2;\n+#endif\n+};\n+\n+static inline struct quichshdr *quic_hshdr(struct sk_buff *skb)\n+{\n+\treturn (struct quichshdr *)skb->data;\n+}\n+\n+union quic_addr {\n+\tstruct sockaddr_in6 v6;\n+\tstruct sockaddr_in v4;\n+\tstruct sockaddr sa;\n+};\n+\n+static inline union quic_addr *quic_addr(const void *addr)\n+{\n+\treturn (union quic_addr *)addr;\n+}\n+\n+struct quic_shash_head {\n+\tstruct hlist_nulls_head\thead;\n+\tspinlock_t\t\tlock; /* Protects 'head' in atomic context */\n+};\n+\n+struct quic_shash_table {\n+\tstruct quic_shash_head *hash;\n+\tu32 size;\n+};\n+\n+struct quic_uhash_head {\n+\tstruct hlist_head\thead;\n+\tstruct mutex\t\tlock; /* Protects 'head' in process context */\n+};\n+\n+struct quic_uhash_table {\n+\tstruct quic_uhash_head *hash;\n+\tu32 size;\n+};\n+\n+struct quic_data {\n+\tu8 *data;\n+\tu32 len;\n+};\n+\n+static inline struct quic_data *quic_data(struct quic_data *d, u8 *data,\n+\t\t\t\t\t  u32 len)\n+{\n+\td->data = data;\n+\td->len  = len;\n+\treturn d;\n+}\n+\n+static inline int quic_data_cmp(struct quic_data *d1, struct quic_data *d2)\n+{\n+\treturn d1->len != d2->len || memcmp(d1->data, d2->data, d1->len);\n+}\n+\n+static inline void quic_data_free(struct quic_data *d)\n+{\n+\tkfree(d->data);\n+\td->data = NULL;\n+\td->len = 0;\n+}\n+\n+static inline u64 quic_ktime_get_us(void)\n+{\n+\treturn ktime_to_us(ktime_get());\n+}\n+\n+u32 quic_sock_hash(struct net *net, union quic_addr *s, union quic_addr *d);\n+struct quic_shash_head *quic_sock_head(u32 hash);\n+u32 quic_sock_hash_size(void);\n+\n+u32 quic_listen_sock_hash(struct net *net, u16 port);\n+struct quic_shash_head *quic_listen_sock_head(u32 hash);\n+u32 quic_listen_sock_hash_size(void);\n+\n+struct quic_shash_head *quic_source_conn_id_head(struct net *net, u8 *scid,\n+\t\t\t\t\t\t u32 len);\n+struct quic_uhash_head *quic_udp_sock_head(struct net *net, u16 port);\n+u32 quic_addr_hash(struct net *net, union quic_addr *a);\n+\n+void quic_hash_tables_destroy(void);\n+int quic_hash_tables_init(void);\n+\n+u32 quic_get_data(u8 **pp, u32 *plen, u8 *data, u32 len);\n+u32 quic_get_int(u8 **pp, u32 *plen, u64 *val, u32 len);\n+s64 quic_get_num(s64 max_pkt_num, s64 pkt_num, u32 n);\n+u8 quic_get_param(u64 *pdest, u8 **pp, u32 *plen);\n+u8 quic_get_var(u8 **pp, u32 *plen, u64 *val);\n+u8 quic_var_len(u64 n);\n+\n+u8 *quic_put_param(u8 *p, u16 id, u64 value);\n+u8 *quic_put_data(u8 *p, u8 *data, u32 len);\n+u8 *quic_put_varint(u8 *p, u64 num, u8 len);\n+u8 *quic_put_int(u8 *p, u64 num, u8 len);\n+u8 *quic_put_var(u8 *p, u64 num);\n+\n+int quic_data_from_string(struct quic_data *to, u8 *from, u32 len);\n+int quic_data_to_string(u8 *to, u32 *plen, struct quic_data *from);\n+\n+bool quic_data_match(struct quic_data *d1, struct quic_data *d2);\n+bool quic_data_has(struct quic_data *d1, struct quic_data *d2);\n+int quic_data_append(struct quic_data *to, u8 *data, u32 len);\n+int quic_data_dup(struct quic_data *to, u8 *data, u32 len);\ndiff --git a/net/quic/protocol.c b/net/quic/protocol.c\nindex 73ccbddeff79..807e2a228ba8 100644\n--- a/net/quic/protocol.c\n+++ b/net/quic/protocol.c\n@@ -309,6 +309,9 @@ static __init int quic_init(void)\n \tint max_share, err = -ENOMEM;\n \tunsigned long limit;\n \n+\tBUILD_BUG_ON(sizeof(struct quic_skb_cb) >\n+\t\t     sizeof_field(struct sk_buff, cb));\n+\n \t/* Set QUIC memory limits based on available system memory, similar to\n \t * sctp_init().\n \t */\n@@ -333,6 +336,10 @@ static __init int quic_init(void)\n \tif (err)\n \t\tgoto err_percpu_counter;\n \n+\terr = quic_hash_tables_init();\n+\tif (err)\n+\t\tgoto err_hash;\n+\n \terr = register_pernet_subsys(&quic_net_ops);\n \tif (err)\n \t\tgoto err_def_ops;\n@@ -350,6 +357,8 @@ static __init int quic_init(void)\n err_protosw:\n \tunregister_pernet_subsys(&quic_net_ops);\n err_def_ops:\n+\tquic_hash_tables_destroy();\n+err_hash:\n \tpercpu_counter_destroy(&quic_sockets_allocated);\n err_percpu_counter:\n \treturn err;\n@@ -362,6 +371,7 @@ static __exit void quic_exit(void)\n #endif\n \tquic_protosw_exit();\n \tunregister_pernet_subsys(&quic_net_ops);\n+\tquic_hash_tables_destroy();\n \tpercpu_counter_destroy(&quic_sockets_allocated);\n \tpr_info(\"quic: exit\\n\");\n }\ndiff --git a/net/quic/socket.c b/net/quic/socket.c\nindex 6605266eaa59..6a742fe57df1 100644\n--- a/net/quic/socket.c\n+++ b/net/quic/socket.c\n@@ -50,6 +50,10 @@ static int quic_init_sock(struct sock *sk)\n \n static void quic_destroy_sock(struct sock *sk)\n {\n+\tquic_data_free(quic_ticket(sk));\n+\tquic_data_free(quic_token(sk));\n+\tquic_data_free(quic_alpn(sk));\n+\n \tsk_sockets_allocated_dec(sk);\n \tsock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);\n }\ndiff --git a/net/quic/socket.h b/net/quic/socket.h\nindex 98d3f738e909..9a2f4b851676 100644\n--- a/net/quic/socket.h\n+++ b/net/quic/socket.h\n@@ -10,6 +10,8 @@\n \n #include <net/udp_tunnel.h>\n \n+#include \"common.h\"\n+\n #include \"protocol.h\"\n \n extern struct proto quic_prot;\n@@ -25,6 +27,10 @@ enum quic_state {\n struct quic_sock {\n \tstruct inet_sock\t\tinet;\n \tstruct list_head\t\treqs;\n+\n+\tstruct quic_data\t\tticket;\n+\tstruct quic_data\t\ttoken;\n+\tstruct quic_data\t\talpn;\n };\n \n struct quic6_sock {\n@@ -42,6 +48,21 @@ static inline struct list_head *quic_reqs(const struct sock *sk)\n \treturn &quic_sk(sk)->reqs;\n }\n \n+static inline struct quic_data *quic_token(const struct sock *sk)\n+{\n+\treturn &quic_sk(sk)->token;\n+}\n+\n+static inline struct quic_data *quic_ticket(const struct sock *sk)\n+{\n+\treturn &quic_sk(sk)->ticket;\n+}\n+\n+static inline struct quic_data *quic_alpn(const struct sock *sk)\n+{\n+\treturn &quic_sk(sk)->alpn;\n+}\n+\n static inline bool quic_is_serv(const struct sock *sk)\n {\n \treturn !!sk->sk_max_ack_backlog;\n",
    "prefixes": [
        "net-next",
        "v11",
        "03/15"
    ]
}