LCOV - code coverage report
Current view: top level - home/net-next/net/quic - inqueue.c (source / functions) Hit Total Coverage
Test: quic.info Lines: 329 392 83.9 %
Date: 2025-07-04 13:24:45 Functions: 16 18 88.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* QUIC kernel implementation
       3             :  * (C) Copyright Red Hat Corp. 2023
       4             :  *
       5             :  * This file is part of the QUIC kernel implementation
       6             :  *
       7             :  * Initialization/cleanup for QUIC protocol support.
       8             :  *
       9             :  * Written or modified by:
      10             :  *    Xin Long <lucien.xin@gmail.com>
      11             :  */
      12             : 
      13             : #include <net/proto_memory.h>
      14             : 
      15             : #include "socket.h"
      16             : 
      17             : /* Frees socket receive memory resources after read. */
      18      577512 : static void quic_inq_rfree(int len, struct sock *sk)
      19             : {
      20      577512 :         if (!len)
      21             :                 return;
      22             : 
      23      555380 :         atomic_sub(len, &sk->sk_rmem_alloc);
      24      555380 :         sk_mem_uncharge(sk, len);
      25             : }
      26             : 
      27             : /* Charges socket receive memory for new frame. */
      28     6363645 : static void quic_inq_set_owner_r(int len, struct sock *sk)
      29             : {
      30     6363645 :         if (!len)
      31             :                 return;
      32             : 
      33     6363641 :         atomic_add(len, &sk->sk_rmem_alloc);
      34     6363641 :         sk_mem_charge(sk, len);
      35             : }
      36             : 
      37             : #define QUIC_INQ_RWND_SHIFT     4
      38             : 
      39             : /* Update receive flow control windows and send MAX_DATA or MAX_STREAM_DATA frames if needed. */
      40      551526 : void quic_inq_flow_control(struct sock *sk, struct quic_stream *stream, u32 bytes)
      41             : {
      42      551526 :         struct quic_pnspace *space = quic_pnspace(sk, QUIC_CRYPTO_APP);
      43      551526 :         struct quic_packet *packet = quic_packet(sk);
      44      551526 :         struct quic_inqueue *inq = quic_inq(sk);
      45      551526 :         u32 mss, window;
      46      551526 :         u8 frame = 0;
      47             : 
      48      551526 :         if (!bytes)
      49             :                 return;
      50             : 
      51      551526 :         mss = quic_packet_mss(packet);
      52             :         /* Account for bytes read at both stream and connection levels. */
      53      551526 :         stream->recv.bytes += bytes;
      54      551526 :         inq->bytes += bytes;
      55             : 
      56             :          /* Check and update connection-level flow control. */
      57      551526 :         window = inq->max_data;
      58      551526 :         if (inq->bytes + window - inq->max_bytes >=
      59      551526 :             max(mss, (window >> QUIC_INQ_RWND_SHIFT))) {
      60             :                 /* Reduce window increment if memory pressure detected. */
      61       60622 :                 if (sk_under_memory_pressure(sk))
      62           0 :                         window >>= 1;
      63             :                 /* Increase advertised max data to received data + window. */
      64       60622 :                 inq->max_bytes = inq->bytes + window;
      65       60622 :                 if (!quic_outq_transmit_frame(sk, QUIC_FRAME_MAX_DATA, inq, 0, true))
      66       60622 :                         frame = 1;
      67             :         }
      68             : 
      69             :         /* Check and update stream-level flow control. */
      70      551526 :         window = stream->recv.window;
      71      551526 :         if (stream->recv.state < QUIC_STREAM_RECV_STATE_RECVD &&
      72      533826 :             stream->recv.bytes + window - stream->recv.max_bytes >=
      73      533826 :             max(mss, (window >> QUIC_INQ_RWND_SHIFT))) {
      74      109073 :                 if (sk_under_memory_pressure(sk))
      75           0 :                         window >>= 1;
      76      109073 :                 stream->recv.max_bytes = stream->recv.bytes + window;
      77      109073 :                 if (!quic_outq_transmit_frame(sk, QUIC_FRAME_MAX_STREAM_DATA, stream, 0, true))
      78             :                         frame = 1;
      79             :         }
      80             : 
      81      442453 :         if (frame) {
      82      154750 :                 space->need_sack = 1;  /* Request an ACK frame to be bundled with it. */
      83      154750 :                 quic_outq_transmit(sk);
      84             :         }
      85             : }
      86             : 
      87             : /* Handle in-order stream frame delivery. */
      88     6359791 : static void quic_inq_stream_tail(struct sock *sk, struct quic_stream *stream,
      89             :                                  struct quic_frame *frame)
      90             : {
      91     6359791 :         struct quic_inqueue *inq = quic_inq(sk);
      92     6359791 :         struct quic_stream_update update = {};
      93     6359791 :         u64 overlap;
      94             : 
      95             :         /* Calculate overlap between stream's current recv offset and frame offset. */
      96     6359791 :         overlap = stream->recv.offset - frame->offset;
      97     6359791 :         if (overlap) { /* Discard overlapping prefix and adjust memory accounting. */
      98         412 :                 quic_inq_rfree((int)frame->len, sk);
      99         412 :                 frame->data += overlap;
     100         412 :                 frame->len -= overlap;
     101         412 :                 quic_inq_set_owner_r((int)frame->len, sk);
     102         412 :                 frame->offset += overlap;
     103             :         }
     104     6359791 :         stream->recv.offset += frame->len; /* Advance the stream's receive offset. */
     105             : 
     106     6359791 :         if (frame->stream_fin) {
     107             :                 /* Notify that the stream has been fully received. */
     108       17636 :                 update.id = stream->id;
     109       17636 :                 update.state = QUIC_STREAM_RECV_STATE_RECVD;
     110       17636 :                 update.finalsz = frame->offset + frame->len;
     111       17636 :                 quic_inq_event_recv(sk, QUIC_EVENT_STREAM_UPDATE, &update);
     112             : 
     113             :                 /* rfc9000#section-3.2:
     114             :                  *
     115             :                  * Once all data for the stream has been received, the receiving part
     116             :                  * enters the "Data Recvd" state.
     117             :                  */
     118       17636 :                 stream->recv.state = update.state;
     119             :                 /* Release stream and update limits to allow opening new streams. */
     120       17636 :                 quic_stream_recv_put(quic_streams(sk), stream, quic_is_serv(sk));
     121             :         }
     122             : 
     123     6359791 :         frame->offset = 0; /* Reset offset as it will be reused as read offset in recvmsg(). */
     124     6359791 :         if (frame->level) {
     125             :                 /* Stream frame was received at encryption level 0-RTT (early data).  Queue it
     126             :                  * into early_list. After the handshake completes and 1-RTT keys are installed,
     127             :                  * these frames will be moved to recv_list for delivery to the application.
     128             :                  */
     129         241 :                 frame->level = 0;
     130         241 :                 list_add_tail(&frame->list, &inq->early_list);
     131         241 :                 return;
     132             :         }
     133             :         /* Frame is ready for application delivery: queue in recv_list. */
     134     6359550 :         list_add_tail(&frame->list, &inq->recv_list);
     135     6359550 :         sk->sk_data_ready(sk); /* Notify socket that data is available. */
     136             : }
     137             : 
     138             : /* Check and optionally charge receive memory for a QUIC socket.
     139             :  * Equivalent to sk_rmem_schedule().
     140             :  */
     141     6363164 : static bool quic_sk_rmem_schedule(struct sock *sk, int size)
     142             : {
     143     6363164 :         int delta;
     144             : 
     145     6363164 :         if (!sk_has_account(sk))
     146             :                 return true;
     147     6363164 :         delta = size - sk->sk_forward_alloc;
     148     8933646 :         return delta <= 0 || __sk_mem_schedule(sk, delta, SK_MEM_RECV);
     149             : }
     150             : 
     151             : /* Process an incoming QUIC stream frame.
     152             :  *
     153             :  * Validates memory limits, flow control limits, and deduplicates before queuing.  Inserts frame
     154             :  * either in-order or out-of-order depending on stream state.
     155             :  *
     156             :  * Returns 0 on success, -ENOBUFS if memory/flow limits are hit, or -EINVAL on protocol violation.
     157             :  */
     158     6370599 : int quic_inq_stream_recv(struct sock *sk, struct quic_frame *frame)
     159             : {
     160     6370599 :         u64 offset = frame->offset, off, highest = 0;
     161     6370599 :         struct quic_stream *stream = frame->stream;
     162     6370599 :         struct quic_inqueue *inq = quic_inq(sk);
     163     6370599 :         struct quic_stream_update update = {};
     164     6370599 :         struct net *net = sock_net(sk);
     165     6370599 :         s64 stream_id = stream->id;
     166     6370599 :         struct list_head *head;
     167     6370599 :         struct quic_frame *pos;
     168             : 
     169             :         /* Discard duplicate frames that are fully covered by the current receive offset.
     170             :          * However, do not discard if this frame carries a FIN and the stream has not yet
     171             :          * received any FIN, to ensure proper handling of stream termination.
     172             :          */
     173     6370599 :         if (stream->recv.offset >= offset + frame->len &&
     174       10646 :             (stream->recv.state == QUIC_STREAM_RECV_STATE_SIZE_KNOWN ||
     175       10597 :              !frame->stream_fin)) {
     176       10642 :                 quic_frame_put(frame);
     177       10642 :                 return 0;
     178             :         }
     179             : 
     180             :         /* Check receive buffer size and system limits. */
     181     6359957 :         quic_inq_set_owner_r((int)frame->len, sk);
     182     6359957 :         if (sk_rmem_alloc_get(sk) > sk->sk_rcvbuf || !quic_sk_rmem_schedule(sk, frame->len)) {
     183           0 :                 QUIC_INC_STATS(net, QUIC_MIB_FRM_RCVBUFDROP);
     184           0 :                 quic_inq_rfree((int)frame->len, sk);
     185           0 :                 return -ENOBUFS;
     186             :         }
     187             : 
     188     6359957 :         off = offset + frame->len;
     189     6359957 :         if (off > stream->recv.highest) { /* New data beyond current highest seen. */
     190             :                 /* rfc9000#section-4.1:
     191             :                  *
     192             :                  * A receiver MUST close the connection with an error of type
     193             :                  * FLOW_CONTROL_ERROR if the sender violates the advertised connection or
     194             :                  * stream data limits.
     195             :                  */
     196     6348034 :                 highest = off - stream->recv.highest; /* New data beyond previous highest offset. */
     197     6348034 :                 if (inq->highest + highest > inq->max_bytes ||
     198     6348034 :                     stream->recv.highest + highest > stream->recv.max_bytes) {
     199           0 :                         frame->errcode = QUIC_TRANSPORT_ERROR_FLOW_CONTROL;
     200           0 :                         quic_inq_rfree((int)frame->len, sk);
     201           0 :                         return -ENOBUFS;
     202             :                 }
     203             :                 /* Check for violation of known final size (protocol error). */
     204     6348034 :                 if (stream->recv.finalsz && off > stream->recv.finalsz) {
     205           0 :                         frame->errcode = QUIC_TRANSPORT_ERROR_FINAL_SIZE;
     206           0 :                         quic_inq_rfree((int)frame->len, sk);
     207           0 :                         return -EINVAL;
     208             :                 }
     209             :         }
     210     6359957 :         if (!stream->recv.highest && !frame->stream_fin) {
     211             :                 /* Notify if first data received on stream. Skip FIN frame, as it will trigger
     212             :                  * a "Size Known" state later.
     213             :                  */
     214         273 :                 update.id = stream->id;
     215         273 :                 update.state = QUIC_STREAM_RECV_STATE_RECV;
     216         273 :                 quic_inq_event_recv(sk, QUIC_EVENT_STREAM_UPDATE, &update);
     217             :         }
     218     6359957 :         head = &inq->stream_list;
     219     6359957 :         if (stream->recv.offset < offset) { /* Out-of-order: insert in frame list in order. */
     220      788098 :                 list_for_each_entry(pos, head, list) {
     221      761805 :                         if (pos->stream->id < stream_id)
     222       15787 :                                 continue;
     223      746018 :                         if (pos->stream->id > stream_id) {
     224             :                                 head = &pos->list;
     225             :                                 break;
     226             :                         }
     227      745276 :                         if (pos->offset > offset) {
     228             :                                 head = &pos->list;
     229             :                                 break;
     230             :                         }
     231      744218 :                         if (pos->offset + pos->len >= offset + frame->len &&
     232          84 :                             (pos->stream_fin || !frame->stream_fin)) {
     233             :                                 /* Duplicate or overlapping frame.  Keep if it has FIN while
     234             :                                  * the other does not.
     235             :                                  */
     236          84 :                                 quic_inq_rfree((int)frame->len, sk);
     237          84 :                                 quic_frame_put(frame);
     238          84 :                                 return 0;
     239             :                         }
     240             :                 }
     241       28093 :                 if (frame->stream_fin) {
     242             :                         /* rfc9000#section-4.5:
     243             :                          *
     244             :                          * Once a final size for a stream is known, it cannot change. If a
     245             :                          * RESET_STREAM or STREAM frame is received indicating a change in the
     246             :                          * final size for the stream, an endpoint SHOULD respond with an error
     247             :                          * of type FINAL_SIZE_ERROR.
     248             :                          */
     249           8 :                         if (off < stream->recv.highest ||
     250           8 :                             (stream->recv.finalsz && stream->recv.finalsz != off)) {
     251           0 :                                 frame->errcode = QUIC_TRANSPORT_ERROR_FINAL_SIZE;
     252           0 :                                 quic_inq_rfree((int)frame->len, sk);
     253           0 :                                 return -EINVAL;
     254             :                         }
     255             :                         /* Notify that the stream has known the final size. */
     256           8 :                         update.id = stream->id;
     257           8 :                         update.state = QUIC_STREAM_RECV_STATE_SIZE_KNOWN;
     258           8 :                         update.finalsz = off;
     259           8 :                         quic_inq_event_recv(sk, QUIC_EVENT_STREAM_UPDATE, &update);
     260             : 
     261             :                         /* rfc9000#section-3.2:
     262             :                          *
     263             :                          * When a STREAM frame with a FIN bit is received, the final size of
     264             :                          * the stream is known; The receiving part of the stream then enters
     265             :                          * the "Size Known" state.
     266             :                          */
     267           8 :                         stream->recv.state = update.state;
     268           8 :                         stream->recv.finalsz = update.finalsz;
     269             :                 }
     270       28093 :                 list_add_tail(&frame->list, head);
     271       28093 :                 stream->recv.frags++;
     272       28093 :                 inq->highest += highest;
     273       28093 :                 stream->recv.highest += highest;
     274       28093 :                 return 0;
     275             :         }
     276             : 
     277             :         /* In-order: directly handled and queued. */
     278     6331780 :         inq->highest += highest;
     279     6331780 :         stream->recv.highest += highest;
     280     6331780 :         quic_inq_stream_tail(sk, stream, frame);
     281     6331780 :         if (!stream->recv.frags)
     282             :                 return 0;
     283             : 
     284             :         /* Check the buffered frames list and merge any frames contiguous with the current
     285             :          * stream offset to maintain ordered data delivery.
     286             :          */
     287       44015 :         list_for_each_entry_safe(frame, pos, head, list) {
     288       43463 :                 if (frame->stream->id < stream_id)
     289        5144 :                         continue;
     290       38319 :                 if (frame->stream->id > stream_id)
     291             :                         break;
     292       38306 :                 if (frame->offset > stream->recv.offset)
     293             :                         break;
     294       28093 :                 list_del(&frame->list);
     295       28093 :                 stream->recv.frags--;
     296       28093 :                 if (stream->recv.offset >= frame->offset + frame->len &&
     297          82 :                     (stream->recv.state == QUIC_STREAM_RECV_STATE_RECVD ||
     298          82 :                      !frame->stream_fin)) {
     299             :                         /* Duplicate frame. Do not discard if it has FIN and no FIN seen yet. */
     300          82 :                         quic_inq_rfree((int)frame->len, sk);
     301          82 :                         quic_frame_put(frame);
     302          82 :                         continue;
     303             :                 }
     304       28011 :                 quic_inq_stream_tail(sk, stream, frame);
     305             :         }
     306             :         return 0;
     307             : }
     308             : 
     309             : /* Purge all pending reassembly frames for a given stream.  Called when resetting a stream. */
     310       17660 : void quic_inq_stream_list_purge(struct sock *sk, struct quic_stream *stream)
     311             : {
     312       17660 :         struct list_head *head = &quic_inq(sk)->stream_list;
     313       17660 :         struct quic_frame *frame, *next;
     314       17660 :         int bytes = 0;
     315             : 
     316       17770 :         list_for_each_entry_safe(frame, next, head, list) {
     317         110 :                 if (frame->stream != stream)
     318         110 :                         continue;
     319           0 :                 list_del(&frame->list);
     320           0 :                 bytes += frame->len;
     321           0 :                 quic_frame_put(frame);
     322             :         }
     323       17660 :         quic_inq_rfree(bytes, sk);
     324       17660 : }
     325             : 
     326        4472 : static void quic_inq_list_purge(struct sock *sk, struct list_head *head)
     327             : {
     328        4472 :         struct quic_frame *frame, *next;
     329        4472 :         int bytes = 0;
     330             : 
     331        4472 :         list_for_each_entry_safe(frame, next, head, list) {
     332           0 :                 list_del(&frame->list);
     333           0 :                 bytes += frame->len;
     334           0 :                 quic_frame_put(frame);
     335             :         }
     336        4472 :         quic_inq_rfree(bytes, sk);
     337        4472 : }
     338             : 
     339             : /* Handle in-order crypto (handshake) frame delivery.
     340             :  *
     341             :  * Similar to quic_inq_stream_tail(), but with special handling for New Session Ticket Message
     342             :  * in crypto frame (level == 0). Tickets are saved in quic_ticket() and exposed to userspace
     343             :  * via getsockopt().
     344             :  */
     345        3195 : static void quic_inq_handshake_tail(struct sock *sk, struct quic_frame *frame)
     346             : {
     347        3195 :         struct quic_crypto *crypto = quic_crypto(sk, frame->level);
     348        3195 :         struct quic_data *ticket = quic_ticket(sk);
     349        3195 :         struct quic_inqueue *inq = quic_inq(sk);
     350        3195 :         u64 overlap, type, length;
     351        3195 :         struct list_head *head;
     352        3195 :         struct quic_frame *pos;
     353        3195 :         u32 len;
     354        3195 :         u8 *p;
     355             : 
     356        3195 :         overlap = crypto->recv_offset - frame->offset;
     357        3195 :         if (overlap) {
     358           1 :                 quic_inq_rfree((int)frame->len, sk);
     359           1 :                 frame->data += overlap;
     360           1 :                 frame->len -= overlap;
     361           1 :                 quic_inq_set_owner_r((int)frame->len, sk);
     362           1 :                 frame->offset += overlap;
     363             :         }
     364        3195 :         crypto->recv_offset += frame->len;
     365             : 
     366        3195 :         if (frame->level) {
     367             :                 /* For handshake messages, insert frame before any data/event frames. */
     368        2724 :                 head = &inq->recv_list;
     369        3918 :                 list_for_each_entry(pos, head, list) {
     370        1194 :                         if (!pos->level) {
     371             :                                 head = &pos->list;
     372             :                                 break;
     373             :                         }
     374             :                 }
     375             : 
     376        2724 :                 frame->offset = 0;
     377        2724 :                 list_add_tail(&frame->list, head);
     378        2724 :                 sk->sk_data_ready(sk);
     379        2724 :                 return;
     380             :         }
     381             : 
     382             :         /* Special handling for New Session Ticket Message (level == 0). */
     383         471 :         if (!crypto->ticket_ready && crypto->recv_offset <= QUIC_TICKET_MAX_LEN) {
     384             :                 /* Append received frame data to ticket buffer. */
     385         471 :                 quic_data_append(ticket, frame->data, frame->len);
     386             :                 /* Attempt to parse the TLS message if we have at least the 4-byte header. */
     387         471 :                 if (ticket->len >= 4) {
     388         471 :                         p = ticket->data;
     389         471 :                         len = ticket->len;
     390         471 :                         quic_get_int(&p, &len, &type, 1);
     391         471 :                         quic_get_int(&p, &len, &length, 3);
     392             :                         /* If the full TLS message is available, mark the ticket as ready. */
     393         471 :                         if (ticket->len >= length + 4) {
     394             :                                 /* Notify userspace with the full ticket message. Applications
     395             :                                  * can receive it via the NEW_SESSION_TICKET event or getsockopt().
     396             :                                  */
     397         470 :                                 crypto->ticket_ready  = 1;
     398         470 :                                 quic_inq_event_recv(sk, QUIC_EVENT_NEW_SESSION_TICKET, ticket);
     399             :                         }
     400             :                 }
     401             :         }
     402         471 :         quic_inq_rfree((int)frame->len, sk);
     403         471 :         quic_frame_put(frame); /* Data copied to ticket buffer; release the frame. */
     404             : }
     405             : 
     406             : /* Process an incoming QUIC crypto (handshake) frame.
     407             :  *
     408             :  * This function behaves similarly to quic_inq_stream_recv(), but operates on different crypto
     409             :  * levels instead of streams. It handles:
     410             :  *
     411             :  * Returns: 0 on success, or -ENOBUFS if buffer limits are exceeded.
     412             :  */
     413        3544 : int quic_inq_handshake_recv(struct sock *sk, struct quic_frame *frame)
     414             : {
     415        3544 :         u64 offset = frame->offset, crypto_offset;
     416        3544 :         struct quic_inqueue *inq = quic_inq(sk);
     417        3544 :         struct quic_crypto *crypto;
     418        3544 :         u8 level = frame->level;
     419        3544 :         struct list_head *head;
     420        3544 :         struct quic_frame *pos;
     421             : 
     422        3544 :         crypto = quic_crypto(sk, level);
     423        3544 :         crypto_offset = crypto->recv_offset;
     424        3544 :         pr_debug("%s: recv_offset: %llu, offset: %llu, level: %u, len: %u\n",
     425             :                  __func__, crypto_offset, offset, level, frame->len);
     426             : 
     427        3544 :         if (crypto_offset >= offset + frame->len) {
     428         345 :                 quic_frame_put(frame);
     429         345 :                 return 0;
     430             :         }
     431             : 
     432        3199 :         quic_inq_set_owner_r((int)frame->len, sk);
     433        3199 :         if (sk_rmem_alloc_get(sk) > sk->sk_rcvbuf || !quic_sk_rmem_schedule(sk, frame->len)) {
     434             :                 /* rfc9000#section-7.5:
     435             :                  *
     436             :                  * If an endpoint's buffer is exceeded during the handshake, it can expand its
     437             :                  * buffer temporarily to complete the handshake. If an endpoint does not expand
     438             :                  * its buffer, it MUST close the connection with a CRYPTO_BUFFER_EXCEEDED error
     439             :                  * code.
     440             :                  */
     441           0 :                 QUIC_INC_STATS(sock_net(sk), QUIC_MIB_FRM_RCVBUFDROP);
     442           0 :                 frame->errcode = QUIC_TRANSPORT_ERROR_CRYPTO_BUF_EXCEEDED;
     443           0 :                 quic_inq_rfree((int)frame->len, sk);
     444           0 :                 return -ENOBUFS;
     445             :         }
     446             : 
     447        3199 :         head = &inq->handshake_list;
     448        3199 :         if (offset > crypto_offset) {
     449          43 :                 list_for_each_entry(pos, head, list) {
     450          13 :                         if (pos->level < level)
     451           0 :                                 continue;
     452          13 :                         if (pos->level > level) {
     453             :                                 head = &pos->list;
     454             :                                 break;
     455             :                         }
     456          13 :                         if (pos->offset > offset) {
     457             :                                 head = &pos->list;
     458             :                                 break;
     459             :                         }
     460          13 :                         if (pos->offset + pos->len >= offset + frame->len) {
     461           4 :                                 quic_inq_rfree((int)frame->len, sk);
     462           4 :                                 quic_frame_put(frame);
     463           4 :                                 return 0;
     464             :                         }
     465             :                 }
     466          30 :                 list_add_tail(&frame->list, head);
     467          30 :                 return 0;
     468             :         }
     469             : 
     470        3165 :         quic_inq_handshake_tail(sk, frame);
     471             : 
     472        3195 :         list_for_each_entry_safe(frame, pos, head, list) {
     473          34 :                 if (frame->level < level)
     474           0 :                         continue;
     475          34 :                 if (frame->level > level)
     476             :                         break;
     477          34 :                 if (frame->offset > crypto->recv_offset)
     478             :                         break;
     479          30 :                 list_del(&frame->list);
     480          30 :                 if (crypto->recv_offset >= frame->offset + frame->len) {
     481           0 :                         quic_inq_rfree((int)frame->len, sk);
     482           0 :                         quic_frame_put(frame);
     483           0 :                         continue;
     484             :                 }
     485          30 :                 quic_inq_handshake_tail(sk, frame);
     486             :         }
     487             :         return 0;
     488             : }
     489             : 
     490             : /* Populate transport parameters from inqueue. */
     491        2079 : void quic_inq_get_param(struct sock *sk, struct quic_transport_param *p)
     492             : {
     493        2079 :         struct quic_inqueue *inq = quic_inq(sk);
     494             : 
     495        2079 :         if (p->remote)
     496             :                 return;
     497             : 
     498        2055 :         p->disable_compatible_version = inq->disable_compatible_version;
     499        2055 :         p->disable_1rtt_encryption = inq->disable_1rtt_encryption;
     500        2055 :         p->max_datagram_frame_size = inq->max_datagram_frame_size;
     501        2055 :         p->max_udp_payload_size = inq->max_udp_payload_size;
     502        2055 :         p->ack_delay_exponent = inq->ack_delay_exponent;
     503        2055 :         p->max_idle_timeout = inq->max_idle_timeout;
     504        2055 :         p->grease_quic_bit = inq->grease_quic_bit;
     505        2055 :         p->stateless_reset = inq->stateless_reset;
     506        2055 :         p->max_ack_delay = inq->max_ack_delay;
     507        2055 :         p->max_data = inq->max_data;
     508             : }
     509             : 
     510             : /* Configure inqueue from transport parameters. */
     511        3172 : void quic_inq_set_param(struct sock *sk, struct quic_transport_param *p)
     512             : {
     513        3172 :         struct quic_packet *packet = quic_packet(sk);
     514        3172 :         struct quic_inqueue *inq = quic_inq(sk);
     515             : 
     516        3172 :         if (p->remote) {
     517        1004 :                 if (p->max_idle_timeout &&
     518        1002 :                     (!inq->max_idle_timeout || p->max_idle_timeout < inq->max_idle_timeout))
     519         399 :                         inq->timeout = p->max_idle_timeout;
     520             : 
     521        1004 :                 if (inq->disable_1rtt_encryption && p->disable_1rtt_encryption)
     522           4 :                         quic_packet_set_taglen(packet, 0);
     523        1004 :                 return;
     524             :         }
     525             : 
     526        2168 :         inq->disable_compatible_version = p->disable_compatible_version;
     527        2168 :         inq->disable_1rtt_encryption = p->disable_1rtt_encryption;
     528        2168 :         inq->max_datagram_frame_size = p->max_datagram_frame_size;
     529        2168 :         inq->max_udp_payload_size = p->max_udp_payload_size;
     530        2168 :         inq->ack_delay_exponent = p->ack_delay_exponent;
     531        2168 :         inq->max_idle_timeout = p->max_idle_timeout;
     532        2168 :         inq->grease_quic_bit = p->grease_quic_bit;
     533        2168 :         inq->stateless_reset = p->stateless_reset;
     534        2168 :         inq->max_ack_delay = p->max_ack_delay;
     535        2168 :         inq->max_data = p->max_data;
     536             : 
     537        2168 :         inq->timeout = inq->max_idle_timeout;
     538        2168 :         inq->max_bytes = inq->max_data;
     539        2168 :         sk->sk_rcvbuf = (int)p->max_data * 2;
     540             : }
     541             : 
     542             : /* Process an incoming QUIC event and handle it for delivery. */
     543      153736 : int quic_inq_event_recv(struct sock *sk, u8 event, void *args)
     544             : {
     545      153736 :         struct list_head *head = &quic_inq(sk)->recv_list;
     546      153736 :         struct quic_frame *frame, *pos;
     547      153736 :         u32 args_len = 0;
     548      153736 :         u8 *p;
     549             : 
     550      153736 :         if (!event || event > QUIC_EVENT_MAX)
     551             :                 return -EINVAL;
     552             : 
     553      153736 :         if (!(quic_inq(sk)->events & BIT(event)))
     554             :                 return 0;  /* Event type not subscribed by user. */
     555             : 
     556          68 :         switch (event) { /* Determine size of the argument payload based on event type. */
     557             :         case QUIC_EVENT_STREAM_UPDATE:
     558             :                 args_len = sizeof(struct quic_stream_update);
     559             :                 break;
     560           0 :         case QUIC_EVENT_STREAM_MAX_DATA:
     561           0 :                 args_len = sizeof(struct quic_stream_max_data);
     562           0 :                 break;
     563           8 :         case QUIC_EVENT_STREAM_MAX_STREAM:
     564           8 :                 args_len = sizeof(u64);
     565           8 :                 break;
     566           8 :         case QUIC_EVENT_CONNECTION_ID:
     567           8 :                 args_len = sizeof(struct quic_connection_id_info);
     568           8 :                 break;
     569           4 :         case QUIC_EVENT_CONNECTION_CLOSE:
     570           4 :                 args_len = sizeof(struct quic_connection_close);
     571           4 :                 p = ((struct quic_connection_close *)args)->phrase;
     572           4 :                 if (*p)
     573           8 :                         args_len += strlen(p) + 1;
     574             :                 break;
     575          12 :         case QUIC_EVENT_CONNECTION_MIGRATION:
     576             :         case QUIC_EVENT_KEY_UPDATE:
     577          12 :                 args_len = sizeof(u8);
     578          12 :                 break;
     579           4 :         case QUIC_EVENT_NEW_SESSION_TICKET:
     580             :         case QUIC_EVENT_NEW_TOKEN:
     581           4 :                 args_len = ((struct quic_data *)args)->len;
     582           4 :                 args = ((struct quic_data *)args)->data;
     583           4 :                 break;
     584             :         default:
     585             :                 return -EINVAL;
     586             :         }
     587             : 
     588          68 :         frame = quic_frame_alloc(1 + args_len, NULL, GFP_ATOMIC);
     589          68 :         if (!frame) {
     590           0 :                 pr_debug("%s: event: %u, args_len: %u\n", __func__, event, args_len);
     591           0 :                 return -ENOMEM;
     592             :         }
     593          68 :         p = quic_put_data(frame->data, &event, 1);
     594          68 :         quic_put_data(p, args, args_len);
     595          68 :         frame->event = 1; /* Mark this frame as an event. */
     596          68 :         frame->offset = 0;
     597             : 
     598             :         /* Insert event frame ahead of stream or dgram data. */
     599          72 :         list_for_each_entry(pos, head, list) {
     600          12 :                 if (!pos->level && !pos->event) {
     601             :                         head = &pos->list;
     602             :                         break;
     603             :                 }
     604             :         }
     605          68 :         quic_inq_set_owner_r((int)frame->len, sk);
     606          68 :         list_add_tail(&frame->list, head);
     607          68 :         sk->sk_data_ready(sk);
     608          68 :         return 0;
     609             : }
     610             : 
     611             : /* Process an incoming QUIC datagram frame. */
     612           8 : int quic_inq_dgram_recv(struct sock *sk, struct quic_frame *frame)
     613             : {
     614           8 :         quic_inq_set_owner_r((int)frame->len, sk);
     615           8 :         if (sk_rmem_alloc_get(sk) > sk->sk_rcvbuf || !quic_sk_rmem_schedule(sk, frame->len)) {
     616           0 :                 QUIC_INC_STATS(sock_net(sk), QUIC_MIB_FRM_RCVBUFDROP);
     617           0 :                 quic_inq_rfree((int)frame->len, sk);
     618           0 :                 return -ENOBUFS;
     619             :         }
     620             : 
     621           8 :         frame->dgram = 1; /* Mark the frame as a datagram and prepare for delivery. */
     622           8 :         frame->offset = 0;
     623           8 :         list_add_tail(&frame->list, &quic_inq(sk)->recv_list);
     624           8 :         sk->sk_data_ready(sk);
     625           8 :         return 0;
     626             : }
     627             : 
     628      554326 : void quic_inq_data_read(struct sock *sk, u32 bytes)
     629             : {
     630      554326 :         quic_inq_rfree((int)bytes, sk);
     631      554326 : }
     632             : 
     633             : /* Workqueue handler to process decrypted QUIC packets. */
     634           0 : static void quic_inq_decrypted_work(struct work_struct *work)
     635             : {
     636           0 :         struct quic_sock *qs = container_of(work, struct quic_sock, inq.work);
     637           0 :         struct sock *sk = &qs->inet.sk;
     638           0 :         struct sk_buff_head *head;
     639           0 :         struct sk_buff *skb;
     640             : 
     641           0 :         lock_sock(sk);
     642           0 :         head = &sk->sk_receive_queue;
     643           0 :         if (sock_flag(sk, SOCK_DEAD)) { /* If the socket is already dead, drop all pending skbs. */
     644           0 :                 skb_queue_purge(head);
     645           0 :                 goto out;
     646             :         }
     647             : 
     648           0 :         skb = skb_dequeue(head);
     649           0 :         while (skb) {
     650           0 :                 QUIC_SKB_CB(skb)->resume = 1; /* Mark skb decrypted already before processing. */
     651           0 :                 quic_packet_process(sk, skb);
     652           0 :                 skb = skb_dequeue(head);
     653             :         }
     654           0 : out:
     655           0 :         release_sock(sk);
     656           0 :         sock_put(sk); /* Drop the hold from quic_inq_decrypted_tail(). */
     657           0 : }
     658             : 
     659             : /* Queue an decrypted SKB and schedule processing.
     660             :  *
     661             :  * This function queues a fully decrypted skb for asynchronous processing and schedules
     662             :  * the workqueue to process it.
     663             :  */
     664           0 : void quic_inq_decrypted_tail(struct sock *sk, struct sk_buff *skb)
     665             : {
     666           0 :         struct quic_inqueue *inq = quic_inq(sk);
     667             : 
     668           0 :         sock_hold(sk);
     669             :         /* Add skb to receive queue, and process it later in quic_inq_decrypted_work(). */
     670           0 :         skb_queue_tail(&sk->sk_receive_queue, skb);
     671             : 
     672             :         /* Schedule work to process queued decrypted packets.  If work was already pending,
     673             :          * drop the extra hold.
     674             :          */
     675           0 :         if (!schedule_work(&inq->work))
     676           0 :                 sock_put(sk);
     677           0 : }
     678             : 
     679        2132 : void quic_inq_backlog_tail(struct sock *sk, struct sk_buff *skb)
     680             : {
     681        2132 :         __skb_queue_tail(&quic_inq(sk)->backlog_list, skb);
     682        2132 : }
     683             : 
     684        1119 : void quic_inq_init(struct sock *sk)
     685             : {
     686        1119 :         struct quic_inqueue *inq = quic_inq(sk);
     687             : 
     688        1119 :         skb_queue_head_init(&inq->backlog_list);
     689        1119 :         INIT_LIST_HEAD(&inq->handshake_list);
     690        1119 :         INIT_LIST_HEAD(&inq->stream_list);
     691        1119 :         INIT_LIST_HEAD(&inq->early_list);
     692        1119 :         INIT_LIST_HEAD(&inq->recv_list);
     693        1119 :         INIT_WORK(&inq->work, quic_inq_decrypted_work);
     694        1119 : }
     695             : 
     696        1118 : void quic_inq_free(struct sock *sk)
     697             : {
     698        1118 :         struct quic_inqueue *inq = quic_inq(sk);
     699             : 
     700        1118 :         __skb_queue_purge(&sk->sk_receive_queue);
     701        1118 :         __skb_queue_purge(&inq->backlog_list);
     702        1118 :         quic_inq_list_purge(sk, &inq->handshake_list);
     703        1118 :         quic_inq_list_purge(sk, &inq->stream_list);
     704        1118 :         quic_inq_list_purge(sk, &inq->early_list);
     705        1118 :         quic_inq_list_purge(sk, &inq->recv_list);
     706        1118 : }

Generated by: LCOV version 1.14