From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oa1-f42.google.com (mail-oa1-f42.google.com [209.85.160.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9DD5E396B7D for ; Thu, 15 Jan 2026 16:53:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.42 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768496008; cv=none; b=QDblxKOqF6GznJt2JUXQqejSGhPE8v3n0zWPybI1cIxc4w4c4w4gvOIkBNdAUkB7r2OckLuA8TEnwq59R6icsE2VQgTh5wvCkanKDZ+MaxiQi1K4BhdMyGH1Hs/1FzrKLV3nUw05yn6qVB+4K70QRGmAxjtCHMqpqVJXYSkEKMI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768496008; c=relaxed/simple; bh=JWWtGuV/VwhZsUmEljlNKeFiQPvZzC1+EmFtymL4mHg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ysf5cdhhqq8sScWBN/Rh5NcVzk/6f28ktx7VADrS7dbM7xyZoDEiMacotI2H/4a4tbrQSDSyxQRQIx9ZB2tEoc4TGVJ4uWhCmyh/9Hvrrx9cO9rUfax8fHSaji/P9/X7Xnz8JvgJiRMaBkLUVGquuWE0XaOYMAzwktHjrq+kIcg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Qy/70Np8; arc=none smtp.client-ip=209.85.160.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Qy/70Np8" Received: by mail-oa1-f42.google.com with SMTP id 586e51a60fabf-40427db1300so651437fac.0 for ; Thu, 15 Jan 2026 08:53:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768496005; x=1769100805; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oX2zMpvfQJcsDHtvGDGxiX3cGUndHgHP6A2JLNcAI8o=; b=Qy/70Np8YMdc+49dmzoQnRBRRmjcZZniIXL8R6k8+SoO/ZA05RecTxlM0u3ZRmiGv6 xtNfMsnsyquzIHqZVnB16jUn3rnvh7u25u3CkUi3WPLqC39W3uTV2/hFQExeC5aBt83D Dv1t0ZrEkh7m70py8HdXOYVcSyJYMBK85aWbavgR/Vz++7Wbgyx8KEoDMy5Jb++7EAkZ /RIZBHX38hbLaw+huX5uzpCuS2abwH4qoge+8blx/RNAk7rOe6XtTVa2YNXhwEopNdnY OauXhMEJH0uWntj4LBP6FvXVObjyBmXNq0WxxQcFPmkt8DET5itzwc0pwucuImAf6ppC 48tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768496005; x=1769100805; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=oX2zMpvfQJcsDHtvGDGxiX3cGUndHgHP6A2JLNcAI8o=; b=LvaCH/iGGNIzDObiFT6/HIFqu9JJYnSm7jaDEe3cG7ovuK5ESDB4i6T/9iRTwvTQxh Fe6lWdflewbUh81/2qQg96xKW/ACTpidp2Zz3z9bb4l5gCni2nWxkM2Mub5VHIqdzLlt i1wUXdmoVw6wzMRU4GwsAiojmD5S9He3Ns1Q/jZQBrzWMBMYXiMmPwYJT/4qC62cjW4z S2gAYHTxPRCiYErGpFJrg8QotuvWQXQ7wH50AwnlccthluzxvSfaCs7XnW1U1cTTNNJd cionUVZDMJSyFFT6azuPaz1aAgdT7FgAVyX11I7cyI598Jm5FdpdxZFpRQ56OAVlvFvu awTQ== X-Forwarded-Encrypted: i=1; AJvYcCXdgQ6JSX4NGZxbAMIkG9bV3FWCoLh9HBSbiO5Vt0NBBIf6wN132DEmgEF8FV37XRbxKNjs@lists.linux.dev X-Gm-Message-State: AOJu0Yy0VStuSp3oTx/4yIH9ymj1ZpvUG9UTM6mERzWJIC+fS4F4SDCZ Qq9tnFHeMkBiDVpXFAlGovHCm9Iv2laTloCDRvKapDLNWklBzcXXXenMS8tv7gmx X-Gm-Gg: AY/fxX7tyfvw6oUgRC7lPx90xbHFduOgYynla0K/t2K1S//wyPvnGux50MOIvvHGrcC 4Y6CABTP1G5oTt6f0ZITOpaguBeCjYCh3bqs4SLXxpOF17ZHGTrU+DqIlKCt7DONPHGldzmwCUW t7DVA1ZlKD/MAKpqkVDY1sI+v0Q1eilZQ4/nMsOB0rFAnN10lJ3D6hdoFDAQEuGAdXObOBnEnG+ 0erHAJXDcs0PyTvx+xYWyc0M8qMfzyPu7MYXuvsUx14INwVBT6LJGYUkRWa2YcgAowAqwON5CYO OkavzbaxJt7GkckOHvVwaFztxXhE1XT5+U2yubXsuxsuFN1sr/AZsTojjF7Vw/m3WcgtYw0TZmS D1pxvoTs0tVFbpY9ySmbdD/4Mfh/wi1NJWsLAsci5VfidnGYz6r3NmaYRUEXu8dRK0hVga2d9xf /evnYqmVEBXe3kASdaXITw+CM3PYdNOnI6UgU80b/+0lr2wWL4SeQ= X-Received: by 2002:a05:6102:5705:b0:5ee:9df0:a608 with SMTP id ada2fe7eead31-5f183bdccbfmr2204558137.30.1768490154728; Thu, 15 Jan 2026 07:15:54 -0800 (PST) Received: from wsfd-netdev58.anl.eng.rdu2.dc.redhat.com ([66.187.232.140]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-890770cc6edsm201030056d6.4.2026.01.15.07.15.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Jan 2026 07:15:54 -0800 (PST) From: Xin Long To: network dev , quic@lists.linux.dev Cc: davem@davemloft.net, kuba@kernel.org, Eric Dumazet , Paolo Abeni , Simon Horman , Stefan Metzmacher , Moritz Buhl , Tyler Fanelli , Pengtao He , Thomas Dreibholz , linux-cifs@vger.kernel.org, Steve French , Namjae Jeon , Paulo Alcantara , Tom Talpey , kernel-tls-handshake@lists.linux.dev, Chuck Lever , Jeff Layton , Steve Dickson , Hannes Reinecke , Alexander Aring , David Howells , Matthieu Baerts , John Ericson , Cong Wang , "D . Wythe" , Jason Baron , illiliti , Sabrina Dubroca , Marcelo Ricardo Leitner , Daniel Stenberg , Andy Gospodarek Subject: [PATCH net-next v7 07/16] quic: add connection id management Date: Thu, 15 Jan 2026 10:11:07 -0500 Message-ID: <8f7d6df1f95a5407043c55e720ec0889ac2548fc.1768489876.git.lucien.xin@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: quic@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit This patch introduces 'struct quic_conn_id_set' for managing Connection IDs (CIDs), which are represented by 'struct quic_source_conn_id' and 'struct quic_dest_conn_id'. It provides helpers to add and remove CIDs from the set, and handles insertion of source CIDs into the global connection ID hash table when necessary. - quic_conn_id_add(): Add a new Connection ID to the set, and inserts it to conn_id hash table if it is a source conn_id. - quic_conn_id_remove(): Remove connection IDs the set with sequence numbers less than or equal to a number. It also adds utilities to look up CIDs by value or sequence number, search the global hash table for incoming packets, and check for stateless reset tokens among destination CIDs. These functions are essential for RX path connection lookup and stateless reset processing. - quic_conn_id_find(): Find a Connection ID in the set by seq number. - quic_conn_id_lookup(): Lookup a Connection ID from global hash table using the ID value, typically used for socket lookup on the RX path. - quic_conn_id_token_exists(): Check if a stateless reset token exists in any dest Connection ID (used during stateless reset processing). Note source/dest conn_id set is per socket, the operations on it are always pretected by the sock lock. Signed-off-by: Xin Long --- v3: - Clarify in changelog that conn_id set is always protected by sock lock (suggested by Paolo). - Adjust global source conn_id hashtable operations for the new hashtable type. v4: - Replace struct hlist_node with hlist_nulls_node for the node in struct quic_source_conn_id to support lockless lookup. v7: - Break the loop earlier if common->number > number in quic_conn_id_remove/find() (suggested by Paolo). - Add a comment in quic_conn_id_first_number(). --- net/quic/Makefile | 2 +- net/quic/connid.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++ net/quic/connid.h | 163 +++++++++++++++++++++++++++++++++ net/quic/socket.c | 6 ++ net/quic/socket.h | 13 +++ 5 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 net/quic/connid.c create mode 100644 net/quic/connid.h diff --git a/net/quic/Makefile b/net/quic/Makefile index 094e9da5d739..eee7501588d3 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 stream.o +quic-y := common.o family.o protocol.o socket.o stream.o connid.o diff --git a/net/quic/connid.c b/net/quic/connid.c new file mode 100644 index 000000000000..79f48e9775f2 --- /dev/null +++ b/net/quic/connid.c @@ -0,0 +1,225 @@ +// 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 + */ + +#include +#include + +#include "common.h" +#include "connid.h" + +/* Lookup a source connection ID (scid) in the global source connection ID hash table. */ +struct quic_conn_id *quic_conn_id_lookup(struct net *net, u8 *scid, u32 len) +{ + struct quic_shash_head *head = quic_source_conn_id_head(net, scid, len); + struct quic_source_conn_id *s_conn_id; + struct quic_conn_id *conn_id = NULL; + struct hlist_nulls_node *node; + + hlist_nulls_for_each_entry_rcu(s_conn_id, node, &head->head, node) { + if (net == sock_net(s_conn_id->sk) && s_conn_id->common.id.len == len && + !memcmp(scid, &s_conn_id->common.id.data, s_conn_id->common.id.len)) { + if (likely(refcount_inc_not_zero(&s_conn_id->sk->sk_refcnt))) + conn_id = &s_conn_id->common.id; + break; + } + } + return conn_id; +} + +/* Check if a given stateless reset token exists in any connection ID in the connection ID set. */ +bool quic_conn_id_token_exists(struct quic_conn_id_set *id_set, u8 *token) +{ + struct quic_common_conn_id *common; + struct quic_dest_conn_id *dcid; + + dcid = (struct quic_dest_conn_id *)id_set->active; + if (!memcmp(dcid->token, token, QUIC_CONN_ID_TOKEN_LEN)) /* Fast path. */ + return true; + + list_for_each_entry(common, &id_set->head, list) { + dcid = (struct quic_dest_conn_id *)common; + if (common == id_set->active) + continue; + if (!memcmp(dcid->token, token, QUIC_CONN_ID_TOKEN_LEN)) + return true; + } + return false; +} + +static void quic_source_conn_id_free_rcu(struct rcu_head *head) +{ + struct quic_source_conn_id *s_conn_id; + + s_conn_id = container_of(head, struct quic_source_conn_id, rcu); + kfree(s_conn_id); +} + +static void quic_source_conn_id_free(struct quic_source_conn_id *s_conn_id) +{ + u8 *data = s_conn_id->common.id.data; + u32 len = s_conn_id->common.id.len; + struct quic_shash_head *head; + + if (!hlist_nulls_unhashed(&s_conn_id->node)) { + head = quic_source_conn_id_head(sock_net(s_conn_id->sk), data, len); + spin_lock_bh(&head->lock); + hlist_nulls_del_init_rcu(&s_conn_id->node); + spin_unlock_bh(&head->lock); + } + + /* Freeing is deferred via RCU to avoid use-after-free during concurrent lookups. */ + call_rcu(&s_conn_id->rcu, quic_source_conn_id_free_rcu); +} + +static void quic_conn_id_del(struct quic_common_conn_id *common) +{ + list_del(&common->list); + if (!common->hashed) { + kfree(common); + return; + } + quic_source_conn_id_free((struct quic_source_conn_id *)common); +} + +/* Add a connection ID with sequence number and associated private data to the connection ID set. */ +int quic_conn_id_add(struct quic_conn_id_set *id_set, + struct quic_conn_id *conn_id, u32 number, void *data) +{ + struct quic_source_conn_id *s_conn_id; + struct quic_dest_conn_id *d_conn_id; + struct quic_common_conn_id *common; + struct quic_shash_head *head; + struct list_head *list; + + /* Locate insertion point to keep list ordered by number. */ + list = &id_set->head; + list_for_each_entry(common, list, list) { + if (number == common->number) + return 0; /* Ignore if it already exists on the list. */ + if (number < common->number) { + list = &common->list; + break; + } + } + + if (conn_id->len > QUIC_CONN_ID_MAX_LEN) + return -EINVAL; + common = kzalloc(id_set->entry_size, GFP_ATOMIC); + if (!common) + return -ENOMEM; + common->id = *conn_id; + common->number = number; + if (id_set->entry_size == sizeof(struct quic_dest_conn_id)) { + /* For destination connection IDs, copy the stateless reset token if available. */ + if (data) { + d_conn_id = (struct quic_dest_conn_id *)common; + memcpy(d_conn_id->token, data, QUIC_CONN_ID_TOKEN_LEN); + } + } else { + /* For source connection IDs, mark as hashed and insert into the global source + * connection ID hashtable. + */ + common->hashed = 1; + s_conn_id = (struct quic_source_conn_id *)common; + s_conn_id->sk = data; + + head = quic_source_conn_id_head(sock_net(s_conn_id->sk), common->id.data, + common->id.len); + spin_lock_bh(&head->lock); + hlist_nulls_add_head_rcu(&s_conn_id->node, &head->head); + spin_unlock_bh(&head->lock); + } + list_add_tail(&common->list, list); + + if (number == quic_conn_id_last_number(id_set) + 1) { + if (!id_set->active) + id_set->active = common; + id_set->count++; + + /* Increment count for consecutive following IDs. */ + list_for_each_entry_continue(common, &id_set->head, list) { + if (common->number != ++number) + break; + id_set->count++; + } + } + return 0; +} + +/* Remove connection IDs from the set with sequence numbers less than or equal to a number. */ +void quic_conn_id_remove(struct quic_conn_id_set *id_set, u32 number) +{ + struct quic_common_conn_id *common, *tmp; + struct list_head *list; + + list = &id_set->head; + list_for_each_entry_safe(common, tmp, list, list) { + if (common->number > number) + break; + if (id_set->active == common) + id_set->active = tmp; + quic_conn_id_del(common); + id_set->count--; + } +} + +struct quic_conn_id *quic_conn_id_find(struct quic_conn_id_set *id_set, u32 number) +{ + struct quic_common_conn_id *common; + + list_for_each_entry(common, &id_set->head, list) { + if (common->number > number) + break; + if (common->number == number) + return &common->id; + } + return NULL; +} + +void quic_conn_id_update_active(struct quic_conn_id_set *id_set, u32 number) +{ + struct quic_conn_id *conn_id; + + if (number == id_set->active->number) + return; + conn_id = quic_conn_id_find(id_set, number); + if (!conn_id) + return; + quic_conn_id_set_active(id_set, conn_id); +} + +void quic_conn_id_set_init(struct quic_conn_id_set *id_set, bool source) +{ + id_set->entry_size = source ? sizeof(struct quic_source_conn_id) : + sizeof(struct quic_dest_conn_id); + INIT_LIST_HEAD(&id_set->head); +} + +void quic_conn_id_set_free(struct quic_conn_id_set *id_set) +{ + struct quic_common_conn_id *common, *tmp; + + list_for_each_entry_safe(common, tmp, &id_set->head, list) + quic_conn_id_del(common); + id_set->count = 0; + id_set->active = NULL; +} + +void quic_conn_id_get_param(struct quic_conn_id_set *id_set, struct quic_transport_param *p) +{ + p->active_connection_id_limit = id_set->max_count; +} + +void quic_conn_id_set_param(struct quic_conn_id_set *id_set, struct quic_transport_param *p) +{ + id_set->max_count = p->active_connection_id_limit; +} diff --git a/net/quic/connid.h b/net/quic/connid.h new file mode 100644 index 000000000000..f5bb590ffd93 --- /dev/null +++ b/net/quic/connid.h @@ -0,0 +1,163 @@ +/* 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 + * + * Written or modified by: + * Xin Long + */ + +#define QUIC_CONN_ID_LIMIT 8 +#define QUIC_CONN_ID_DEF 7 +#define QUIC_CONN_ID_LEAST 2 + +#define QUIC_CONN_ID_TOKEN_LEN 16 + +/* Common fields shared by both source and destination Connection IDs */ +struct quic_common_conn_id { + struct quic_conn_id id; /* The actual Connection ID value and its length */ + struct list_head list; /* Linked list node for conn_id list management */ + u32 number; /* Sequence number assigned to this Connection ID */ + u8 hashed; /* Non-zero if this ID is stored in source_conn_id hashtable */ +}; + +struct quic_source_conn_id { + struct quic_common_conn_id common; + struct hlist_nulls_node node; /* Hash table node for fast lookup by Connection ID */ + struct rcu_head rcu; /* RCU header for deferred destruction */ + struct sock *sk; /* Pointer to sk associated with this Connection ID */ +}; + +struct quic_dest_conn_id { + struct quic_common_conn_id common; + u8 token[QUIC_CONN_ID_TOKEN_LEN]; /* Stateless reset token in rfc9000#section-10.3 */ +}; + +struct quic_conn_id_set { + /* Connection ID in use on the current path */ + struct quic_common_conn_id *active; + /* Connection ID to use for a new path (e.g., after migration) */ + struct quic_common_conn_id *alt; + struct list_head head; /* Head of the linked list of available connection IDs */ + u8 entry_size; /* Size of each connection ID entry (in bytes) in the list */ + u8 max_count; /* active_connection_id_limit in rfc9000#section-18.2 */ + u8 count; /* Current number of connection IDs in the list */ +}; + +static inline u32 quic_conn_id_first_number(struct quic_conn_id_set *id_set) +{ + struct quic_common_conn_id *common; + + /* The id_set is guaranteed to be non-empty when called (sk is not in CLOSE state). */ + common = list_first_entry(&id_set->head, struct quic_common_conn_id, list); + return common->number; +} + +static inline u32 quic_conn_id_last_number(struct quic_conn_id_set *id_set) +{ + return quic_conn_id_first_number(id_set) + id_set->count - 1; +} + +static inline void quic_conn_id_generate(struct quic_conn_id *conn_id) +{ + get_random_bytes(conn_id->data, QUIC_CONN_ID_DEF_LEN); + conn_id->len = QUIC_CONN_ID_DEF_LEN; +} + +/* Select an alternate destination Connection ID for a new path (e.g., after migration). */ +static inline bool quic_conn_id_select_alt(struct quic_conn_id_set *id_set, bool active) +{ + if (id_set->alt) + return true; + /* NAT rebinding: peer keeps using the current source conn_id. + * In this case, continue using the same dest conn_id for the new path. + */ + if (active) { + id_set->alt = id_set->active; + return true; + } + /* Treat the prev conn_ids as used. + * Try selecting the next conn_id in the list, unless at the end. + */ + if (id_set->active->number != quic_conn_id_last_number(id_set)) { + id_set->alt = list_next_entry(id_set->active, list); + return true; + } + /* If there's only one conn_id in the list, reuse the active one. */ + if (id_set->active->number == quic_conn_id_first_number(id_set)) { + id_set->alt = id_set->active; + return true; + } + /* No alternate conn_id could be selected. Caller should send a + * QUIC_FRAME_RETIRE_CONNECTION_ID frame to request new connection IDs from the peer. + */ + return false; +} + +static inline void quic_conn_id_set_alt(struct quic_conn_id_set *id_set, struct quic_conn_id *alt) +{ + id_set->alt = (struct quic_common_conn_id *)alt; +} + +/* Swap the active and alternate destination Connection IDs after path migration completes, + * since the path has already been switched accordingly. + */ +static inline void quic_conn_id_swap_active(struct quic_conn_id_set *id_set) +{ + void *active = id_set->active; + + id_set->active = id_set->alt; + id_set->alt = active; +} + +/* Choose which destination Connection ID to use for a new path migration if alt is true. */ +static inline struct quic_conn_id *quic_conn_id_choose(struct quic_conn_id_set *id_set, u8 alt) +{ + return (alt && id_set->alt) ? &id_set->alt->id : &id_set->active->id; +} + +static inline struct quic_conn_id *quic_conn_id_active(struct quic_conn_id_set *id_set) +{ + return &id_set->active->id; +} + +static inline void quic_conn_id_set_active(struct quic_conn_id_set *id_set, + struct quic_conn_id *active) +{ + id_set->active = (struct quic_common_conn_id *)active; +} + +static inline u32 quic_conn_id_number(struct quic_conn_id *conn_id) +{ + return ((struct quic_common_conn_id *)conn_id)->number; +} + +static inline struct sock *quic_conn_id_sk(struct quic_conn_id *conn_id) +{ + return ((struct quic_source_conn_id *)conn_id)->sk; +} + +static inline void quic_conn_id_set_token(struct quic_conn_id *conn_id, u8 *token) +{ + memcpy(((struct quic_dest_conn_id *)conn_id)->token, token, QUIC_CONN_ID_TOKEN_LEN); +} + +static inline int quic_conn_id_cmp(struct quic_conn_id *a, struct quic_conn_id *b) +{ + return a->len != b->len || memcmp(a->data, b->data, a->len); +} + +int quic_conn_id_add(struct quic_conn_id_set *id_set, struct quic_conn_id *conn_id, + u32 number, void *data); +bool quic_conn_id_token_exists(struct quic_conn_id_set *id_set, u8 *token); +void quic_conn_id_remove(struct quic_conn_id_set *id_set, u32 number); + +struct quic_conn_id *quic_conn_id_find(struct quic_conn_id_set *id_set, u32 number); +struct quic_conn_id *quic_conn_id_lookup(struct net *net, u8 *scid, u32 len); +void quic_conn_id_update_active(struct quic_conn_id_set *id_set, u32 number); + +void quic_conn_id_get_param(struct quic_conn_id_set *id_set, struct quic_transport_param *p); +void quic_conn_id_set_param(struct quic_conn_id_set *id_set, struct quic_transport_param *p); +void quic_conn_id_set_init(struct quic_conn_id_set *id_set, bool source); +void quic_conn_id_set_free(struct quic_conn_id_set *id_set); diff --git a/net/quic/socket.c b/net/quic/socket.c index d6f25669c693..ad581d84f684 100644 --- a/net/quic/socket.c +++ b/net/quic/socket.c @@ -41,6 +41,9 @@ static int quic_init_sock(struct sock *sk) sk->sk_write_space = quic_write_space; sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); + quic_conn_id_set_init(quic_source(sk), 1); + quic_conn_id_set_init(quic_dest(sk), 0); + if (quic_stream_init(quic_streams(sk))) return -ENOMEM; @@ -55,6 +58,9 @@ static int quic_init_sock(struct sock *sk) static void quic_destroy_sock(struct sock *sk) { + quic_conn_id_set_free(quic_source(sk)); + quic_conn_id_set_free(quic_dest(sk)); + quic_stream_free(quic_streams(sk)); quic_data_free(quic_ticket(sk)); diff --git a/net/quic/socket.h b/net/quic/socket.h index 0dfd3f8f3115..34363dd3345a 100644 --- a/net/quic/socket.h +++ b/net/quic/socket.h @@ -14,6 +14,7 @@ #include "common.h" #include "family.h" #include "stream.h" +#include "connid.h" #include "protocol.h" @@ -37,6 +38,8 @@ struct quic_sock { struct quic_data alpn; struct quic_stream_table streams; + struct quic_conn_id_set source; + struct quic_conn_id_set dest; }; struct quic6_sock { @@ -79,6 +82,16 @@ static inline struct quic_stream_table *quic_streams(const struct sock *sk) return &quic_sk(sk)->streams; } +static inline struct quic_conn_id_set *quic_source(const struct sock *sk) +{ + return &quic_sk(sk)->source; +} + +static inline struct quic_conn_id_set *quic_dest(const struct sock *sk) +{ + return &quic_sk(sk)->dest; +} + static inline bool quic_is_serv(const struct sock *sk) { return !!sk->sk_max_ack_backlog; -- 2.47.1