From: Xin Long <lucien.xin@gmail.com>
To: network dev <netdev@vger.kernel.org>, quic@lists.linux.dev
Cc: davem@davemloft.net, kuba@kernel.org,
Eric Dumazet <edumazet@google.com>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Stefan Metzmacher <metze@samba.org>,
Moritz Buhl <mbuhl@openbsd.org>,
Tyler Fanelli <tfanelli@redhat.com>,
Pengtao He <hepengtao@xiaomi.com>,
Thomas Dreibholz <dreibh@simula.no>,
linux-cifs@vger.kernel.org, Steve French <smfrench@gmail.com>,
Namjae Jeon <linkinjeon@kernel.org>,
Paulo Alcantara <pc@manguebit.com>, Tom Talpey <tom@talpey.com>,
kernel-tls-handshake@lists.linux.dev,
Chuck Lever <chuck.lever@oracle.com>,
Jeff Layton <jlayton@kernel.org>,
Steve Dickson <steved@redhat.com>,
Hannes Reinecke <hare@suse.de>,
Alexander Aring <aahringo@redhat.com>,
David Howells <dhowells@redhat.com>,
Matthieu Baerts <matttbe@kernel.org>,
John Ericson <mail@johnericson.me>,
Cong Wang <xiyou.wangcong@gmail.com>,
"D . Wythe" <alibuda@linux.alibaba.com>,
Jason Baron <jbaron@akamai.com>,
illiliti <illiliti@protonmail.com>,
Sabrina Dubroca <sd@queasysnail.net>,
Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
Daniel Stenberg <daniel@haxx.se>,
Andy Gospodarek <andrew.gospodarek@broadcom.com>,
"Marc E . Fiuczynski" <marc@fiuczynski.com>
Subject: Re: [PATCH net-next v11 06/15] quic: add stream management
Date: Thu, 26 Mar 2026 11:06:26 -0400 [thread overview]
Message-ID: <CADvbK_eXUfnGGQgGc_k-ecCW3-Co1MpGb7UvMgLonPy3HRhyFA@mail.gmail.com> (raw)
In-Reply-To: <91c6fd0a44eb15a98f945171ead8062badb89a60.1774410440.git.lucien.xin@gmail.com>
On Tue, Mar 24, 2026 at 11:49 PM Xin Long <lucien.xin@gmail.com> wrote:
>
> This patch introduces 'struct quic_stream_table' for managing QUIC streams,
> each represented by 'struct quic_stream'.
>
> It implements mechanisms for acquiring and releasing streams on both the
> send and receive paths, ensuring efficient lifecycle management during
> transmission and reception.
>
> - quic_stream_get(): Acquire a send-side stream by ID and flags during
> TX path, or a receive-side stream by ID during RX path.
>
> - quic_stream_put(): Release a send-side stream when sending is done,
> or a receive-side stream when receiving is done.
>
> It includes logic to detect when stream ID limits are reached and when
> control frames should be sent to update or request limits from the peer.
>
> - quic_stream_id_exceeds(): Check a stream ID would exceed local (recv)
> or peer (send) limits.
>
> - quic_stream_max_streams_update(): Determines whether a
> MAX_STREAMS_UNI/BIDI frame should be sent to the peer.
>
> Note stream hash table is per socket, the operations on it are always
> protected by the sock lock.
>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> Acked-by: Paolo Abeni <pabeni@redhat.com>
> ---
> v3:
> - Merge send/recv stream helpers into unified functions to reduce code:
> * quic_stream_id_send/recv() → quic_stream_id_valid()
> * quic_stream_id_send/recv_closed() → quic_stream_id_closed()
> * quic_stream_id_send/recv_exceeds() → quic_stream_id_exceeds()
> (pointed out by Paolo).
> - Clarify in changelog that stream hash table is always protected by sock
> lock (suggested by Paolo).
> - quic_stream_init/free(): adjust for new hashtable type; call
> quic_stream_delete() in quic_stream_free() to avoid open-coded logic.
> - Receiving streams: delete stream only when fully read or reset, instead
> of when no data was received. Prevents freeing a stream while a FIN
> with no data is still queued.
> v4:
> - Replace struct quic_shash_table with struct hlist_head for the
> stream hashtable. Since they are protected by the socket lock,
> no per-chain lock is needed.
> - Initialize stream to NULL in stream creation functions to avoid
> warnings from Smatch (reported by Simon).
> - Allocate send streams with GFP_KERNEL_ACCOUNT and receive streams
> with GFP_ATOMIC | __GFP_ACCOUNT for memory accounting (suggested
> by Paolo).
> v5:
> - Introduce struct quic_stream_limits to merge quic_stream_send_create()
> and quic_stream_recv_create(), and to simplify quic_stream_get_param()
> (suggested by Paolo).
> - Annotate the sock-lock requirement for quic_stream_send/recv_get()
> and quic_stream_send/recv_put() (notied by Paolo).
> - Add quic_stream_bidi_put() to deduplicate the common logic between
> quic_stream_send_put() and quic_stream_recv_put().
> - Remove the unnecessary check when incrementing
> streams->send.next_bidi/uni_stream_id in quic_stream_create().
> - Remove the unused 'is_serv' parameter from quic_stream_get_param().
> v7:
> - Free the allocated streams on error path in quic_stream_create() (noted
> by Paolo).
> - Merge quic_stream_send_get/put() and quic_stream_recv_get/put() helpers
> to quic_stream_get/put() (suggested by Paolo).
> - Add more comments in quic_stream_id_exceeds() and quic_stream_create().
> v8:
> - Replace bitfields with plain u8 in struct quic_stream_limits and struct
> quic_stream (suggested by Paolo).
> v9:
> - Fix grammar in the comment for quic_stream::send.window.
> v10:
> - Move quic_stream_init() to after sock_prot_inuse_add() ensure counters
> are incremented before any early return paths in quic_init_sock(),
> preventing underflow in quic_destroy_sock() (noted by AI review).
> - Initialize the output parameters '*max_uni' and '*max_bidi' to 0 at the
> start of quic_stream_max_streams_update()
> - Use 'stream->recv.state > QUIC_STREAM_RECV_STATE_RECVD' instead of '!='
> for clearer intent.
> - Simplify some state checks in quic_stream_put() by using range
> comparisons (> or <) instead of multiple != conditions.
> - streams_uni/bidi are u16 type, and their overflow is already prevented
> by QUIC_MAX_STREAMS indirectly. Update comment in quic_stream_create().
> - Replace open-coded kzalloc(sizeof(*stream)) with kzalloc_obj(*stream)
> in quic_stream_create().
> v11:
> - Set maximum line length to 80 characters.
> - Change is_serv parameter type to bool in quic_stream_id_local().
> ---
> net/quic/Makefile | 2 +-
> net/quic/socket.c | 5 +
> net/quic/socket.h | 8 +
> net/quic/stream.c | 444 ++++++++++++++++++++++++++++++++++++++++++++++
> net/quic/stream.h | 133 ++++++++++++++
> 5 files changed, 591 insertions(+), 1 deletion(-)
> create mode 100644 net/quic/stream.c
> create mode 100644 net/quic/stream.h
>
> diff --git a/net/quic/Makefile b/net/quic/Makefile
> index 13bf4a4e5442..094e9da5d739 100644
> --- a/net/quic/Makefile
> +++ b/net/quic/Makefile
> @@ -5,4 +5,4 @@
>
> obj-$(CONFIG_IP_QUIC) += quic.o
>
> -quic-y := common.o family.o protocol.o socket.o
> +quic-y := common.o family.o protocol.o socket.o stream.o
> diff --git a/net/quic/socket.c b/net/quic/socket.c
> index 8dc2cb7628db..0006668551f4 100644
> --- a/net/quic/socket.c
> +++ b/net/quic/socket.c
> @@ -45,11 +45,16 @@ static int quic_init_sock(struct sock *sk)
> sk_sockets_allocated_inc(sk);
> sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
>
> + if (quic_stream_init(quic_streams(sk)))
> + return -ENOMEM;
> +
> return 0;
> }
>
> static void quic_destroy_sock(struct sock *sk)
> {
> + quic_stream_free(quic_streams(sk));
> +
> quic_data_free(quic_ticket(sk));
> quic_data_free(quic_token(sk));
> quic_data_free(quic_alpn(sk));
> diff --git a/net/quic/socket.h b/net/quic/socket.h
> index 61df0c5867be..e76737b9b74b 100644
> --- a/net/quic/socket.h
> +++ b/net/quic/socket.h
> @@ -13,6 +13,7 @@
>
> #include "common.h"
> #include "family.h"
> +#include "stream.h"
>
> #include "protocol.h"
>
> @@ -33,6 +34,8 @@ struct quic_sock {
> struct quic_data ticket;
> struct quic_data token;
> struct quic_data alpn;
> +
> + struct quic_stream_table streams;
> };
>
> struct quic6_sock {
> @@ -65,6 +68,11 @@ static inline struct quic_data *quic_alpn(const struct sock *sk)
> return &quic_sk(sk)->alpn;
> }
>
> +static inline struct quic_stream_table *quic_streams(const struct sock *sk)
> +{
> + return &quic_sk(sk)->streams;
> +}
> +
> static inline bool quic_is_serv(const struct sock *sk)
> {
> return !!sk->sk_max_ack_backlog;
> diff --git a/net/quic/stream.c b/net/quic/stream.c
> new file mode 100644
> index 000000000000..4d980f9b03ce
> --- /dev/null
> +++ b/net/quic/stream.c
> @@ -0,0 +1,444 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/* QUIC kernel implementation
> + * (C) Copyright Red Hat Corp. 2023
> + *
> + * This file is part of the QUIC kernel implementation
> + *
> + * Initialization/cleanup for QUIC protocol support.
> + *
> + * Written or modified by:
> + * Xin Long <lucien.xin@gmail.com>
> + */
> +
> +#include <linux/quic.h>
> +
> +#include "common.h"
> +#include "stream.h"
> +
> +/* Check if a stream ID is valid for sending or receiving. */
> +static bool quic_stream_id_valid(s64 stream_id, bool is_serv, bool send)
> +{
> + u8 type = (stream_id & QUIC_STREAM_TYPE_MASK);
> +
> + if (send) {
> + if (is_serv)
> + return type != QUIC_STREAM_TYPE_CLIENT_UNI;
> + return type != QUIC_STREAM_TYPE_SERVER_UNI;
> + }
> + if (is_serv)
> + return type != QUIC_STREAM_TYPE_SERVER_UNI;
> + return type != QUIC_STREAM_TYPE_CLIENT_UNI;
> +}
> +
> +/* Check if a stream ID was initiated locally. */
> +static bool quic_stream_id_local(s64 stream_id, bool is_serv)
> +{
> + return is_serv ^ !(stream_id & QUIC_STREAM_TYPE_SERVER_MASK);
> +}
> +
> +/* Check if a stream ID represents a unidirectional stream. */
> +static bool quic_stream_id_uni(s64 stream_id)
> +{
> + return stream_id & QUIC_STREAM_TYPE_UNI_MASK;
> +}
> +
> +#define QUIC_STREAM_HT_SIZE 64
> +
> +static struct hlist_head *quic_stream_head(struct quic_stream_table *streams,
> + s64 stream_id)
> +{
> + return &streams->head[stream_id & (QUIC_STREAM_HT_SIZE - 1)];
> +}
> +
> +struct quic_stream *quic_stream_find(struct quic_stream_table *streams,
> + s64 stream_id)
> +{
> + struct hlist_head *head = quic_stream_head(streams, stream_id);
> + struct quic_stream *stream;
> +
> + hlist_for_each_entry(stream, head, node) {
> + if (stream->id == stream_id)
> + break;
> + }
> + return stream;
> +}
> +
> +static void quic_stream_add(struct quic_stream_table *streams,
> + struct quic_stream *stream)
> +{
> + struct hlist_head *head;
> +
> + head = quic_stream_head(streams, stream->id);
> + hlist_add_head(&stream->node, head);
> +}
> +
> +static void quic_stream_delete(struct quic_stream *stream)
> +{
> + hlist_del_init(&stream->node);
> + kfree(stream);
> +}
> +
> +/* Create and register new streams for sending or receiving. */
> +static struct quic_stream *quic_stream_create(struct quic_stream_table *streams,
> + s64 max_stream_id, bool send,
> + bool is_serv)
> +{
> + struct quic_stream_limits *limits = &streams->send;
> + struct quic_stream *pos, *stream = NULL;
> + gfp_t gfp = GFP_KERNEL_ACCOUNT;
> + struct hlist_node *tmp;
> + HLIST_HEAD(head);
> + s64 stream_id;
> + u32 count = 0;
> +
> + if (!send) {
> + limits = &streams->recv;
> + gfp = GFP_ATOMIC | __GFP_ACCOUNT;
> + }
> + stream_id = limits->next_bidi_stream_id;
> + if (quic_stream_id_uni(max_stream_id))
> + stream_id = limits->next_uni_stream_id;
> +
> + /* rfc9000#section-2.1: A stream ID that is used out of order results in
> + * all streams of that type with lower-numbered stream IDs also being
> + * opened.
> + */
> + while (stream_id <= max_stream_id) {
> + stream = kzalloc_obj(*stream, gfp);
> + if (!stream)
> + goto free;
> +
> + stream->id = stream_id;
> + if (quic_stream_id_uni(stream_id)) {
> + if (send) {
> + stream->send.max_bytes =
> + limits->max_stream_data_uni;
> + } else {
> + stream->recv.max_bytes =
> + limits->max_stream_data_uni;
> + stream->recv.window = stream->recv.max_bytes;
> + }
> + hlist_add_head(&stream->node, &head);
> + stream_id += QUIC_STREAM_ID_STEP;
> + continue;
> + }
> +
> + if (quic_stream_id_local(stream_id, is_serv)) {
> + stream->send.max_bytes =
> + streams->send.max_stream_data_bidi_remote;
> + stream->recv.max_bytes =
> + streams->recv.max_stream_data_bidi_local;
> + } else {
> + stream->send.max_bytes =
> + streams->send.max_stream_data_bidi_local;
> + stream->recv.max_bytes =
> + streams->recv.max_stream_data_bidi_remote;
> + }
> + stream->recv.window = stream->recv.max_bytes;
> + hlist_add_head(&stream->node, &head);
> + stream_id += QUIC_STREAM_ID_STEP;
> + }
> +
> + hlist_for_each_entry_safe(pos, tmp, &head, node) {
> + hlist_del_init(&pos->node);
> + quic_stream_add(streams, pos);
> + count++;
> + }
> +
> + /* Streams must be opened sequentially. Update the next stream ID so the
> + * correct starting point is known if an out-of-order open is requested.
> + * Note overflow of next_uni/bidi_stream_id is impossible with s64.
> + */
> + if (quic_stream_id_uni(stream_id)) {
> + limits->next_uni_stream_id = stream_id;
> + limits->streams_uni += count;
> + return stream;
> + }
> +
> + limits->next_bidi_stream_id = stream_id;
> + limits->streams_bidi += count;
> + return stream;
> +
> +free:
> + hlist_for_each_entry_safe(pos, tmp, &head, node) {
> + hlist_del_init(&pos->node);
> + kfree(pos);
> + }
> + return NULL;
> +}
> +
> +/* Check if a send or receive stream ID is already closed. */
> +static bool quic_stream_id_closed(struct quic_stream_table *streams,
> + s64 stream_id, bool send)
> +{
> + struct quic_stream_limits *limits = send ? &streams->send :
> + &streams->recv;
> +
> + if (quic_stream_id_uni(stream_id))
> + return stream_id < limits->next_uni_stream_id;
> + return stream_id < limits->next_bidi_stream_id;
> +}
> +
> +/* Check if a stream ID would exceed local (recv) or peer (send) limits. */
> +bool quic_stream_id_exceeds(struct quic_stream_table *streams, s64 stream_id,
> + bool send)
> +{
> + u64 nstreams;
> +
> + if (!send) {
> + /* recv.max_uni_stream_id is updated in
> + * quic_stream_max_streams_update() already based on
> + * next_uni/bidi_stream_id, max_streams_uni/bidi, and
> + * streams_uni/bidi, so only recv.max_uni_stream_id needs to be
> + * checked.
> + */
> + if (quic_stream_id_uni(stream_id))
> + return stream_id > streams->recv.max_uni_stream_id;
> +
> + return stream_id > streams->recv.max_bidi_stream_id;
> + }
> +
> + if (quic_stream_id_uni(stream_id)) {
> + if (stream_id > streams->send.max_uni_stream_id)
> + return true;
> + stream_id -= streams->send.next_uni_stream_id;
> + nstreams = quic_stream_id_to_streams(stream_id);
> +
> + return nstreams + streams->send.streams_uni >
> + streams->send.max_streams_uni;
> + }
> +
> + if (stream_id > streams->send.max_bidi_stream_id)
> + return true;
> + stream_id -= streams->send.next_bidi_stream_id;
> + nstreams = quic_stream_id_to_streams(stream_id);
> +
> + return nstreams + streams->send.streams_bidi >
> + streams->send.max_streams_bidi;
> +}
> +
> +/* Get or create a send or recv stream by ID. Requires sock lock held. */
> +struct quic_stream *quic_stream_get(struct quic_stream_table *streams,
> + s64 stream_id, u32 flags, bool is_serv,
> + bool send)
> +{
> + struct quic_stream *stream;
> +
> + if (!quic_stream_id_valid(stream_id, is_serv, send))
> + return ERR_PTR(-EINVAL);
> +
> + stream = quic_stream_find(streams, stream_id);
> + if (stream) {
> + if (send && (flags & MSG_QUIC_STREAM_NEW) &&
> + stream->send.state != QUIC_STREAM_SEND_STATE_READY)
> + return ERR_PTR(-EINVAL);
> + return stream;
> + }
> +
> + if (!send && quic_stream_id_local(stream_id, is_serv)) {
> + if (quic_stream_id_closed(streams, stream_id, !send))
> + return ERR_PTR(-ENOSTR);
> + return ERR_PTR(-EINVAL);
> + }
> +
> + if (quic_stream_id_closed(streams, stream_id, send))
> + return ERR_PTR(-ENOSTR);
> +
> + if (send && !(flags & MSG_QUIC_STREAM_NEW))
> + return ERR_PTR(-EINVAL);
> +
> + if (quic_stream_id_exceeds(streams, stream_id, send))
> + return ERR_PTR(-EAGAIN);
> +
> + stream = quic_stream_create(streams, stream_id, send, is_serv);
> + if (!stream)
> + return ERR_PTR(-ENOSTR);
> +
> + if (send || quic_stream_id_valid(stream_id, is_serv, !send))
> + streams->send.active_stream_id = stream_id;
> +
> + return stream;
> +}
> +
> +/* Release or clean up a send or recv stream. This function updates stream
> + * counters and state when a send stream has either successfully sent all data
> + * or has been reset, or when a recv stream has either consumed all data or has
> + * been reset. Requires sock lock held.
> + */
> +void quic_stream_put(struct quic_stream_table *streams,
> + struct quic_stream *stream, bool is_serv, bool send)
> +{
> + if (quic_stream_id_uni(stream->id)) {
> + if (send) {
> + /* For uni streams, decrement uni count and delete
> + * immediately.
> + */
> + streams->send.streams_uni--;
> + quic_stream_delete(stream);
> + return;
> + }
> + /* For uni streams, decrement uni count and mark done. */
> + if (!stream->recv.done) {
> + stream->recv.done = 1;
> + streams->recv.streams_uni--;
> + streams->recv.uni_pending = 1;
> + }
> + /* Delete stream if fully read or reset. */
> + if (stream->recv.state > QUIC_STREAM_RECV_STATE_RECVD)
> + quic_stream_delete(stream);
> + return;
> + }
> +
> + if (send) {
> + /* For bidi streams, only proceed if receive side is in a final
> + * state.
> + */
> + if (stream->recv.state < QUIC_STREAM_RECV_STATE_RECVD)
> + return;
> + } else {
> + /* For bidi streams, only proceed if send side is in a final
> + * state.
> + */
> + if (stream->send.state != QUIC_STREAM_SEND_STATE_RECVD &&
> + stream->send.state != QUIC_STREAM_SEND_STATE_RESET_RECVD)
> + return;
> + }
> +
> + if (quic_stream_id_local(stream->id, is_serv)) {
> + /* Local-initiated stream: mark send done and decrement
> + * send.bidi count.
> + */
> + if (!stream->send.done) {
> + stream->send.done = 1;
> + streams->send.streams_bidi--;
> + }
> + } else {
> + /* Remote-initiated stream: mark recv done and decrement recv
> + * bidi count.
> + */
> + if (!stream->recv.done) {
> + stream->recv.done = 1;
> + streams->recv.streams_bidi--;
> + streams->recv.bidi_pending = 1;
> + }
> + }
> +
> + /* Delete stream if fully read or reset. */
> + if (stream->recv.state > QUIC_STREAM_RECV_STATE_RECVD)
> + quic_stream_delete(stream);
> +}
> +
> +/* Updates the maximum allowed incoming stream IDs if any streams were recently
> + * closed. Recalculates the max_uni and max_bidi stream ID limits based on the
> + * number of open streams and whether any were marked for deletion.
> + *
> + * Returns true if either max_uni or max_bidi was updated, indicating that a
> + * MAX_STREAMS_UNI or MAX_STREAMS_BIDI frame should be sent to the peer.
> + */
> +bool quic_stream_max_streams_update(struct quic_stream_table *streams,
> + s64 *max_uni, s64 *max_bidi)
> +{
> + s64 max, rem;
> +
> + *max_uni = 0;
> + *max_bidi = 0;
> + if (streams->recv.uni_pending) {
> + rem = streams->recv.max_streams_uni - streams->recv.streams_uni;
> + max = streams->recv.next_uni_stream_id - QUIC_STREAM_ID_STEP +
> + (rem << QUIC_STREAM_TYPE_BITS);
> +
> + streams->recv.max_uni_stream_id = max;
> + *max_uni = quic_stream_id_to_streams(max);
> + streams->recv.uni_pending = 0;
> + }
> + if (streams->recv.bidi_pending) {
> + rem = streams->recv.max_streams_bidi -
> + streams->recv.streams_bidi;
> + max = streams->recv.next_bidi_stream_id - QUIC_STREAM_ID_STEP +
> + (rem << QUIC_STREAM_TYPE_BITS);
> +
> + streams->recv.max_bidi_stream_id = max;
> + *max_bidi = quic_stream_id_to_streams(max);
> + streams->recv.bidi_pending = 0;
> + }
> +
> + return *max_uni || *max_bidi;
> +}
> +
> +int quic_stream_init(struct quic_stream_table *streams)
> +{
> + struct hlist_head *head;
> + int i;
> +
> + head = kmalloc_array(QUIC_STREAM_HT_SIZE, sizeof(*head), GFP_KERNEL);
> + if (!head)
> + return -ENOMEM;
> + for (i = 0; i < QUIC_STREAM_HT_SIZE; i++)
> + INIT_HLIST_HEAD(&head[i]);
> + streams->head = head;
> + return 0;
> +}
> +
> +void quic_stream_free(struct quic_stream_table *streams)
> +{
> + struct quic_stream *stream;
> + struct hlist_head *head;
> + struct hlist_node *tmp;
> + int i;
> +
> + if (!streams->head)
> + return;
> +
> + for (i = 0; i < QUIC_STREAM_HT_SIZE; i++) {
> + head = &streams->head[i];
> + hlist_for_each_entry_safe(stream, tmp, head, node)
> + quic_stream_delete(stream);
> + }
> + kfree(streams->head);
The AI report on
https://netdev-ai.bots.linux.dev/ai-review.html?id=1624d906-c0b6-4e12-a63f-5cbfc51b660e#patch-5
is false positive.
As the sk_alloc() calls sk_prot_alloc() with __GFP_ZERO, and the streams->head
is always initialized to NULL.
next prev parent reply other threads:[~2026-03-26 15:06 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-25 3:47 [PATCH net-next v11 00/15] net: introduce QUIC infrastructure and core subcomponents Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 01/15] net: define IPPROTO_QUIC and SOL_QUIC constants Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 02/15] net: build socket infrastructure for QUIC protocol Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 03/15] quic: provide common utilities and data structures Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 04/15] quic: provide family ops for address and protocol Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 05/15] quic: provide quic.h header files for kernel and userspace Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 06/15] quic: add stream management Xin Long
2026-03-26 15:06 ` Xin Long [this message]
2026-03-26 20:07 ` Jakub Kicinski
2026-03-26 21:48 ` Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 07/15] quic: add connection id management Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 08/15] quic: add path management Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 09/15] quic: add congestion control Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 10/15] quic: add packet number space Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 11/15] quic: add crypto key derivation and installation Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 12/15] quic: add crypto packet encryption and decryption Xin Long
2026-03-26 15:10 ` Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 13/15] quic: add timer management Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 14/15] quic: add packet builder base Xin Long
2026-03-25 3:47 ` [PATCH net-next v11 15/15] quic: add packet parser base Xin Long
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CADvbK_eXUfnGGQgGc_k-ecCW3-Co1MpGb7UvMgLonPy3HRhyFA@mail.gmail.com \
--to=lucien.xin@gmail.com \
--cc=aahringo@redhat.com \
--cc=alibuda@linux.alibaba.com \
--cc=andrew.gospodarek@broadcom.com \
--cc=chuck.lever@oracle.com \
--cc=daniel@haxx.se \
--cc=davem@davemloft.net \
--cc=dhowells@redhat.com \
--cc=dreibh@simula.no \
--cc=edumazet@google.com \
--cc=hare@suse.de \
--cc=hepengtao@xiaomi.com \
--cc=horms@kernel.org \
--cc=illiliti@protonmail.com \
--cc=jbaron@akamai.com \
--cc=jlayton@kernel.org \
--cc=kernel-tls-handshake@lists.linux.dev \
--cc=kuba@kernel.org \
--cc=linkinjeon@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=mail@johnericson.me \
--cc=marc@fiuczynski.com \
--cc=marcelo.leitner@gmail.com \
--cc=matttbe@kernel.org \
--cc=mbuhl@openbsd.org \
--cc=metze@samba.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pc@manguebit.com \
--cc=quic@lists.linux.dev \
--cc=sd@queasysnail.net \
--cc=smfrench@gmail.com \
--cc=steved@redhat.com \
--cc=tfanelli@redhat.com \
--cc=tom@talpey.com \
--cc=xiyou.wangcong@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox