aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c43eb1a831d7..d9735b76d073 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -533,6 +533,12 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
533 533
534 if (tp->urg_data & TCP_URG_VALID) 534 if (tp->urg_data & TCP_URG_VALID)
535 mask |= POLLPRI; 535 mask |= POLLPRI;
536 } else if (sk->sk_state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
537 /* Active TCP fastopen socket with defer_connect
538 * Return POLLOUT so application can call write()
539 * in order for kernel to generate SYN+data
540 */
541 mask |= POLLOUT | POLLWRNORM;
536 } 542 }
537 /* This barrier is coupled with smp_wmb() in tcp_reset() */ 543 /* This barrier is coupled with smp_wmb() in tcp_reset() */
538 smp_rmb(); 544 smp_rmb();
@@ -1071,6 +1077,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
1071 int *copied, size_t size) 1077 int *copied, size_t size)
1072{ 1078{
1073 struct tcp_sock *tp = tcp_sk(sk); 1079 struct tcp_sock *tp = tcp_sk(sk);
1080 struct inet_sock *inet = inet_sk(sk);
1074 int err, flags; 1081 int err, flags;
1075 1082
1076 if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE)) 1083 if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE))
@@ -1085,9 +1092,19 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
1085 tp->fastopen_req->data = msg; 1092 tp->fastopen_req->data = msg;
1086 tp->fastopen_req->size = size; 1093 tp->fastopen_req->size = size;
1087 1094
1095 if (inet->defer_connect) {
1096 err = tcp_connect(sk);
1097 /* Same failure procedure as in tcp_v4/6_connect */
1098 if (err) {
1099 tcp_set_state(sk, TCP_CLOSE);
1100 inet->inet_dport = 0;
1101 sk->sk_route_caps = 0;
1102 }
1103 }
1088 flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; 1104 flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
1089 err = __inet_stream_connect(sk->sk_socket, msg->msg_name, 1105 err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
1090 msg->msg_namelen, flags); 1106 msg->msg_namelen, flags);
1107 inet->defer_connect = 0;
1091 *copied = tp->fastopen_req->copied; 1108 *copied = tp->fastopen_req->copied;
1092 tcp_free_fastopen_req(tp); 1109 tcp_free_fastopen_req(tp);
1093 return err; 1110 return err;
@@ -1107,7 +1124,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
1107 lock_sock(sk); 1124 lock_sock(sk);
1108 1125
1109 flags = msg->msg_flags; 1126 flags = msg->msg_flags;
1110 if (flags & MSG_FASTOPEN) { 1127 if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect)) {
1111 err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); 1128 err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
1112 if (err == -EINPROGRESS && copied_syn > 0) 1129 if (err == -EINPROGRESS && copied_syn > 0)
1113 goto out; 1130 goto out;
@@ -2656,6 +2673,18 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
2656 err = -EINVAL; 2673 err = -EINVAL;
2657 } 2674 }
2658 break; 2675 break;
2676 case TCP_FASTOPEN_CONNECT:
2677 if (val > 1 || val < 0) {
2678 err = -EINVAL;
2679 } else if (sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) {
2680 if (sk->sk_state == TCP_CLOSE)
2681 tp->fastopen_connect = val;
2682 else
2683 err = -EINVAL;
2684 } else {
2685 err = -EOPNOTSUPP;
2686 }
2687 break;
2659 case TCP_TIMESTAMP: 2688 case TCP_TIMESTAMP:
2660 if (!tp->repair) 2689 if (!tp->repair)
2661 err = -EPERM; 2690 err = -EPERM;
@@ -3016,6 +3045,10 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
3016 val = icsk->icsk_accept_queue.fastopenq.max_qlen; 3045 val = icsk->icsk_accept_queue.fastopenq.max_qlen;
3017 break; 3046 break;
3018 3047
3048 case TCP_FASTOPEN_CONNECT:
3049 val = tp->fastopen_connect;
3050 break;
3051
3019 case TCP_TIMESTAMP: 3052 case TCP_TIMESTAMP:
3020 val = tcp_time_stamp + tp->tsoffset; 3053 val = tcp_time_stamp + tp->tsoffset;
3021 break; 3054 break;