aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_fastopen.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_fastopen.c')
-rw-r--r--net/ipv4/tcp_fastopen.c20
1 files changed, 8 insertions, 12 deletions
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index ea82fd492c1b..e3d87aca6be8 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -141,7 +141,7 @@ static bool tcp_fastopen_create_child(struct sock *sk,
141 req->sk = NULL; 141 req->sk = NULL;
142 142
143 child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); 143 child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL);
144 if (child == NULL) 144 if (!child)
145 return false; 145 return false;
146 146
147 spin_lock(&queue->fastopenq->lock); 147 spin_lock(&queue->fastopenq->lock);
@@ -155,12 +155,7 @@ static bool tcp_fastopen_create_child(struct sock *sk,
155 tp = tcp_sk(child); 155 tp = tcp_sk(child);
156 156
157 tp->fastopen_rsk = req; 157 tp->fastopen_rsk = req;
158 /* Do a hold on the listner sk so that if the listener is being 158 tcp_rsk(req)->tfo_listener = true;
159 * closed, the child that has been accepted can live on and still
160 * access listen_lock.
161 */
162 sock_hold(sk);
163 tcp_rsk(req)->listener = sk;
164 159
165 /* RFC1323: The window in SYN & SYN/ACK segments is never 160 /* RFC1323: The window in SYN & SYN/ACK segments is never
166 * scaled. So correct it appropriately. 161 * scaled. So correct it appropriately.
@@ -174,6 +169,7 @@ static bool tcp_fastopen_create_child(struct sock *sk,
174 inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS, 169 inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
175 TCP_TIMEOUT_INIT, TCP_RTO_MAX); 170 TCP_TIMEOUT_INIT, TCP_RTO_MAX);
176 171
172 atomic_set(&req->rsk_refcnt, 1);
177 /* Add the child socket directly into the accept queue */ 173 /* Add the child socket directly into the accept queue */
178 inet_csk_reqsk_queue_add(sk, req, child); 174 inet_csk_reqsk_queue_add(sk, req, child);
179 175
@@ -218,10 +214,9 @@ static bool tcp_fastopen_create_child(struct sock *sk,
218 sk->sk_data_ready(sk); 214 sk->sk_data_ready(sk);
219 bh_unlock_sock(child); 215 bh_unlock_sock(child);
220 sock_put(child); 216 sock_put(child);
221 WARN_ON(req->sk == NULL); 217 WARN_ON(!req->sk);
222 return true; 218 return true;
223} 219}
224EXPORT_SYMBOL(tcp_fastopen_create_child);
225 220
226static bool tcp_fastopen_queue_check(struct sock *sk) 221static bool tcp_fastopen_queue_check(struct sock *sk)
227{ 222{
@@ -238,14 +233,14 @@ static bool tcp_fastopen_queue_check(struct sock *sk)
238 * temporarily vs a server not supporting Fast Open at all. 233 * temporarily vs a server not supporting Fast Open at all.
239 */ 234 */
240 fastopenq = inet_csk(sk)->icsk_accept_queue.fastopenq; 235 fastopenq = inet_csk(sk)->icsk_accept_queue.fastopenq;
241 if (fastopenq == NULL || fastopenq->max_qlen == 0) 236 if (!fastopenq || fastopenq->max_qlen == 0)
242 return false; 237 return false;
243 238
244 if (fastopenq->qlen >= fastopenq->max_qlen) { 239 if (fastopenq->qlen >= fastopenq->max_qlen) {
245 struct request_sock *req1; 240 struct request_sock *req1;
246 spin_lock(&fastopenq->lock); 241 spin_lock(&fastopenq->lock);
247 req1 = fastopenq->rskq_rst_head; 242 req1 = fastopenq->rskq_rst_head;
248 if ((req1 == NULL) || time_after(req1->expires, jiffies)) { 243 if (!req1 || time_after(req1->rsk_timer.expires, jiffies)) {
249 spin_unlock(&fastopenq->lock); 244 spin_unlock(&fastopenq->lock);
250 NET_INC_STATS_BH(sock_net(sk), 245 NET_INC_STATS_BH(sock_net(sk),
251 LINUX_MIB_TCPFASTOPENLISTENOVERFLOW); 246 LINUX_MIB_TCPFASTOPENLISTENOVERFLOW);
@@ -254,7 +249,7 @@ static bool tcp_fastopen_queue_check(struct sock *sk)
254 fastopenq->rskq_rst_head = req1->dl_next; 249 fastopenq->rskq_rst_head = req1->dl_next;
255 fastopenq->qlen--; 250 fastopenq->qlen--;
256 spin_unlock(&fastopenq->lock); 251 spin_unlock(&fastopenq->lock);
257 reqsk_free(req1); 252 reqsk_put(req1);
258 } 253 }
259 return true; 254 return true;
260} 255}
@@ -308,6 +303,7 @@ fastopen:
308 } else if (foc->len > 0) /* Client presents an invalid cookie */ 303 } else if (foc->len > 0) /* Client presents an invalid cookie */
309 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL); 304 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
310 305
306 valid_foc.exp = foc->exp;
311 *foc = valid_foc; 307 *foc = valid_foc;
312 return false; 308 return false;
313} 309}