• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Based on net/ipv4/inet_connection_sock.c
4  * Authors:	See the TCP sources
5  *
6  * NewIP INET
7  * An implementation of the TCP/IP protocol suite for the LINUX
8  * operating system. NewIP INET is implemented using the  BSD Socket
9  * interface as the means of communication with the user level.
10  *
11  * Support for NewIP INET connection oriented protocols.
12  */
13 #define pr_fmt(fmt) KBUILD_MODNAME ": [%s:%d] " fmt, __func__, __LINE__
14 
15 #include <linux/module.h>
16 #include <linux/nip.h>
17 #include <linux/jhash.h>
18 
19 #include <net/tcp.h>
20 #include <net/nip_addrconf.h>
21 #include <net/inet_connection_sock.h>
22 #include <net/inet_hashtables.h>
23 #include <net/nip_route.h>
24 #include <net/sock.h>
25 #include <net/ninet_connection_sock.h>
26 #include <net/tcp_nip.h>
27 #include "tcp_nip_parameter.h"
28 
29 /* Function
30  *	Timeout handler for request processing, used to retransmit SYN+ACK
31  * Parameter
32  *	t: Request control block
33  */
ninet_reqsk_timer_handler(struct timer_list * t)34 static void ninet_reqsk_timer_handler(struct timer_list *t)
35 {
36 	struct request_sock *req = from_timer(req, t, rsk_timer);
37 	struct sock *sk_listener = req->rsk_listener;
38 	struct net *net = sock_net(sk_listener);
39 	struct inet_connection_sock *icsk = inet_csk(sk_listener);
40 	struct request_sock_queue *queue = &icsk->icsk_accept_queue;
41 	int max_retries, thresh;
42 
43 	/* Defines the maximum number of retransmissions. Thresh defaults to 5 */
44 	max_retries = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_synack_retries;
45 	thresh = max_retries;
46 
47 	/* Check timeout times. SYN+ACK retransmission times +1 */
48 	if (req->num_timeout <= thresh) {
49 		unsigned long timeo;
50 
51 		req->rsk_ops->rtx_syn_ack(sk_listener, req);
52 		req->num_retrans++;
53 		/* If the number of times out is still 0, the number is increased by 1
54 		 * to determine whether it is the first time out
55 		 */
56 		if (req->num_timeout++ == 0)
57 			atomic_dec(&queue->young);
58 		timeo = min(TCP_TIMEOUT_INIT, TCP_RTO_MAX);
59 		mod_timer(&req->rsk_timer, jiffies + timeo);
60 		return;
61 	}
62 
63 	inet_csk_reqsk_queue_drop_and_put(sk_listener, req);
64 }
65 
66 /* Function
67  *	Add request_SOCK to the connection queue and ehash table,
68  *	and set the SYNACK timeout retransmission timer
69  * Parameter
70  *	sk: Transmission control block
71  *	req: Connection request block
72  *	timeout: The initial timeout period
73  */
ninet_csk_reqsk_queue_hash_add(struct sock * sk,struct request_sock * req,unsigned long timeout)74 void ninet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
75 				    unsigned long timeout)
76 {
77 	req->num_retrans = 0;
78 	req->num_timeout = 0;
79 	req->sk = NULL;
80 
81 	timer_setup(&req->rsk_timer, ninet_reqsk_timer_handler,
82 		    TIMER_PINNED);
83 	mod_timer(&req->rsk_timer, jiffies + timeout);
84 
85 	inet_ehash_insert(req_to_sk(req), NULL, NULL);
86 
87 	smp_wmb(); /* memory barrier */
88 	refcount_set(&req->rsk_refcnt, TCP_NUM_2 + 1);
89 
90 	inet_csk_reqsk_queue_added(sk);
91 }
92 
93