diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 35 |
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; |