LCOV - code coverage report
Current view: top level - home/net-next/net/quic - protocol.c (source / functions) Hit Total Coverage
Test: quic.info Lines: 196 269 72.9 %
Date: 2025-07-04 13:24:45 Functions: 18 20 90.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 <net/inet_common.h>
      14             : #include <linux/version.h>
      15             : #include <linux/proc_fs.h>
      16             : #include <net/protocol.h>
      17             : #include <net/rps.h>
      18             : #include <net/tls.h>
      19             : 
      20             : #include "socket.h"
      21             : 
      22             : static unsigned int quic_net_id __read_mostly;
      23             : 
      24             : struct quic_transport_param quic_default_param __read_mostly;
      25             : struct kmem_cache *quic_frame_cachep __read_mostly;
      26             : struct percpu_counter quic_sockets_allocated;
      27             : 
      28             : long sysctl_quic_mem[3];
      29             : int sysctl_quic_rmem[3];
      30             : int sysctl_quic_wmem[3];
      31             : 
      32         581 : static int quic_inet_connect(struct socket *sock, struct sockaddr *addr, int addr_len, int flags)
      33             : {
      34         581 :         struct sock *sk = sock->sk;
      35         581 :         const struct proto *prot;
      36             : 
      37         581 :         if (addr_len < (int)sizeof(addr->sa_family))
      38             :                 return -EINVAL;
      39             : 
      40         581 :         prot = READ_ONCE(sk->sk_prot);
      41             : 
      42         581 :         return prot->connect(sk, addr, addr_len);
      43             : }
      44             : 
      45         118 : static int quic_inet_listen(struct socket *sock, int backlog)
      46             : {
      47         118 :         struct quic_conn_id_set *source, *dest;
      48         118 :         struct quic_conn_id conn_id, *active;
      49         118 :         struct quic_path_group *paths;
      50         118 :         struct quic_crypto *crypto;
      51         118 :         struct quic_packet *packet;
      52         118 :         struct sock *sk = sock->sk;
      53         118 :         union quic_addr *a;
      54         118 :         int err = 0;
      55             : 
      56         118 :         lock_sock(sk);
      57             : 
      58         118 :         crypto = quic_crypto(sk, QUIC_CRYPTO_INITIAL);
      59         118 :         packet = quic_packet(sk);
      60         118 :         source = quic_source(sk);
      61         118 :         dest = quic_dest(sk);
      62             : 
      63         118 :         if (!backlog) /* Exit listen state if backlog is zero. */
      64           0 :                 goto free;
      65             : 
      66         118 :         if (!sk_unhashed(sk)) /* Already hashed/listening. */
      67           0 :                 goto out;
      68             : 
      69         118 :         paths = quic_paths(sk);
      70         118 :         a = quic_path_saddr(paths, 0);
      71         118 :         if (!a->v4.sin_port) { /* Auto-bind if not already bound. */
      72           0 :                 err = quic_path_bind(sk, paths, 0);
      73           0 :                 if (err)
      74           0 :                         goto free;
      75           0 :                 quic_set_sk_addr(sk, a, true);
      76             :         }
      77             :         /* Generate and add destination and source connection IDs for sending Initial-level
      78             :          * CLOSE frames to refuse connection attempts in case of verification failure.
      79             :          */
      80         118 :         quic_conn_id_generate(&conn_id);
      81         118 :         err = quic_conn_id_add(dest, &conn_id, 0, NULL);
      82         118 :         if (err)
      83           0 :                 goto free;
      84         118 :         quic_conn_id_generate(&conn_id);
      85         118 :         err = quic_conn_id_add(source, &conn_id, 0, sk);
      86         118 :         if (err)
      87           0 :                 goto free;
      88         118 :         active = quic_conn_id_active(dest);
      89         118 :         paths->serv = 1; /* Mark this as a server. */
      90             : 
      91             :         /* Install initial keys to generate Retry/Stateless Reset tokens. */
      92         118 :         err = quic_crypto_set_cipher(crypto, TLS_CIPHER_AES_GCM_128, CRYPTO_ALG_ASYNC);
      93         118 :         if (err)
      94           0 :                 goto free;
      95         118 :         err = quic_crypto_initial_keys_install(crypto, active, packet->version, 1);
      96         118 :         if (err)
      97           0 :                 goto free;
      98             : 
      99             :         /* Set socket state to LISTENING and add to sock hash table. */
     100         118 :         quic_set_state(sk, QUIC_SS_LISTENING);
     101         118 :         sk->sk_max_ack_backlog = backlog;
     102         118 :         err = sk->sk_prot->hash(sk);
     103         118 :         if (err)
     104           0 :                 goto free;
     105         118 : out:
     106         118 :         release_sock(sk);
     107         118 :         return err;
     108           0 : free:
     109           0 :         quic_set_state(sk, QUIC_SS_CLOSED);
     110           0 :         sk->sk_max_ack_backlog = 0;
     111             : 
     112           0 :         quic_conn_id_set_free(source);
     113           0 :         quic_conn_id_set_free(dest);
     114           0 :         quic_crypto_free(crypto);
     115           0 :         goto out;
     116             : }
     117             : 
     118         173 : static int quic_inet_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
     119             : {
     120         173 :         return quic_get_sk_addr(sock, uaddr, peer);
     121             : }
     122             : 
     123      280637 : static __poll_t quic_inet_poll(struct file *file, struct socket *sock, poll_table *wait)
     124             : {
     125      280637 :         struct sock *sk = sock->sk;
     126      280637 :         struct list_head *head;
     127      280637 :         __poll_t mask;
     128             : 
     129      280637 :         poll_wait(file, sk_sleep(sk), wait);
     130             : 
     131      280636 :         sock_rps_record_flow(sk); /* Record the flow's CPU association for RFS. */
     132             : 
     133             :         /* A listening socket becomes readable when the accept queue is not empty. */
     134      280637 :         if (quic_is_listen(sk))
     135           0 :                 return !list_empty(quic_reqs(sk)) ? (EPOLLIN | EPOLLRDNORM) : 0;
     136             : 
     137      280637 :         mask = 0;
     138      280637 :         if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) /* Error check. */
     139           0 :                 mask |= EPOLLERR | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
     140             : 
     141      280637 :         head = &quic_inq(sk)->recv_list;
     142      280637 :         if (!list_empty(head)) /* Readable check. */
     143      136831 :                 mask |= EPOLLIN | EPOLLRDNORM;
     144             : 
     145      280637 :         if (quic_is_closed(sk)) {
     146             :                 /* A broken connection should report almost everything in order to let
     147             :                  * applications to detect it reliable.
     148             :                  */
     149         324 :                 mask |= EPOLLHUP;
     150         324 :                 mask |= EPOLLERR;
     151         324 :                 mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
     152         324 :                 mask |= EPOLLOUT | EPOLLWRNORM;
     153         324 :                 return mask;
     154             :         }
     155             : 
     156      280313 :         if (sk_stream_wspace(sk) > 0 && quic_outq_wspace(sk, NULL) > 0) { /* Writable check. */
     157      277799 :                 mask |= EPOLLOUT | EPOLLWRNORM;
     158             :         } else {
     159        2514 :                 sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
     160             :                 /* Do writeable check again after the bit is set to avoid a lost I/O siginal,
     161             :                  * similar to sctp_poll().
     162             :                  */
     163        2515 :                 if (sk_stream_wspace(sk) > 0 && quic_outq_wspace(sk, NULL) > 0)
     164           0 :                         mask |= EPOLLOUT | EPOLLWRNORM;
     165             :         }
     166             :         return mask;
     167             : }
     168             : 
     169             : static struct ctl_table quic_table[] = {
     170             :         {
     171             :                 .procname       = "quic_mem",
     172             :                 .data           = &sysctl_quic_mem,
     173             :                 .maxlen         = sizeof(sysctl_quic_mem),
     174             :                 .mode           = 0644,
     175             :                 .proc_handler   = proc_doulongvec_minmax
     176             :         },
     177             :         {
     178             :                 .procname       = "quic_rmem",
     179             :                 .data           = &sysctl_quic_rmem,
     180             :                 .maxlen         = sizeof(sysctl_quic_rmem),
     181             :                 .mode           = 0644,
     182             :                 .proc_handler   = proc_dointvec,
     183             :         },
     184             :         {
     185             :                 .procname       = "quic_wmem",
     186             :                 .data           = &sysctl_quic_wmem,
     187             :                 .maxlen         = sizeof(sysctl_quic_wmem),
     188             :                 .mode           = 0644,
     189             :                 .proc_handler   = proc_dointvec,
     190             :         },
     191             : };
     192             : 
     193    16596091 : struct quic_net *quic_net(struct net *net)
     194             : {
     195    16596091 :         return net_generic(net, quic_net_id);
     196             : }
     197             : 
     198             : #ifdef CONFIG_PROC_FS
     199        1536 : static int quic_seq_show(struct seq_file *seq, void *v)
     200             : {
     201        1536 :         struct net *net = seq_file_net(seq);
     202        1536 :         u32 hash = (u32)(*(loff_t *)v);
     203        1536 :         struct quic_path_group *paths;
     204        1536 :         struct quic_hash_head *head;
     205        1536 :         struct quic_outqueue *outq;
     206        1536 :         struct sock *sk;
     207             : 
     208        1536 :         if (hash >= QUIC_HT_SIZE)
     209             :                 return -ENOMEM;
     210             : 
     211        1536 :         head = quic_sock_hash(hash);
     212        1536 :         spin_lock_bh(&head->s_lock);
     213        3107 :         sk_for_each(sk, &head->head) {
     214          35 :                 if (net != sock_net(sk))
     215           0 :                         continue;
     216             : 
     217          35 :                 paths = quic_paths(sk);
     218          35 :                 quic_seq_dump_addr(seq, quic_path_saddr(paths, 0));
     219          35 :                 quic_seq_dump_addr(seq, quic_path_daddr(paths, 0));
     220          35 :                 quic_seq_dump_addr(seq, quic_path_uaddr(paths, 0));
     221             : 
     222          35 :                 outq = quic_outq(sk);
     223          35 :                 seq_printf(seq, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", sk->sk_state,
     224             :                            outq->window, quic_packet_mss(quic_packet(sk)),
     225          35 :                            outq->inflight, READ_ONCE(sk->sk_wmem_queued),
     226             :                            sk_rmem_alloc_get(sk), sk->sk_sndbuf, sk->sk_rcvbuf);
     227             :         }
     228        1536 :         spin_unlock_bh(&head->s_lock);
     229        1536 :         return 0;
     230             : }
     231             : 
     232          48 : static void *quic_seq_start(struct seq_file *seq, loff_t *pos)
     233             : {
     234          48 :         if (*pos >= QUIC_HT_SIZE)
     235             :                 return NULL;
     236             : 
     237          24 :         if (*pos < 0)
     238           0 :                 *pos = 0;
     239             : 
     240          24 :         if (*pos == 0)
     241          24 :                 seq_printf(seq, "LOCAL_ADDRESS\tREMOTE_ADDRESS\tUDP_ADDRESS\tSTATE\t"
     242             :                                 "WINDOW\tMSS\tIN_FLIGHT\tTX_QUEUE\tRX_QUEUE\tSNDBUF\tRCVBUF\n");
     243             : 
     244             :         return (void *)pos;
     245             : }
     246             : 
     247        1536 : static void *quic_seq_next(struct seq_file *seq, void *v, loff_t *pos)
     248             : {
     249        1536 :         if (++*pos >= QUIC_HT_SIZE)
     250          24 :                 return NULL;
     251             : 
     252             :         return pos;
     253             : }
     254             : 
     255          48 : static void quic_seq_stop(struct seq_file *seq, void *v)
     256             : {
     257          48 : }
     258             : 
     259             : static const struct snmp_mib quic_snmp_list[] = {
     260             :         SNMP_MIB_ITEM("QuicConnCurrentEstabs", QUIC_MIB_CONN_CURRENTESTABS),
     261             :         SNMP_MIB_ITEM("QuicConnPassiveEstabs", QUIC_MIB_CONN_PASSIVEESTABS),
     262             :         SNMP_MIB_ITEM("QuicConnActiveEstabs", QUIC_MIB_CONN_ACTIVEESTABS),
     263             :         SNMP_MIB_ITEM("QuicPktRcvFastpaths", QUIC_MIB_PKT_RCVFASTPATHS),
     264             :         SNMP_MIB_ITEM("QuicPktDecFastpaths", QUIC_MIB_PKT_DECFASTPATHS),
     265             :         SNMP_MIB_ITEM("QuicPktEncFastpaths", QUIC_MIB_PKT_ENCFASTPATHS),
     266             :         SNMP_MIB_ITEM("QuicPktRcvBacklogs", QUIC_MIB_PKT_RCVBACKLOGS),
     267             :         SNMP_MIB_ITEM("QuicPktDecBacklogs", QUIC_MIB_PKT_DECBACKLOGS),
     268             :         SNMP_MIB_ITEM("QuicPktEncBacklogs", QUIC_MIB_PKT_ENCBACKLOGS),
     269             :         SNMP_MIB_ITEM("QuicPktInvHdrDrop", QUIC_MIB_PKT_INVHDRDROP),
     270             :         SNMP_MIB_ITEM("QuicPktInvNumDrop", QUIC_MIB_PKT_INVNUMDROP),
     271             :         SNMP_MIB_ITEM("QuicPktInvFrmDrop", QUIC_MIB_PKT_INVFRMDROP),
     272             :         SNMP_MIB_ITEM("QuicPktRcvDrop", QUIC_MIB_PKT_RCVDROP),
     273             :         SNMP_MIB_ITEM("QuicPktDecDrop", QUIC_MIB_PKT_DECDROP),
     274             :         SNMP_MIB_ITEM("QuicPktEncDrop", QUIC_MIB_PKT_ENCDROP),
     275             :         SNMP_MIB_ITEM("QuicFrmRcvBufDrop", QUIC_MIB_FRM_RCVBUFDROP),
     276             :         SNMP_MIB_ITEM("QuicFrmRetrans", QUIC_MIB_FRM_RETRANS),
     277             :         SNMP_MIB_ITEM("QuicFrmOutCloses", QUIC_MIB_FRM_OUTCLOSES),
     278             :         SNMP_MIB_ITEM("QuicFrmInCloses", QUIC_MIB_FRM_INCLOSES),
     279             :         SNMP_MIB_SENTINEL
     280             : };
     281             : 
     282          22 : static int quic_snmp_seq_show(struct seq_file *seq, void *v)
     283             : {
     284          22 :         unsigned long buff[QUIC_MIB_MAX];
     285          22 :         struct net *net = seq->private;
     286          22 :         u32 idx;
     287             : 
     288          22 :         memset(buff, 0, sizeof(unsigned long) * QUIC_MIB_MAX);
     289             : 
     290       10604 :         snmp_get_cpu_field_batch(buff, quic_snmp_list, quic_net(net)->stat);
     291         440 :         for (idx = 0; quic_snmp_list[idx].name; idx++)
     292         418 :                 seq_printf(seq, "%-32s\t%ld\n", quic_snmp_list[idx].name, buff[idx]);
     293             : 
     294          22 :         return 0;
     295             : }
     296             : 
     297             : static const struct seq_operations quic_seq_ops = {
     298             :         .show           = quic_seq_show,
     299             :         .start          = quic_seq_start,
     300             :         .next           = quic_seq_next,
     301             :         .stop           = quic_seq_stop,
     302             : };
     303             : 
     304         482 : static int quic_net_proc_init(struct net *net)
     305             : {
     306         482 :         quic_net(net)->proc_net = proc_net_mkdir(net, "quic", net->proc_net);
     307         482 :         if (!quic_net(net)->proc_net)
     308             :                 return -ENOMEM;
     309             : 
     310         482 :         if (!proc_create_net_single("snmp", 0444, quic_net(net)->proc_net,
     311             :                                     quic_snmp_seq_show, NULL))
     312           0 :                 goto free;
     313         482 :         if (!proc_create_net("sks", 0444, quic_net(net)->proc_net,
     314             :                              &quic_seq_ops, sizeof(struct seq_net_private)))
     315           0 :                 goto free;
     316             :         return 0;
     317           0 : free:
     318           0 :         remove_proc_subtree("quic", net->proc_net);
     319           0 :         quic_net(net)->proc_net = NULL;
     320           0 :         return -ENOMEM;
     321             : }
     322             : 
     323         477 : static void quic_net_proc_exit(struct net *net)
     324             : {
     325         477 :         remove_proc_subtree("quic", net->proc_net);
     326         477 :         quic_net(net)->proc_net = NULL;
     327         477 : }
     328             : #endif
     329             : 
     330           1 : static void quic_transport_param_init(void)
     331             : {
     332           1 :         struct quic_transport_param *p = &quic_default_param;
     333             : 
     334           1 :         p->max_udp_payload_size = QUIC_MAX_UDP_PAYLOAD;
     335           1 :         p->ack_delay_exponent = QUIC_DEF_ACK_DELAY_EXPONENT;
     336           1 :         p->max_ack_delay = QUIC_DEF_ACK_DELAY;
     337           1 :         p->active_connection_id_limit = QUIC_CONN_ID_DEF;
     338           1 :         p->max_idle_timeout = QUIC_DEF_IDLE_TIMEOUT;
     339           1 :         p->max_data = (u64)QUIC_PATH_MAX_PMTU * 32;
     340           1 :         p->max_stream_data_bidi_local = (u64)QUIC_PATH_MAX_PMTU * 16;
     341           1 :         p->max_stream_data_bidi_remote = (u64)QUIC_PATH_MAX_PMTU * 16;
     342           1 :         p->max_stream_data_uni = (u64)QUIC_PATH_MAX_PMTU * 16;
     343           1 :         p->max_streams_bidi = QUIC_DEF_STREAMS;
     344           1 :         p->max_streams_uni = QUIC_DEF_STREAMS;
     345           1 : }
     346             : 
     347             : static const struct proto_ops quic_proto_ops = {
     348             :         .family            = PF_INET,
     349             :         .owner             = THIS_MODULE,
     350             :         .release           = inet_release,
     351             :         .bind              = inet_bind,
     352             :         .connect           = quic_inet_connect,
     353             :         .socketpair        = sock_no_socketpair,
     354             :         .accept            = inet_accept,
     355             :         .getname           = quic_inet_getname,
     356             :         .poll              = quic_inet_poll,
     357             :         .ioctl             = inet_ioctl,
     358             :         .gettstamp         = sock_gettstamp,
     359             :         .listen            = quic_inet_listen,
     360             :         .shutdown          = inet_shutdown,
     361             :         .setsockopt        = sock_common_setsockopt,
     362             :         .getsockopt        = sock_common_getsockopt,
     363             :         .sendmsg           = inet_sendmsg,
     364             :         .recvmsg           = inet_recvmsg,
     365             :         .mmap              = sock_no_mmap,
     366             : };
     367             : 
     368             : static struct inet_protosw quic_stream_protosw = {
     369             :         .type       = SOCK_STREAM,
     370             :         .protocol   = IPPROTO_QUIC,
     371             :         .prot       = &quic_prot,
     372             :         .ops        = &quic_proto_ops,
     373             : };
     374             : 
     375             : static struct inet_protosw quic_dgram_protosw = {
     376             :         .type       = SOCK_DGRAM,
     377             :         .protocol   = IPPROTO_QUIC,
     378             :         .prot       = &quic_prot,
     379             :         .ops        = &quic_proto_ops,
     380             : };
     381             : 
     382             : static const struct proto_ops quicv6_proto_ops = {
     383             :         .family            = PF_INET6,
     384             :         .owner             = THIS_MODULE,
     385             :         .release           = inet6_release,
     386             :         .bind              = inet6_bind,
     387             :         .connect           = quic_inet_connect,
     388             :         .socketpair        = sock_no_socketpair,
     389             :         .accept            = inet_accept,
     390             :         .getname           = quic_inet_getname,
     391             :         .poll              = quic_inet_poll,
     392             :         .ioctl             = inet6_ioctl,
     393             :         .gettstamp         = sock_gettstamp,
     394             :         .listen            = quic_inet_listen,
     395             :         .shutdown          = inet_shutdown,
     396             :         .setsockopt        = sock_common_setsockopt,
     397             :         .getsockopt        = sock_common_getsockopt,
     398             :         .sendmsg           = inet_sendmsg,
     399             :         .recvmsg           = inet_recvmsg,
     400             :         .mmap              = sock_no_mmap,
     401             : };
     402             : 
     403             : static struct inet_protosw quicv6_stream_protosw = {
     404             :         .type       = SOCK_STREAM,
     405             :         .protocol   = IPPROTO_QUIC,
     406             :         .prot       = &quicv6_prot,
     407             :         .ops        = &quicv6_proto_ops,
     408             : };
     409             : 
     410             : static struct inet_protosw quicv6_dgram_protosw = {
     411             :         .type       = SOCK_DGRAM,
     412             :         .protocol   = IPPROTO_QUIC,
     413             :         .prot       = &quicv6_prot,
     414             :         .ops        = &quicv6_proto_ops,
     415             : };
     416             : 
     417           1 : static int quic_protosw_init(void)
     418             : {
     419           1 :         int err;
     420             : 
     421           1 :         err = proto_register(&quic_prot, 1);
     422           1 :         if (err)
     423             :                 return err;
     424             : 
     425           1 :         err = proto_register(&quicv6_prot, 1);
     426           1 :         if (err) {
     427           0 :                 proto_unregister(&quic_prot);
     428           0 :                 return err;
     429             :         }
     430             : 
     431           1 :         inet_register_protosw(&quic_stream_protosw);
     432           1 :         inet_register_protosw(&quic_dgram_protosw);
     433           1 :         inet6_register_protosw(&quicv6_stream_protosw);
     434           1 :         inet6_register_protosw(&quicv6_dgram_protosw);
     435             : 
     436           1 :         return 0;
     437             : }
     438             : 
     439           0 : static void quic_protosw_exit(void)
     440             : {
     441           0 :         inet_unregister_protosw(&quic_dgram_protosw);
     442           0 :         inet_unregister_protosw(&quic_stream_protosw);
     443           0 :         proto_unregister(&quic_prot);
     444             : 
     445           0 :         inet6_unregister_protosw(&quicv6_dgram_protosw);
     446           0 :         inet6_unregister_protosw(&quicv6_stream_protosw);
     447           0 :         proto_unregister(&quicv6_prot);
     448           0 : }
     449             : 
     450         482 : static int __net_init quic_net_init(struct net *net)
     451             : {
     452         482 :         struct quic_net *qn = quic_net(net);
     453         482 :         int err;
     454             : 
     455         482 :         qn->stat = alloc_percpu(struct quic_mib);
     456         482 :         if (!qn->stat)
     457             :                 return -ENOMEM;
     458             : 
     459         482 :         err = quic_crypto_set_cipher(&qn->crypto, TLS_CIPHER_AES_GCM_128, CRYPTO_ALG_ASYNC);
     460         482 :         if (err) {
     461           0 :                 free_percpu(qn->stat);
     462           0 :                 qn->stat = NULL;
     463           0 :                 return err;
     464             :         }
     465         482 :         spin_lock_init(&qn->lock);
     466             : 
     467             : #ifdef CONFIG_PROC_FS
     468         482 :         err = quic_net_proc_init(net);
     469         482 :         if (err) {
     470           0 :                 quic_crypto_free(&qn->crypto);
     471           0 :                 free_percpu(qn->stat);
     472           0 :                 qn->stat = NULL;
     473             :         }
     474             : #endif
     475             :         return err;
     476             : }
     477             : 
     478         477 : static void __net_exit quic_net_exit(struct net *net)
     479             : {
     480         477 :         struct quic_net *qn = quic_net(net);
     481             : 
     482             : #ifdef CONFIG_PROC_FS
     483         477 :         quic_net_proc_exit(net);
     484             : #endif
     485         477 :         quic_crypto_free(&qn->crypto);
     486         477 :         free_percpu(qn->stat);
     487         477 :         qn->stat = NULL;
     488         477 : }
     489             : 
     490             : static struct pernet_operations quic_net_ops = {
     491             :         .init = quic_net_init,
     492             :         .exit = quic_net_exit,
     493             :         .id   = &quic_net_id,
     494             :         .size = sizeof(struct quic_net),
     495             : };
     496             : 
     497             : #ifdef CONFIG_SYSCTL
     498             : static struct ctl_table_header *quic_sysctl_header;
     499             : 
     500           1 : static void quic_sysctl_register(void)
     501             : {
     502           1 :         quic_sysctl_header = register_net_sysctl(&init_net, "net/quic", quic_table);
     503           1 : }
     504             : 
     505           0 : static void quic_sysctl_unregister(void)
     506             : {
     507           0 :         unregister_net_sysctl_table(quic_sysctl_header);
     508             : }
     509             : #endif
     510             : 
     511           1 : static __init int quic_init(void)
     512             : {
     513           1 :         int max_share, err = -ENOMEM;
     514           1 :         unsigned long limit;
     515             : 
     516             :         /* Set QUIC memory limits based on available system memory, similar to sctp_init(). */
     517           1 :         limit = nr_free_buffer_pages() / 8;
     518           1 :         limit = max(limit, 128UL);
     519           1 :         sysctl_quic_mem[0] = (long)limit / 4 * 3;
     520           1 :         sysctl_quic_mem[1] = (long)limit;
     521           1 :         sysctl_quic_mem[2] = sysctl_quic_mem[0] * 2;
     522             : 
     523           1 :         limit = (sysctl_quic_mem[1]) << (PAGE_SHIFT - 7);
     524           1 :         max_share = min(4UL * 1024 * 1024, limit);
     525             : 
     526           1 :         sysctl_quic_rmem[0] = PAGE_SIZE;
     527           1 :         sysctl_quic_rmem[1] = 1024 * 1024;
     528           1 :         sysctl_quic_rmem[2] = max(sysctl_quic_rmem[1], max_share);
     529             : 
     530           1 :         sysctl_quic_wmem[0] = PAGE_SIZE;
     531           1 :         sysctl_quic_wmem[1] = 16 * 1024;
     532           1 :         sysctl_quic_wmem[2] = max(64 * 1024, max_share);
     533             : 
     534           1 :         quic_transport_param_init();
     535           1 :         quic_crypto_init();
     536             : 
     537           1 :         quic_frame_cachep = kmem_cache_create("quic_frame", sizeof(struct quic_frame),
     538             :                                               0, SLAB_HWCACHE_ALIGN, NULL);
     539           1 :         if (!quic_frame_cachep)
     540           0 :                 goto err;
     541             : 
     542           1 :         err = percpu_counter_init(&quic_sockets_allocated, 0, GFP_KERNEL);
     543           1 :         if (err)
     544           0 :                 goto err_percpu_counter;
     545             : 
     546           1 :         if (quic_hash_tables_init())
     547           0 :                 goto err_hash;
     548             : 
     549           1 :         err = register_pernet_subsys(&quic_net_ops);
     550           1 :         if (err)
     551           0 :                 goto err_def_ops;
     552             : 
     553           1 :         err = quic_path_init(quic_packet_rcv);
     554           1 :         if (err)
     555           0 :                 goto err_path;
     556             : 
     557           1 :         err = quic_protosw_init();
     558           1 :         if (err)
     559           0 :                 goto err_protosw;
     560             : 
     561             : #ifdef CONFIG_SYSCTL
     562           1 :         quic_sysctl_register();
     563             : #endif
     564           1 :         pr_info("quic: init\n");
     565           1 :         return 0;
     566             : 
     567           0 : err_protosw:
     568           0 :         quic_path_destroy();
     569           0 : err_path:
     570           0 :         unregister_pernet_subsys(&quic_net_ops);
     571           0 : err_def_ops:
     572           0 :         quic_hash_tables_destroy();
     573           0 : err_hash:
     574           0 :         percpu_counter_destroy(&quic_sockets_allocated);
     575           0 : err_percpu_counter:
     576           0 :         kmem_cache_destroy(quic_frame_cachep);
     577             : err:
     578             :         return err;
     579             : }
     580             : 
     581           0 : static __exit void quic_exit(void)
     582             : {
     583             : #ifdef CONFIG_SYSCTL
     584           0 :         quic_sysctl_unregister();
     585             : #endif
     586           0 :         quic_protosw_exit();
     587           0 :         quic_path_destroy();
     588           0 :         unregister_pernet_subsys(&quic_net_ops);
     589           0 :         quic_hash_tables_destroy();
     590           0 :         percpu_counter_destroy(&quic_sockets_allocated);
     591           0 :         kmem_cache_destroy(quic_frame_cachep);
     592           0 :         pr_info("quic: exit\n");
     593           0 : }
     594             : 
     595             : module_init(quic_init);
     596             : module_exit(quic_exit);
     597             : 
     598             : MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-261");
     599             : MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-261");
     600             : MODULE_AUTHOR("Xin Long <lucien.xin@gmail.com>");
     601             : MODULE_DESCRIPTION("Support for the QUIC protocol (RFC9000)");
     602             : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14