LCOV - code coverage report
Current view: top level - home/net-next/net/quic - common.c (source / functions) Hit Total Coverage
Test: quic.info Lines: 221 258 85.7 %
Date: 2025-07-04 13:24:45 Functions: 23 25 92.0 %

          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 "common.h"
      14             : 
      15             : #define QUIC_VARINT_1BYTE_MAX           0x3fULL
      16             : #define QUIC_VARINT_2BYTE_MAX           0x3fffULL
      17             : #define QUIC_VARINT_4BYTE_MAX           0x3fffffffULL
      18             : 
      19             : #define QUIC_VARINT_2BYTE_PREFIX        0x40
      20             : #define QUIC_VARINT_4BYTE_PREFIX        0x80
      21             : #define QUIC_VARINT_8BYTE_PREFIX        0xc0
      22             : 
      23             : #define QUIC_VARINT_LENGTH(p)           BIT((*(p)) >> 6)
      24             : #define QUIC_VARINT_VALUE_MASK          0x3f
      25             : 
      26             : static struct quic_hash_table quic_hash_tables[QUIC_HT_MAX_TABLES];
      27             : 
      28        1536 : struct quic_hash_head *quic_sock_hash(u32 hash)
      29             : {
      30        1536 :         return &quic_hash_tables[QUIC_HT_SOCK].hash[hash];
      31             : }
      32             : 
      33        6362 : struct quic_hash_head *quic_sock_head(struct net *net, union quic_addr *s, union quic_addr *d)
      34             : {
      35        6362 :         struct quic_hash_table *ht = &quic_hash_tables[QUIC_HT_SOCK];
      36             : 
      37        6362 :         return &ht->hash[quic_ahash(net, s, d) & (ht->size - 1)];
      38             : }
      39             : 
      40        1331 : struct quic_hash_head *quic_listen_sock_head(struct net *net, u16 port)
      41             : {
      42        1331 :         struct quic_hash_table *ht = &quic_hash_tables[QUIC_HT_LISTEN_SOCK];
      43             : 
      44        1331 :         return &ht->hash[port & (ht->size - 1)];
      45             : }
      46             : 
      47     6587223 : struct quic_hash_head *quic_source_conn_id_head(struct net *net, u8 *scid)
      48             : {
      49     6587223 :         struct quic_hash_table *ht = &quic_hash_tables[QUIC_HT_CONNECTION_ID];
      50             : 
      51     6587223 :         return &ht->hash[jhash(scid, 4, 0) & (ht->size - 1)];
      52             : }
      53             : 
      54        3883 : struct quic_hash_head *quic_udp_sock_head(struct net *net, u16 port)
      55             : {
      56        3883 :         struct quic_hash_table *ht = &quic_hash_tables[QUIC_HT_UDP_SOCK];
      57             : 
      58        3883 :         return &ht->hash[port & (ht->size - 1)];
      59             : }
      60             : 
      61     8630162 : struct quic_hash_head *quic_stream_head(struct quic_hash_table *ht, s64 stream_id)
      62             : {
      63     8630162 :         return &ht->hash[stream_id & (ht->size - 1)];
      64             : }
      65             : 
      66           0 : void quic_hash_tables_destroy(void)
      67             : {
      68           0 :         struct quic_hash_table *ht;
      69           0 :         int table;
      70             : 
      71           0 :         for (table = 0; table < QUIC_HT_MAX_TABLES; table++) {
      72           0 :                 ht = &quic_hash_tables[table];
      73           0 :                 ht->size = QUIC_HT_SIZE;
      74           0 :                 kfree(ht->hash);
      75             :         }
      76           0 : }
      77             : 
      78           1 : int quic_hash_tables_init(void)
      79             : {
      80           1 :         struct quic_hash_head *head;
      81           1 :         struct quic_hash_table *ht;
      82           1 :         int table, i;
      83             : 
      84           5 :         for (table = 0; table < QUIC_HT_MAX_TABLES; table++) {
      85           4 :                 ht = &quic_hash_tables[table];
      86           4 :                 ht->size = QUIC_HT_SIZE;
      87           4 :                 head = kmalloc_array(ht->size, sizeof(*head), GFP_KERNEL);
      88           4 :                 if (!head) {
      89           0 :                         quic_hash_tables_destroy();
      90           0 :                         return -ENOMEM;
      91             :                 }
      92         260 :                 for (i = 0; i < ht->size; i++) {
      93         256 :                         INIT_HLIST_HEAD(&head[i].head);
      94         256 :                         if (table == QUIC_HT_UDP_SOCK) {
      95          64 :                                 mutex_init(&head[i].m_lock);
      96          64 :                                 continue;
      97             :                         }
      98         256 :                         spin_lock_init(&head[i].s_lock);
      99             :                 }
     100           4 :                 ht->hash = head;
     101             :         }
     102             : 
     103             :         return 0;
     104             : }
     105             : 
     106             : union quic_var {
     107             :         u8      u8;
     108             :         __be16  be16;
     109             :         __be32  be32;
     110             :         __be64  be64;
     111             : };
     112             : 
     113             : /* Returns the number of bytes required to encode a QUIC variable-length integer. */
     114    32256039 : u8 quic_var_len(u64 n)
     115             : {
     116    32247183 :         if (n <= QUIC_VARINT_1BYTE_MAX)
     117             :                 return 1;
     118    21275079 :         if (n <= QUIC_VARINT_2BYTE_MAX)
     119             :                 return 2;
     120    10421571 :         if (n <= QUIC_VARINT_4BYTE_MAX)
     121    10412645 :                 return 4;
     122             :         return 8;
     123             : }
     124             : 
     125             : /* Decodes a QUIC variable-length integer from a buffer. */
     126    22169476 : u8 quic_get_var(u8 **pp, u32 *plen, u64 *val)
     127             : {
     128    22169476 :         union quic_var n = {};
     129    22169476 :         u8 *p = *pp, len;
     130    22169476 :         u64 v = 0;
     131             : 
     132    22169476 :         if (!*plen)
     133             :                 return 0;
     134             : 
     135    22169476 :         len = QUIC_VARINT_LENGTH(p);
     136    22169476 :         if (*plen < len)
     137             :                 return 0;
     138             : 
     139    22169476 :         switch (len) {
     140     8188079 :         case 1:
     141     8188079 :                 v = *p;
     142     8188079 :                 break;
     143     7103296 :         case 2:
     144     7103296 :                 memcpy(&n.be16, p, 2);
     145     7103296 :                 n.u8 &= QUIC_VARINT_VALUE_MASK;
     146     7103296 :                 v = be16_to_cpu(n.be16);
     147     7103296 :                 break;
     148     6877273 :         case 4:
     149     6877273 :                 memcpy(&n.be32, p, 4);
     150     6877273 :                 n.u8 &= QUIC_VARINT_VALUE_MASK;
     151     6877273 :                 v = be32_to_cpu(n.be32);
     152     6877273 :                 break;
     153         828 :         case 8:
     154         828 :                 memcpy(&n.be64, p, 8);
     155         828 :                 n.u8 &= QUIC_VARINT_VALUE_MASK;
     156         828 :                 v = be64_to_cpu(n.be64);
     157         828 :                 break;
     158             :         default:
     159             :                 return 0;
     160             :         }
     161             : 
     162    22169476 :         *plen -= len;
     163    22169476 :         *pp = p + len;
     164    22169476 :         *val = v;
     165    22169476 :         return len;
     166             : }
     167             : 
     168             : /* Reads a fixed-length integer from the buffer. */
     169     6610889 : u32 quic_get_int(u8 **pp, u32 *plen, u64 *val, u32 len)
     170             : {
     171     6610889 :         union quic_var n;
     172     6610889 :         u8 *p = *pp;
     173     6610889 :         u64 v = 0;
     174             : 
     175     6610889 :         if (*plen < len)
     176             :                 return 0;
     177     6610889 :         *plen -= len;
     178             : 
     179     6610889 :         switch (len) {
     180      144039 :         case 1:
     181      144039 :                 v = *p;
     182      144039 :                 break;
     183        7571 :         case 2:
     184        7571 :                 memcpy(&n.be16, p, 2);
     185        7571 :                 v = be16_to_cpu(n.be16);
     186        7571 :                 break;
     187         907 :         case 3:
     188         907 :                 n.be32 = 0;
     189         907 :                 memcpy(((u8 *)&n.be32) + 1, p, 3);
     190         907 :                 v = be32_to_cpu(n.be32);
     191         907 :                 break;
     192     6458372 :         case 4:
     193     6458372 :                 memcpy(&n.be32, p, 4);
     194     6458372 :                 v = be32_to_cpu(n.be32);
     195     6458372 :                 break;
     196           0 :         case 8:
     197           0 :                 memcpy(&n.be64, p, 8);
     198           0 :                 v = be64_to_cpu(n.be64);
     199           0 :                 break;
     200             :         default:
     201             :                 return 0;
     202             :         }
     203     6610889 :         *pp = p + len;
     204     6610889 :         *val = v;
     205     6610889 :         return len;
     206             : }
     207             : 
     208          56 : u32 quic_get_data(u8 **pp, u32 *plen, u8 *data, u32 len)
     209             : {
     210          56 :         if (*plen < len)
     211             :                 return 0;
     212             : 
     213         112 :         memcpy(data, *pp, len);
     214          56 :         *pp += len;
     215          56 :         *plen -= len;
     216             : 
     217          56 :         return len;
     218             : }
     219             : 
     220             : /* Encodes a value into the QUIC variable-length integer format. */
     221    37207030 : u8 *quic_put_var(u8 *p, u64 num)
     222             : {
     223    37207030 :         union quic_var n;
     224             : 
     225    37207030 :         if (num <= QUIC_VARINT_1BYTE_MAX) {
     226    19406304 :                 *p++ = (u8)(num & 0xff);
     227    19406304 :                 return p;
     228             :         }
     229    17800726 :         if (num <= QUIC_VARINT_2BYTE_MAX) {
     230     9004566 :                 n.be16 = cpu_to_be16((u16)num);
     231     9004566 :                 *((__be16 *)p) = n.be16;
     232     9004566 :                 *p |= QUIC_VARINT_2BYTE_PREFIX;
     233     9004566 :                 return p + 2;
     234             :         }
     235     8796160 :         if (num <= QUIC_VARINT_4BYTE_MAX) {
     236     8787000 :                 n.be32 = cpu_to_be32((u32)num);
     237     8787000 :                 *((__be32 *)p) = n.be32;
     238     8787000 :                 *p |= QUIC_VARINT_4BYTE_PREFIX;
     239     8787000 :                 return p + 4;
     240             :         }
     241        9160 :         n.be64 = cpu_to_be64(num);
     242        9160 :         *((__be64 *)p) = n.be64;
     243        9160 :         *p |= QUIC_VARINT_8BYTE_PREFIX;
     244        9160 :         return p + 8;
     245             : }
     246             : 
     247             : /* Writes a fixed-length integer to the buffer in network byte order. */
     248     6577159 : u8 *quic_put_int(u8 *p, u64 num, u8 len)
     249             : {
     250     6577159 :         union quic_var n;
     251             : 
     252     6577159 :         switch (len) {
     253       12106 :         case 1:
     254       12106 :                 *p++ = (u8)(num & 0xff);
     255       12106 :                 return p;
     256           0 :         case 2:
     257           0 :                 n.be16 = cpu_to_be16((u16)(num & 0xffff));
     258           0 :                 *((__be16 *)p) = n.be16;
     259           0 :                 return p + 2;
     260     6565053 :         case 4:
     261     6565053 :                 n.be32 = cpu_to_be32((u32)num);
     262     6565053 :                 *((__be32 *)p) = n.be32;
     263     6565053 :                 return p + 4;
     264             :         default:
     265             :                 return NULL;
     266             :         }
     267             : }
     268             : 
     269             : /* Encodes a value as a variable-length integer with explicit length. */
     270        5583 : u8 *quic_put_varint(u8 *p, u64 num, u8 len)
     271             : {
     272        5583 :         union quic_var n;
     273             : 
     274        5583 :         switch (len) {
     275           0 :         case 1:
     276           0 :                 *p++ = (u8)(num & 0xff);
     277           0 :                 return p;
     278           0 :         case 2:
     279           0 :                 n.be16 = cpu_to_be16((u16)(num & 0xffff));
     280           0 :                 *((__be16 *)p) = n.be16;
     281           0 :                 *p |= QUIC_VARINT_2BYTE_PREFIX;
     282           0 :                 return p + 2;
     283        5583 :         case 4:
     284        5583 :                 n.be32 = cpu_to_be32((u32)num);
     285        5583 :                 *((__be32 *)p) = n.be32;
     286        5583 :                 *p |= QUIC_VARINT_4BYTE_PREFIX;
     287        5583 :                 return p + 4;
     288             :         default:
     289             :                 return NULL;
     290             :         }
     291             : }
     292             : 
     293    22043437 : u8 *quic_put_data(u8 *p, u8 *data, u32 len)
     294             : {
     295    22043437 :         if (!len)
     296             :                 return p;
     297             : 
     298    43880996 :         memcpy(p, data, len);
     299    21940498 :         return p + len;
     300             : }
     301             : 
     302             : /* Writes a transport parameter as two varints: ID and value length, followed by value. */
     303        8856 : u8 *quic_put_param(u8 *p, u16 id, u64 value)
     304             : {
     305        8856 :         p = quic_put_var(p, id);
     306       15871 :         p = quic_put_var(p, quic_var_len(value));
     307        8856 :         return quic_put_var(p, value);
     308             : }
     309             : 
     310             : /* Reads a QUIC transport parameter value. */
     311        8459 : u8 quic_get_param(u64 *pdest, u8 **pp, u32 *plen)
     312             : {
     313        8459 :         u64 valuelen;
     314             : 
     315        8459 :         if (!quic_get_var(pp, plen, &valuelen))
     316             :                 return 0;
     317             : 
     318        8459 :         if (*plen < valuelen)
     319             :                 return 0;
     320             : 
     321        8459 :         if (!quic_get_var(pp, plen, pdest))
     322             :                 return 0;
     323             : 
     324        8459 :         return (u8)valuelen;
     325             : }
     326             : 
     327             : /* rfc9000#section-a.3: DecodePacketNumber()
     328             :  *
     329             :  * Reconstructs the full packet number from a truncated one.
     330             :  */
     331     6575216 : s64 quic_get_num(s64 max_pkt_num, s64 pkt_num, u32 n)
     332             : {
     333     6575216 :         s64 expected = max_pkt_num + 1;
     334     6575216 :         s64 win = BIT_ULL(n * 8);
     335     6575216 :         s64 hwin = win / 2;
     336     6575216 :         s64 mask = win - 1;
     337     6575216 :         s64 cand;
     338             : 
     339     6575216 :         cand = (expected & ~mask) | pkt_num;
     340     6575216 :         if (cand <= expected - hwin && cand < (1ULL << 62) - win)
     341           7 :                 return cand + win;
     342     6575209 :         if (cand > expected + hwin && cand >= win)
     343           0 :                 return cand - win;
     344             :         return cand;
     345             : }
     346             : 
     347         897 : int quic_data_dup(struct quic_data *to, u8 *data, u32 len)
     348             : {
     349         897 :         if (!len)
     350             :                 return 0;
     351             : 
     352         887 :         data = kmemdup(data, len, GFP_ATOMIC);
     353         887 :         if (!data)
     354             :                 return -ENOMEM;
     355             : 
     356         887 :         kfree(to->data);
     357         887 :         to->data = data;
     358         887 :         to->len = len;
     359         887 :         return 0;
     360             : }
     361             : 
     362         471 : int quic_data_append(struct quic_data *to, u8 *data, u32 len)
     363             : {
     364         471 :         u8 *p;
     365             : 
     366         471 :         if (!len)
     367             :                 return 0;
     368             : 
     369         471 :         p = kzalloc(to->len + len, GFP_ATOMIC);
     370         471 :         if (!p)
     371             :                 return -ENOMEM;
     372         471 :         p = quic_put_data(p, to->data, to->len);
     373         471 :         p = quic_put_data(p, data, len);
     374             : 
     375         471 :         kfree(to->data);
     376         471 :         to->len = to->len + len;
     377         471 :         to->data = p - to->len;
     378         471 :         return 0;
     379             : }
     380             : 
     381             : /* Check whether 'd2' is equal to any element inside the list 'd1'.
     382             :  *
     383             :  * 'd1' is assumed to be a sequence of length-prefixed elements. Each element
     384             :  * is compared to 'd2' using 'quic_data_cmp()'.
     385             :  *
     386             :  * Returns 1 if a match is found, 0 otherwise.
     387             :  */
     388         362 : int quic_data_has(struct quic_data *d1, struct quic_data *d2)
     389             : {
     390         362 :         struct quic_data d;
     391         362 :         u64 length;
     392         362 :         u32 len;
     393         362 :         u8 *p;
     394             : 
     395         386 :         for (p = d1->data, len = d1->len; len; len -= length, p += length) {
     396         386 :                 quic_get_int(&p, &len, &length, 1);
     397         386 :                 quic_data(&d, p, length);
     398         386 :                 if (!quic_data_cmp(&d, d2))
     399             :                         return 1;
     400             :         }
     401             :         return 0;
     402             : }
     403             : 
     404             : /* Check if any element of 'd1' is present in the list 'd2'.
     405             :  *
     406             :  * Iterates through each element in 'd1', and uses 'quic_data_has()' to check
     407             :  * for its presence in 'd2'.
     408             :  *
     409             :  * Returns 1 if any match is found, 0 otherwise.
     410             :  */
     411           0 : int quic_data_match(struct quic_data *d1, struct quic_data *d2)
     412             : {
     413           0 :         struct quic_data d;
     414           0 :         u64 length;
     415           0 :         u32 len;
     416           0 :         u8 *p;
     417             : 
     418           0 :         for (p = d1->data, len = d1->len; len; len -= length, p += length) {
     419           0 :                 quic_get_int(&p, &len, &length, 1);
     420           0 :                 quic_data(&d, p, length);
     421           0 :                 if (quic_data_has(d2, &d))
     422             :                         return 1;
     423             :         }
     424             :         return 0;
     425             : }
     426             : 
     427             : /* Serialize a list of 'quic_data' elements into a comma-separated string.
     428             :  *
     429             :  * Each element in 'from' is length-prefixed. This function copies their raw
     430             :  * content into the output buffer 'to', inserting commas in between. The
     431             :  * resulting string length is written to '*plen'.
     432             :  */
     433          16 : void quic_data_to_string(u8 *to, u32 *plen, struct quic_data *from)
     434             : {
     435          16 :         struct quic_data d;
     436          16 :         u8 *data = to, *p;
     437          16 :         u64 length;
     438          16 :         u32 len;
     439             : 
     440          32 :         for (p = from->data, len = from->len; len; len -= length, p += length) {
     441          16 :                 quic_get_int(&p, &len, &length, 1);
     442          16 :                 quic_data(&d, p, length);
     443          16 :                 data = quic_put_data(data, d.data, d.len);
     444          16 :                 if (len - length)
     445           0 :                         data = quic_put_int(data, ',', 1);
     446             :         }
     447          16 :         *plen = data - to;
     448          16 : }
     449             : 
     450             : /* Parse a comma-separated string into a 'quic_data' list format.
     451             :  *
     452             :  * Each comma-separated token is turned into a length-prefixed element. The
     453             :  * first byte of each element stores the length (minus one). Elements are
     454             :  * stored in 'to->data', and 'to->len' is updated.
     455             :  */
     456         126 : void quic_data_from_string(struct quic_data *to, u8 *from, u32 len)
     457             : {
     458         126 :         struct quic_data d;
     459         126 :         u8 *p = to->data;
     460             : 
     461         126 :         to->len = 0;
     462         270 :         while (len) {
     463         144 :                 d.data = p++;
     464         144 :                 d.len  = 1;
     465         162 :                 while (len && *from == ' ') {
     466          18 :                         from++;
     467          18 :                         len--;
     468             :                 }
     469        1214 :                 while (len) {
     470        1088 :                         if (*from == ',') {
     471          18 :                                 from++;
     472          18 :                                 len--;
     473          18 :                                 break;
     474             :                         }
     475        1070 :                         *p++ = *from++;
     476        1070 :                         len--;
     477        1070 :                         d.len++;
     478             :                 }
     479         144 :                 *d.data = (u8)(d.len - 1);
     480         144 :                 to->len += d.len;
     481             :         }
     482         126 : }

Generated by: LCOV version 1.14