diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 3ba605f60e4e..581ecf02c6b5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -270,6 +270,7 @@ | |||
270 | #include <linux/slab.h> | 270 | #include <linux/slab.h> |
271 | 271 | ||
272 | #include <net/icmp.h> | 272 | #include <net/icmp.h> |
273 | #include <net/inet_common.h> | ||
273 | #include <net/tcp.h> | 274 | #include <net/tcp.h> |
274 | #include <net/xfrm.h> | 275 | #include <net/xfrm.h> |
275 | #include <net/ip.h> | 276 | #include <net/ip.h> |
@@ -376,6 +377,7 @@ void tcp_init_sock(struct sock *sk) | |||
376 | skb_queue_head_init(&tp->out_of_order_queue); | 377 | skb_queue_head_init(&tp->out_of_order_queue); |
377 | tcp_init_xmit_timers(sk); | 378 | tcp_init_xmit_timers(sk); |
378 | tcp_prequeue_init(tp); | 379 | tcp_prequeue_init(tp); |
380 | INIT_LIST_HEAD(&tp->tsq_node); | ||
379 | 381 | ||
380 | icsk->icsk_rto = TCP_TIMEOUT_INIT; | 382 | icsk->icsk_rto = TCP_TIMEOUT_INIT; |
381 | tp->mdev = TCP_TIMEOUT_INIT; | 383 | tp->mdev = TCP_TIMEOUT_INIT; |
@@ -796,6 +798,10 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, | |||
796 | inet_csk(sk)->icsk_ext_hdr_len - | 798 | inet_csk(sk)->icsk_ext_hdr_len - |
797 | tp->tcp_header_len); | 799 | tp->tcp_header_len); |
798 | 800 | ||
801 | /* TSQ : try to have two TSO segments in flight */ | ||
802 | xmit_size_goal = min_t(u32, xmit_size_goal, | ||
803 | sysctl_tcp_limit_output_bytes >> 1); | ||
804 | |||
799 | xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); | 805 | xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); |
800 | 806 | ||
801 | /* We try hard to avoid divides here */ | 807 | /* We try hard to avoid divides here */ |
@@ -977,26 +983,67 @@ static inline int select_size(const struct sock *sk, bool sg) | |||
977 | return tmp; | 983 | return tmp; |
978 | } | 984 | } |
979 | 985 | ||
986 | void tcp_free_fastopen_req(struct tcp_sock *tp) | ||
987 | { | ||
988 | if (tp->fastopen_req != NULL) { | ||
989 | kfree(tp->fastopen_req); | ||
990 | tp->fastopen_req = NULL; | ||
991 | } | ||
992 | } | ||
993 | |||
994 | static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size) | ||
995 | { | ||
996 | struct tcp_sock *tp = tcp_sk(sk); | ||
997 | int err, flags; | ||
998 | |||
999 | if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE)) | ||
1000 | return -EOPNOTSUPP; | ||
1001 | if (tp->fastopen_req != NULL) | ||
1002 | return -EALREADY; /* Another Fast Open is in progress */ | ||
1003 | |||
1004 | tp->fastopen_req = kzalloc(sizeof(struct tcp_fastopen_request), | ||
1005 | sk->sk_allocation); | ||
1006 | if (unlikely(tp->fastopen_req == NULL)) | ||
1007 | return -ENOBUFS; | ||
1008 | tp->fastopen_req->data = msg; | ||
1009 | |||
1010 | flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; | ||
1011 | err = __inet_stream_connect(sk->sk_socket, msg->msg_name, | ||
1012 | msg->msg_namelen, flags); | ||
1013 | *size = tp->fastopen_req->copied; | ||
1014 | tcp_free_fastopen_req(tp); | ||
1015 | return err; | ||
1016 | } | ||
1017 | |||
980 | int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 1018 | int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
981 | size_t size) | 1019 | size_t size) |
982 | { | 1020 | { |
983 | struct iovec *iov; | 1021 | struct iovec *iov; |
984 | struct tcp_sock *tp = tcp_sk(sk); | 1022 | struct tcp_sock *tp = tcp_sk(sk); |
985 | struct sk_buff *skb; | 1023 | struct sk_buff *skb; |
986 | int iovlen, flags, err, copied; | 1024 | int iovlen, flags, err, copied = 0; |
987 | int mss_now = 0, size_goal; | 1025 | int mss_now = 0, size_goal, copied_syn = 0, offset = 0; |
988 | bool sg; | 1026 | bool sg; |
989 | long timeo; | 1027 | long timeo; |
990 | 1028 | ||
991 | lock_sock(sk); | 1029 | lock_sock(sk); |
992 | 1030 | ||
993 | flags = msg->msg_flags; | 1031 | flags = msg->msg_flags; |
1032 | if (flags & MSG_FASTOPEN) { | ||
1033 | err = tcp_sendmsg_fastopen(sk, msg, &copied_syn); | ||
1034 | if (err == -EINPROGRESS && copied_syn > 0) | ||
1035 | goto out; | ||
1036 | else if (err) | ||
1037 | goto out_err; | ||
1038 | offset = copied_syn; | ||
1039 | } | ||
1040 | |||
994 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 1041 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
995 | 1042 | ||
996 | /* Wait for a connection to finish. */ | 1043 | /* Wait for a connection to finish. */ |
997 | if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) | 1044 | if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) |
998 | if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) | 1045 | if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) |
999 | goto out_err; | 1046 | goto do_error; |
1000 | 1047 | ||
1001 | if (unlikely(tp->repair)) { | 1048 | if (unlikely(tp->repair)) { |
1002 | if (tp->repair_queue == TCP_RECV_QUEUE) { | 1049 | if (tp->repair_queue == TCP_RECV_QUEUE) { |
@@ -1032,6 +1079,15 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1032 | unsigned char __user *from = iov->iov_base; | 1079 | unsigned char __user *from = iov->iov_base; |
1033 | 1080 | ||
1034 | iov++; | 1081 | iov++; |
1082 | if (unlikely(offset > 0)) { /* Skip bytes copied in SYN */ | ||
1083 | if (offset >= seglen) { | ||
1084 | offset -= seglen; | ||
1085 | continue; | ||
1086 | } | ||
1087 | seglen -= offset; | ||
1088 | from += offset; | ||
1089 | offset = 0; | ||
1090 | } | ||
1035 | 1091 | ||
1036 | while (seglen > 0) { | 1092 | while (seglen > 0) { |
1037 | int copy = 0; | 1093 | int copy = 0; |
@@ -1194,7 +1250,7 @@ out: | |||
1194 | if (copied && likely(!tp->repair)) | 1250 | if (copied && likely(!tp->repair)) |
1195 | tcp_push(sk, flags, mss_now, tp->nonagle); | 1251 | tcp_push(sk, flags, mss_now, tp->nonagle); |
1196 | release_sock(sk); | 1252 | release_sock(sk); |
1197 | return copied; | 1253 | return copied + copied_syn; |
1198 | 1254 | ||
1199 | do_fault: | 1255 | do_fault: |
1200 | if (!skb->len) { | 1256 | if (!skb->len) { |
@@ -1207,7 +1263,7 @@ do_fault: | |||
1207 | } | 1263 | } |
1208 | 1264 | ||
1209 | do_error: | 1265 | do_error: |
1210 | if (copied) | 1266 | if (copied + copied_syn) |
1211 | goto out; | 1267 | goto out; |
1212 | out_err: | 1268 | out_err: |
1213 | err = sk_stream_error(sk, flags, err); | 1269 | err = sk_stream_error(sk, flags, err); |
@@ -3310,8 +3366,7 @@ EXPORT_SYMBOL(tcp_md5_hash_key); | |||
3310 | 3366 | ||
3311 | #endif | 3367 | #endif |
3312 | 3368 | ||
3313 | /** | 3369 | /* Each Responder maintains up to two secret values concurrently for |
3314 | * Each Responder maintains up to two secret values concurrently for | ||
3315 | * efficient secret rollover. Each secret value has 4 states: | 3370 | * efficient secret rollover. Each secret value has 4 states: |
3316 | * | 3371 | * |
3317 | * Generating. (tcp_secret_generating != tcp_secret_primary) | 3372 | * Generating. (tcp_secret_generating != tcp_secret_primary) |
@@ -3563,6 +3618,8 @@ void __init tcp_init(void) | |||
3563 | pr_info("Hash tables configured (established %u bind %u)\n", | 3618 | pr_info("Hash tables configured (established %u bind %u)\n", |
3564 | tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size); | 3619 | tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size); |
3565 | 3620 | ||
3621 | tcp_metrics_init(); | ||
3622 | |||
3566 | tcp_register_congestion_control(&tcp_reno); | 3623 | tcp_register_congestion_control(&tcp_reno); |
3567 | 3624 | ||
3568 | memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets)); | 3625 | memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets)); |
@@ -3573,4 +3630,5 @@ void __init tcp_init(void) | |||
3573 | tcp_secret_primary = &tcp_secret_one; | 3630 | tcp_secret_primary = &tcp_secret_one; |
3574 | tcp_secret_retiring = &tcp_secret_two; | 3631 | tcp_secret_retiring = &tcp_secret_two; |
3575 | tcp_secret_secondary = &tcp_secret_two; | 3632 | tcp_secret_secondary = &tcp_secret_two; |
3633 | tcp_tasklet_init(); | ||
3576 | } | 3634 | } |