From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qt1-f176.google.com (mail-qt1-f176.google.com [209.85.160.176]) (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 9A84D313529 for ; Thu, 15 Jan 2026 15:17:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.176 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768490270; cv=none; b=g3p4iij5F7eL3DYGWz4Uc2A1ZR5aLV+I9gegBobG3s3ccCfRFtT6c8mAjNSDsA4mmKnoHl1cZSoIr+gT2zpRMuyRgYOzs5xtoNtZ4lQ8EKMPauorUbjUPTrkdunuS15yiyX3i1nbRRRDyR+nc2GtfhFbnQke6fDTeuojcJxENF0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768490270; c=relaxed/simple; bh=xMS/tcmCZaN5xUVesZbLR7t6pScTYfmBdZu7MKMd/sI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lZ7Kazx7CUNdjUTxgX4B4N6SL3V1vmjA/lDY1RcfLl1yOmCcQAzkBgCZVxY0+YQGQgDqn7JV0LtLVXjQe16xWww7vrhhX4MuEtFXh+VETTrpsG5MC971CYD9rUupvJbmAzshiXAstqip8fYZ+f5FMOGlDzd0eaz/eruz71dumzo= 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=Y9lw0KUS; arc=none smtp.client-ip=209.85.160.176 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="Y9lw0KUS" Received: by mail-qt1-f176.google.com with SMTP id d75a77b69052e-4ed66b5abf7so22902861cf.1 for ; Thu, 15 Jan 2026 07:17:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768490253; x=1769095053; 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=tkWp6pA+PyOqEwSCGnlRAstWh+s8zGXF+ytmYPGxmgg=; b=Y9lw0KUSxchjQVOICpzPYdBQ+t+E08WQrLJIzs1qM/U2j9q62IS3u5sXQ40//zg4lM l1DQsaytll4Urln7DYr0vpI22d5yoEF2PSCjrtOHplsp8E+TVfbaYS73BBdXMPb88nqz 6mEfj/5RLArIOWAivul7rpsJj7IWyo2a80q66k5AS0yDQSgtZTSulogfv5hx2D3dCe8r y2uPu9WXs1XJj9x/Mg+SFZRi+ISLX58H80xqTLj1TqI0JvCX7TgGP6eXgjqiPNZCpTmM kd+XVtb6To/3iOAEC/OA8FWkziqEU+izMrKre28wDfGIeZyrtCdBzw6nc/BkmsqIBRye 961g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768490253; x=1769095053; 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=tkWp6pA+PyOqEwSCGnlRAstWh+s8zGXF+ytmYPGxmgg=; b=hi/XJSP3M3hdR2HXkPtRLm4VU89QuBObI5PNbvaHml1d0IYQUQU+Ii7hjMIdHOLdwV Mu6D1DvLPlm1Gx36TtrytiUjKAavBnvD4bE8A5hiyTJL/Bw+EMTjeGiiD1y+NkvLQ8PM LhUPrKdvMjWiOM3QvnkL18uEypHQcGaniTnMbNgbXKdYIi+RF6v2DzUC1Tkok1k7M2Dn ZlHs2Kk17cyY5PXAyAkc9BUK1MOnZfmckLagjjQgEtzmvo3M/p10kFF75DLIb1jZj/Gb R4ooBzZ1IkXxkmX0sTtkiVjwzYUFzTEVSB5sxbfke9bUuEZiIqbX/W7K4IHPAU2A0up8 hMDA== X-Forwarded-Encrypted: i=1; AJvYcCUDNXPc1pg+ywCiEXRlwS5x6Rp3Ve/yprR92NXh+PV44Za0VaiQ7SOFIW/vOjzuNj3joAvv@lists.linux.dev X-Gm-Message-State: AOJu0YyIyv2LswxopHUBtw3vg9+9zB3Z+svz4GEjcWkMNlhKDOOy6j3E vEU4dZlIaQcuOqIvZMs84SVU7TKdg5Xrm8xXuyMgtLGaFx8WTADtYyhs X-Gm-Gg: AY/fxX64+MvCUtmKu+1OxoQIlZCAED2BKr6omdjiNrdyR8E3nZ7X+B+l47k6I2Alxlb OBH3AJA0Z1B/9dYG7NrSWg+JYsPqQh24lTeauI3tVMDyHhwlXCWYU+OPLB3i9cNk5YQXpxAr9rD hSEq9OQ7KXyMned3Yd9Zao0tw3T30Kn84toqe9D/YQF8QzypZNU6GWMrN/mRbjbVOyWrwEdzVVL aweputB7SXj7oQNfy5mvg4lhOUDcGjet9ukeXKrPC7dYKXSoUPsQ9JxZPM7cxenMAHvJRWPSI/C IrksU4Fc4H9wv57e/k9vc3Wc+XeqIgExUmnICSvxpQneKONbtcqbTPZj1C1zl8b5Yg3JCeyzNwz nHIKfy7VgLH3MBJDQbm9+2LL5ZFAN+tMko88EVF3rNfyl8HSv8MbCkpMLp1L2oeBQz2TjkvnOtI 13jju3l5uIqtF7hHsVibWqm+ss8ulYkLWmKlvjXeiXQUjBe1KHcPM= X-Received: by 2002:a05:622a:13c6:b0:4e8:a560:d980 with SMTP id d75a77b69052e-5019f9125f9mr43546671cf.38.1768490252585; Thu, 15 Jan 2026 07:17:32 -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.17.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Jan 2026 07:17:32 -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 15/16] quic: add packet builder base Date: Thu, 15 Jan 2026 10:11:15 -0500 Message-ID: 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-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces 'quic_packet' to handle packing of QUIC packets on the transmit (TX) path. It provides functionality for frame packing and packet construction. The packet configuration includes setting the path, calculating overhead, and verifying routing. Frames are appended to the packet before it is created with the queued frames. Once assembled, the packet is encrypted, bundled, and sent out. There is also support to flush the packet when no additional frames remain. Functions to create application (short) and handshake (long) packets are currently placeholders for future implementation. - quic_packet_config(): Set the path, compute overhead, and verify routing. - quic_packet_tail(): Append a frame to the packet for transmission. - quic_packet_create_and_xmit(): Create and send the packet with the queued frames. - quic_packet_xmit(): Encrypt, bundle, and send out the packet. - quic_packet_flush(): Send the packet if there's nothing left to bundle. Signed-off-by: Xin Long --- v3: - Adjust global connection and listen socket hashtable operations based on the new hashtable type. - Introduce quic_packet_backlog_schedule() to enqueue Initial packets to quic_net.backlog_list and defer their decryption for ALPN demux to quic_packet_backlog_work() on quic_net.work, since quic_crypto_initial_keys_install()/crypto_aead_setkey() must run in process context. v4: - Update quic_(listen_)sock_lookup() to support lockless socket lookup using hlist_nulls_node APIs. - Use quic_wq for QUIC packet backlog processing work. v5: - Rename quic_packet_create() to quic_packet_create_and_xmit() (suggested by Paolo). - Move the packet parser base code to a separate patch, keeping only the packet builder base in this patch (suggested by Paolo). - Change sent_time timestamp from u32 to u64 to improve accuracy. --- net/quic/Makefile | 2 +- net/quic/packet.c | 313 ++++++++++++++++++++++++++++++++++++++++++++++ net/quic/packet.h | 121 ++++++++++++++++++ net/quic/socket.c | 1 + net/quic/socket.h | 7 ++ 5 files changed, 443 insertions(+), 1 deletion(-) create mode 100644 net/quic/packet.c create mode 100644 net/quic/packet.h diff --git a/net/quic/Makefile b/net/quic/Makefile index 645ee470c95e..4a43052eb441 100644 --- a/net/quic/Makefile +++ b/net/quic/Makefile @@ -6,4 +6,4 @@ obj-$(CONFIG_IP_QUIC) += quic.o quic-y := common.o family.o protocol.o socket.o stream.o connid.o path.o \ - cong.o pnspace.o crypto.o timer.o frame.o + cong.o pnspace.o crypto.o timer.o frame.o packet.o diff --git a/net/quic/packet.c b/net/quic/packet.c new file mode 100644 index 000000000000..348e760aa197 --- /dev/null +++ b/net/quic/packet.c @@ -0,0 +1,313 @@ +// 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 "socket.h" + +#define QUIC_HLEN 1 + +/* Make these fixed for easy coding. */ +#define QUIC_PACKET_NUMBER_LEN QUIC_PN_MAX_LEN +#define QUIC_PACKET_LENGTH_LEN 4 + +static struct sk_buff *quic_packet_handshake_create(struct sock *sk) +{ + struct quic_packet *packet = quic_packet(sk); + struct quic_frame *frame, *next; + + /* Free all frames for now, and future patches will implement the actual creation logic. */ + list_for_each_entry_safe(frame, next, &packet->frame_list, list) { + list_del(&frame->list); + quic_frame_put(frame); + } + return NULL; +} + +static int quic_packet_number_check(struct sock *sk) +{ + return 0; +} + +static struct sk_buff *quic_packet_app_create(struct sock *sk) +{ + struct quic_packet *packet = quic_packet(sk); + struct quic_frame *frame, *next; + + /* Free all frames for now, and future patches will implement the actual creation logic. */ + list_for_each_entry_safe(frame, next, &packet->frame_list, list) { + list_del(&frame->list); + quic_frame_put(frame); + } + return NULL; +} + +/* Update the MSS and inform congestion control. */ +void quic_packet_mss_update(struct sock *sk, u32 mss) +{ + struct quic_packet *packet = quic_packet(sk); + struct quic_cong *cong = quic_cong(sk); + + packet->mss[0] = (u16)mss; + quic_cong_set_mss(cong, packet->mss[0] - packet->taglen[0]); +} + +/* Perform routing for the QUIC packet on the specified path, update header length and MSS + * accordingly, reset path and start PMTU timer. + */ +int quic_packet_route(struct sock *sk) +{ + struct quic_path_group *paths = quic_paths(sk); + struct quic_packet *packet = quic_packet(sk); + struct quic_config *c = quic_config(sk); + union quic_addr *sa, *da; + u32 pmtu; + int err; + + da = quic_path_daddr(paths, packet->path); + sa = quic_path_saddr(paths, packet->path); + err = quic_flow_route(sk, da, sa, &paths->fl); + if (err) + return err; + + packet->hlen = quic_encap_len(da); + pmtu = min_t(u32, dst_mtu(__sk_dst_get(sk)), QUIC_PATH_MAX_PMTU); + quic_packet_mss_update(sk, pmtu - packet->hlen); + + quic_path_pl_reset(paths); + quic_timer_reset(sk, QUIC_TIMER_PMTU, c->plpmtud_probe_interval); + return 0; +} + +/* Configure the QUIC packet header and routing based on encryption level and path. */ +int quic_packet_config(struct sock *sk, u8 level, u8 path) +{ + struct quic_conn_id_set *dest = quic_dest(sk), *source = quic_source(sk); + struct quic_packet *packet = quic_packet(sk); + struct quic_config *c = quic_config(sk); + u32 hlen = QUIC_HLEN; + + /* If packet already has data, no need to reconfigure. */ + if (!quic_packet_empty(packet)) + return 0; + + packet->ack_eliciting = 0; + packet->frame_len = 0; + packet->ipfragok = 0; + packet->padding = 0; + packet->frames = 0; + hlen += QUIC_PACKET_NUMBER_LEN; /* Packet number length. */ + hlen += quic_conn_id_choose(dest, path)->len; /* DCID length. */ + if (level) { + hlen += 1; /* Length byte for DCID. */ + hlen += 1 + quic_conn_id_active(source)->len; /* Length byte + SCID length. */ + if (level == QUIC_CRYPTO_INITIAL) /* Include token for Initial packets. */ + hlen += quic_var_len(quic_token(sk)->len) + quic_token(sk)->len; + hlen += QUIC_VERSION_LEN; /* Version length. */ + hlen += QUIC_PACKET_LENGTH_LEN; /* Packet length field length. */ + /* Allow fragmentation if PLPMTUD is enabled, as it no longer relies on ICMP + * Toobig messages to discover the path MTU. + */ + packet->ipfragok = !!c->plpmtud_probe_interval; + } + packet->level = level; + packet->len = (u16)hlen; + packet->overhead = (u8)hlen; + + if (packet->path != path) { /* If the path changed, update and reset routing cache. */ + packet->path = path; + __sk_dst_reset(sk); + } + + /* Perform routing and MSS update for the configured packet. */ + if (quic_packet_route(sk) < 0) + return -1; + return 0; +} + +static void quic_packet_encrypt_done(struct sk_buff *skb, int err) +{ + /* Free it for now, future patches will implement the actual deferred transmission logic. */ + kfree_skb(skb); +} + +/* Coalescing Packets. */ +static int quic_packet_bundle(struct sock *sk, struct sk_buff *skb) +{ + struct quic_skb_cb *head_cb, *cb = QUIC_SKB_CB(skb); + struct quic_packet *packet = quic_packet(sk); + struct sk_buff *p; + + if (!packet->head) { /* First packet to bundle: initialize the head. */ + packet->head = skb; + cb->last = skb; + goto out; + } + + /* If bundling would exceed MSS, flush the current bundle. */ + if (packet->head->len + skb->len >= packet->mss[0]) { + quic_packet_flush(sk); + packet->head = skb; + cb->last = skb; + goto out; + } + /* Bundle it and update metadata for the aggregate skb. */ + p = packet->head; + head_cb = QUIC_SKB_CB(p); + if (head_cb->last == p) + skb_shinfo(p)->frag_list = skb; + else + head_cb->last->next = skb; + p->data_len += skb->len; + p->truesize += skb->truesize; + p->len += skb->len; + head_cb->last = skb; + head_cb->ecn |= cb->ecn; /* Merge ECN flags. */ + +out: + /* rfc9000#section-12.2: + * Packets with a short header (Section 17.3) do not contain a Length field and so + * cannot be followed by other packets in the same UDP datagram. + * + * so Return 1 to flush if it is a Short header packet. + */ + return !cb->level; +} + +/* Transmit a QUIC packet, possibly encrypting and bundling it. */ +int quic_packet_xmit(struct sock *sk, struct sk_buff *skb) +{ + struct quic_packet *packet = quic_packet(sk); + struct quic_skb_cb *cb = QUIC_SKB_CB(skb); + struct net *net = sock_net(sk); + int err; + + /* Skip encryption if taglen == 0 (e.g., disable_1rtt_encryption). */ + if (!packet->taglen[quic_hdr(skb)->form]) + goto xmit; + + cb->crypto_done = quic_packet_encrypt_done; + /* Associate skb with sk to ensure sk is valid during async encryption completion. */ + WARN_ON(!skb_set_owner_sk_safe(skb, sk)); + err = quic_crypto_encrypt(quic_crypto(sk, packet->level), skb); + if (err) { + if (err != -EINPROGRESS) { + QUIC_INC_STATS(net, QUIC_MIB_PKT_ENCDROP); + kfree_skb(skb); + return err; + } + QUIC_INC_STATS(net, QUIC_MIB_PKT_ENCBACKLOGS); + return err; + } + if (!cb->resume) /* Encryption completes synchronously. */ + QUIC_INC_STATS(net, QUIC_MIB_PKT_ENCFASTPATHS); + +xmit: + if (quic_packet_bundle(sk, skb)) + quic_packet_flush(sk); + return 0; +} + +/* Create and transmit a new QUIC packet. */ +int quic_packet_create_and_xmit(struct sock *sk) +{ + struct quic_packet *packet = quic_packet(sk); + struct sk_buff *skb; + int err; + + err = quic_packet_number_check(sk); + if (err) + goto err; + + if (packet->level) + skb = quic_packet_handshake_create(sk); + else + skb = quic_packet_app_create(sk); + if (!skb) { + err = -ENOMEM; + goto err; + } + + err = quic_packet_xmit(sk, skb); + if (err && err != -EINPROGRESS) + goto err; + + /* Return 1 if at least one ACK-eliciting (non-PING) frame was sent. */ + return !!packet->frames; +err: + pr_debug("%s: err: %d\n", __func__, err); + return 0; +} + +/* Flush any coalesced/bundled QUIC packets. */ +void quic_packet_flush(struct sock *sk) +{ + struct quic_path_group *paths = quic_paths(sk); + struct quic_packet *packet = quic_packet(sk); + + if (packet->head) { + quic_lower_xmit(sk, packet->head, + quic_path_daddr(paths, packet->path), &paths->fl); + packet->head = NULL; + } +} + +/* Append a frame to the tail of the current QUIC packet. */ +int quic_packet_tail(struct sock *sk, struct quic_frame *frame) +{ + struct quic_packet *packet = quic_packet(sk); + u8 taglen; + + /* Reject frame if it doesn't match the packet's encryption level or path, or if + * padding is already in place (no further frames should be added). + */ + if (frame->level != (packet->level % QUIC_CRYPTO_EARLY) || + frame->path != packet->path || packet->padding) + return 0; + + /* Check if frame would exceed the current datagram MSS (excluding AEAD tag). */ + taglen = quic_packet_taglen(packet); + if (packet->len + frame->len > packet->mss[frame->dgram] - taglen) { + /* If some data has already been added to the packet, bail out. */ + if (packet->len != packet->overhead) + return 0; + /* Otherwise, allow IP fragmentation for this packet unless it’s a PING probe. */ + if (!quic_frame_ping(frame->type)) + packet->ipfragok = 1; + } + if (frame->padding) + packet->padding = frame->padding; + + /* Track frames that require retransmission if lost (i.e., ACK-eliciting and non-PING). */ + if (frame->ack_eliciting) { + packet->ack_eliciting = 1; + if (!quic_frame_ping(frame->type)) { + packet->frames++; + packet->frame_len += frame->len; + } + } + + list_move_tail(&frame->list, &packet->frame_list); + packet->len += frame->len; + return frame->len; +} + +void quic_packet_init(struct sock *sk) +{ + struct quic_packet *packet = quic_packet(sk); + + INIT_LIST_HEAD(&packet->frame_list); + packet->taglen[0] = QUIC_TAG_LEN; + packet->taglen[1] = QUIC_TAG_LEN; + packet->mss[0] = QUIC_TAG_LEN; + packet->mss[1] = QUIC_TAG_LEN; + + packet->version = QUIC_VERSION_V1; +} diff --git a/net/quic/packet.h b/net/quic/packet.h new file mode 100644 index 000000000000..85efeba6199b --- /dev/null +++ b/net/quic/packet.h @@ -0,0 +1,121 @@ +/* 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 + */ + +struct quic_packet { + struct quic_conn_id dcid; /* Dest Connection ID from received packet */ + struct quic_conn_id scid; /* Source Connection ID from received packet */ + union quic_addr daddr; /* Dest address from received packet */ + union quic_addr saddr; /* Source address from received packet */ + + struct list_head frame_list; /* List of frames to pack into packet for send */ + struct sk_buff *head; /* Head skb for packet bundling on send */ + u16 frame_len; /* Length of all ack-eliciting frames excluding PING */ + u8 taglen[2]; /* Tag length for short and long packets */ + u32 version; /* QUIC version used/selected during handshake */ + u8 errframe; /* Frame type causing packet processing failure */ + u8 overhead; /* QUIC header length excluding frames */ + u16 errcode; /* Error code on packet processing failure */ + u16 frames; /* Number of ack-eliciting frames excluding PING */ + u16 mss[2]; /* MSS for datagram and non-datagram packets */ + u16 hlen; /* UDP + IP header length for sending */ + u16 len; /* QUIC packet length excluding taglen for sending */ + + u8 ack_eliciting:1; /* Packet contains ack-eliciting frames to send */ + u8 ack_requested:1; /* Packet contains ack-eliciting frames received */ + u8 ack_immediate:1; /* Send ACK immediately (skip ack_delay timer) */ + u8 non_probing:1; /* Packet has ack-eliciting frames excluding NEW_CONNECTION_ID */ + u8 has_sack:1; /* Packet has ACK frames received */ + u8 ipfragok:1; /* Allow IP fragmentation */ + u8 padding:1; /* Packet has padding frames */ + u8 path:1; /* Path identifier used to send this packet */ + u8 level; /* Encryption level used */ +}; + +struct quic_packet_sent { + struct list_head list; /* Link in sent packet list for ACK tracking */ + u64 sent_time; /* Timestamp when packet was sent */ + s64 number; /* Packet number */ + u8 level; /* Packet number space */ + u8 ecn:2; /* ECN bits */ + + u16 frame_len; /* Combined length of all frames held */ + u16 frames; /* Number of frames held */ + + struct quic_frame *frame_array[]; /* Array of pointers to held frames */ +}; + +#define QUIC_PACKET_INITIAL_V1 0 +#define QUIC_PACKET_0RTT_V1 1 +#define QUIC_PACKET_HANDSHAKE_V1 2 +#define QUIC_PACKET_RETRY_V1 3 + +#define QUIC_PACKET_INITIAL_V2 1 +#define QUIC_PACKET_0RTT_V2 2 +#define QUIC_PACKET_HANDSHAKE_V2 3 +#define QUIC_PACKET_RETRY_V2 0 + +#define QUIC_PACKET_INITIAL QUIC_PACKET_INITIAL_V1 +#define QUIC_PACKET_0RTT QUIC_PACKET_0RTT_V1 +#define QUIC_PACKET_HANDSHAKE QUIC_PACKET_HANDSHAKE_V1 +#define QUIC_PACKET_RETRY QUIC_PACKET_RETRY_V1 + +#define QUIC_VERSION_LEN 4 + +static inline u8 quic_packet_taglen(struct quic_packet *packet) +{ + return packet->taglen[!!packet->level]; +} + +static inline void quic_packet_set_taglen(struct quic_packet *packet, u8 taglen) +{ + packet->taglen[0] = taglen; +} + +static inline u32 quic_packet_mss(struct quic_packet *packet) +{ + return packet->mss[0] - packet->taglen[!!packet->level]; +} + +static inline u32 quic_packet_max_payload(struct quic_packet *packet) +{ + return packet->mss[0] - packet->overhead - packet->taglen[!!packet->level]; +} + +static inline u32 quic_packet_max_payload_dgram(struct quic_packet *packet) +{ + return packet->mss[1] - packet->overhead - packet->taglen[!!packet->level]; +} + +static inline int quic_packet_empty(struct quic_packet *packet) +{ + return list_empty(&packet->frame_list); +} + +static inline void quic_packet_reset(struct quic_packet *packet) +{ + packet->level = 0; + packet->errcode = 0; + packet->errframe = 0; + packet->has_sack = 0; + packet->non_probing = 0; + packet->ack_requested = 0; + packet->ack_immediate = 0; +} + +int quic_packet_tail(struct sock *sk, struct quic_frame *frame); +int quic_packet_config(struct sock *sk, u8 level, u8 path); + +int quic_packet_xmit(struct sock *sk, struct sk_buff *skb); +int quic_packet_create_and_xmit(struct sock *sk); +int quic_packet_route(struct sock *sk); + +void quic_packet_mss_update(struct sock *sk, u32 mss); +void quic_packet_flush(struct sock *sk); +void quic_packet_init(struct sock *sk); diff --git a/net/quic/socket.c b/net/quic/socket.c index dde1d9becf06..f73d25cd16e9 100644 --- a/net/quic/socket.c +++ b/net/quic/socket.c @@ -48,6 +48,7 @@ static int quic_init_sock(struct sock *sk) quic_cong_init(quic_cong(sk)); quic_timer_init(sk); + quic_packet_init(sk); if (quic_stream_init(quic_streams(sk))) return -ENOMEM; diff --git a/net/quic/socket.h b/net/quic/socket.h index eeb510e0a09b..a463b80a76fc 100644 --- a/net/quic/socket.h +++ b/net/quic/socket.h @@ -20,6 +20,7 @@ #include "path.h" #include "cong.h" +#include "packet.h" #include "frame.h" #include "protocol.h" @@ -77,6 +78,7 @@ struct quic_sock { struct quic_pnspace space[QUIC_PNSPACE_MAX]; struct quic_crypto crypto[QUIC_CRYPTO_MAX]; + struct quic_packet packet; struct quic_timer timers[QUIC_TIMER_MAX]; }; @@ -155,6 +157,11 @@ static inline struct quic_crypto *quic_crypto(const struct sock *sk, u8 level) return &quic_sk(sk)->crypto[level]; } +static inline struct quic_packet *quic_packet(const struct sock *sk) +{ + return &quic_sk(sk)->packet; +} + static inline void *quic_timer(const struct sock *sk, u8 type) { return (void *)&quic_sk(sk)->timers[type]; -- 2.47.1