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");
|