diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 76b148bcb0dc..fafbec8b073e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -661,6 +661,47 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) | |||
661 | return NULL; | 661 | return NULL; |
662 | } | 662 | } |
663 | 663 | ||
664 | static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, | ||
665 | int large_allowed) | ||
666 | { | ||
667 | struct tcp_sock *tp = tcp_sk(sk); | ||
668 | u32 xmit_size_goal, old_size_goal; | ||
669 | |||
670 | xmit_size_goal = mss_now; | ||
671 | |||
672 | if (large_allowed && sk_can_gso(sk)) { | ||
673 | xmit_size_goal = ((sk->sk_gso_max_size - 1) - | ||
674 | inet_csk(sk)->icsk_af_ops->net_header_len - | ||
675 | inet_csk(sk)->icsk_ext_hdr_len - | ||
676 | tp->tcp_header_len); | ||
677 | |||
678 | xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); | ||
679 | |||
680 | /* We try hard to avoid divides here */ | ||
681 | old_size_goal = tp->xmit_size_goal_segs * mss_now; | ||
682 | |||
683 | if (likely(old_size_goal <= xmit_size_goal && | ||
684 | old_size_goal + mss_now > xmit_size_goal)) { | ||
685 | xmit_size_goal = old_size_goal; | ||
686 | } else { | ||
687 | tp->xmit_size_goal_segs = xmit_size_goal / mss_now; | ||
688 | xmit_size_goal = tp->xmit_size_goal_segs * mss_now; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | return max(xmit_size_goal, mss_now); | ||
693 | } | ||
694 | |||
695 | static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) | ||
696 | { | ||
697 | int mss_now; | ||
698 | |||
699 | mss_now = tcp_current_mss(sk); | ||
700 | *size_goal = tcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB)); | ||
701 | |||
702 | return mss_now; | ||
703 | } | ||
704 | |||
664 | static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, | 705 | static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, |
665 | size_t psize, int flags) | 706 | size_t psize, int flags) |
666 | { | 707 | { |
@@ -677,13 +718,12 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse | |||
677 | 718 | ||
678 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 719 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); |
679 | 720 | ||
680 | mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); | 721 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
681 | size_goal = tp->xmit_size_goal; | ||
682 | copied = 0; | 722 | copied = 0; |
683 | 723 | ||
684 | err = -EPIPE; | 724 | err = -EPIPE; |
685 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 725 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
686 | goto do_error; | 726 | goto out_err; |
687 | 727 | ||
688 | while (psize > 0) { | 728 | while (psize > 0) { |
689 | struct sk_buff *skb = tcp_write_queue_tail(sk); | 729 | struct sk_buff *skb = tcp_write_queue_tail(sk); |
@@ -761,8 +801,7 @@ wait_for_memory: | |||
761 | if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) | 801 | if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) |
762 | goto do_error; | 802 | goto do_error; |
763 | 803 | ||
764 | mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); | 804 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
765 | size_goal = tp->xmit_size_goal; | ||
766 | } | 805 | } |
767 | 806 | ||
768 | out: | 807 | out: |
@@ -844,8 +883,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
844 | /* This should be in poll */ | 883 | /* This should be in poll */ |
845 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 884 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); |
846 | 885 | ||
847 | mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); | 886 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
848 | size_goal = tp->xmit_size_goal; | ||
849 | 887 | ||
850 | /* Ok commence sending. */ | 888 | /* Ok commence sending. */ |
851 | iovlen = msg->msg_iovlen; | 889 | iovlen = msg->msg_iovlen; |
@@ -854,7 +892,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
854 | 892 | ||
855 | err = -EPIPE; | 893 | err = -EPIPE; |
856 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 894 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
857 | goto do_error; | 895 | goto out_err; |
858 | 896 | ||
859 | while (--iovlen >= 0) { | 897 | while (--iovlen >= 0) { |
860 | int seglen = iov->iov_len; | 898 | int seglen = iov->iov_len; |
@@ -1007,8 +1045,7 @@ wait_for_memory: | |||
1007 | if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) | 1045 | if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) |
1008 | goto do_error; | 1046 | goto do_error; |
1009 | 1047 | ||
1010 | mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); | 1048 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
1011 | size_goal = tp->xmit_size_goal; | ||
1012 | } | 1049 | } |
1013 | } | 1050 | } |
1014 | 1051 | ||
@@ -1044,9 +1081,7 @@ out_err: | |||
1044 | * this, no blocking and very strange errors 8) | 1081 | * this, no blocking and very strange errors 8) |
1045 | */ | 1082 | */ |
1046 | 1083 | ||
1047 | static int tcp_recv_urg(struct sock *sk, long timeo, | 1084 | static int tcp_recv_urg(struct sock *sk, struct msghdr *msg, int len, int flags) |
1048 | struct msghdr *msg, int len, int flags, | ||
1049 | int *addr_len) | ||
1050 | { | 1085 | { |
1051 | struct tcp_sock *tp = tcp_sk(sk); | 1086 | struct tcp_sock *tp = tcp_sk(sk); |
1052 | 1087 | ||
@@ -1661,7 +1696,7 @@ out: | |||
1661 | return err; | 1696 | return err; |
1662 | 1697 | ||
1663 | recv_urg: | 1698 | recv_urg: |
1664 | err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len); | 1699 | err = tcp_recv_urg(sk, msg, len, flags); |
1665 | goto out; | 1700 | goto out; |
1666 | } | 1701 | } |
1667 | 1702 | ||
@@ -2478,23 +2513,23 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2478 | struct tcphdr *th2; | 2513 | struct tcphdr *th2; |
2479 | unsigned int thlen; | 2514 | unsigned int thlen; |
2480 | unsigned int flags; | 2515 | unsigned int flags; |
2481 | unsigned int total; | ||
2482 | unsigned int mss = 1; | 2516 | unsigned int mss = 1; |
2483 | int flush = 1; | 2517 | int flush = 1; |
2518 | int i; | ||
2484 | 2519 | ||
2485 | if (!pskb_may_pull(skb, sizeof(*th))) | 2520 | th = skb_gro_header(skb, sizeof(*th)); |
2521 | if (unlikely(!th)) | ||
2486 | goto out; | 2522 | goto out; |
2487 | 2523 | ||
2488 | th = tcp_hdr(skb); | ||
2489 | thlen = th->doff * 4; | 2524 | thlen = th->doff * 4; |
2490 | if (thlen < sizeof(*th)) | 2525 | if (thlen < sizeof(*th)) |
2491 | goto out; | 2526 | goto out; |
2492 | 2527 | ||
2493 | if (!pskb_may_pull(skb, thlen)) | 2528 | th = skb_gro_header(skb, thlen); |
2529 | if (unlikely(!th)) | ||
2494 | goto out; | 2530 | goto out; |
2495 | 2531 | ||
2496 | th = tcp_hdr(skb); | 2532 | skb_gro_pull(skb, thlen); |
2497 | __skb_pull(skb, thlen); | ||
2498 | 2533 | ||
2499 | flags = tcp_flag_word(th); | 2534 | flags = tcp_flag_word(th); |
2500 | 2535 | ||
@@ -2504,7 +2539,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2504 | 2539 | ||
2505 | th2 = tcp_hdr(p); | 2540 | th2 = tcp_hdr(p); |
2506 | 2541 | ||
2507 | if (th->source != th2->source || th->dest != th2->dest) { | 2542 | if ((th->source ^ th2->source) | (th->dest ^ th2->dest)) { |
2508 | NAPI_GRO_CB(p)->same_flow = 0; | 2543 | NAPI_GRO_CB(p)->same_flow = 0; |
2509 | continue; | 2544 | continue; |
2510 | } | 2545 | } |
@@ -2519,14 +2554,15 @@ found: | |||
2519 | flush |= flags & TCP_FLAG_CWR; | 2554 | flush |= flags & TCP_FLAG_CWR; |
2520 | flush |= (flags ^ tcp_flag_word(th2)) & | 2555 | flush |= (flags ^ tcp_flag_word(th2)) & |
2521 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); | 2556 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); |
2522 | flush |= th->ack_seq != th2->ack_seq || th->window != th2->window; | 2557 | flush |= (th->ack_seq ^ th2->ack_seq) | (th->window ^ th2->window); |
2523 | flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th)); | 2558 | for (i = sizeof(*th); !flush && i < thlen; i += 4) |
2559 | flush |= *(u32 *)((u8 *)th + i) ^ | ||
2560 | *(u32 *)((u8 *)th2 + i); | ||
2524 | 2561 | ||
2525 | total = p->len; | ||
2526 | mss = skb_shinfo(p)->gso_size; | 2562 | mss = skb_shinfo(p)->gso_size; |
2527 | 2563 | ||
2528 | flush |= skb->len > mss || skb->len <= 0; | 2564 | flush |= (skb_gro_len(skb) > mss) | !skb_gro_len(skb); |
2529 | flush |= ntohl(th2->seq) + total != ntohl(th->seq); | 2565 | flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); |
2530 | 2566 | ||
2531 | if (flush || skb_gro_receive(head, skb)) { | 2567 | if (flush || skb_gro_receive(head, skb)) { |
2532 | mss = 1; | 2568 | mss = 1; |
@@ -2538,7 +2574,7 @@ found: | |||
2538 | tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); | 2574 | tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); |
2539 | 2575 | ||
2540 | out_check_final: | 2576 | out_check_final: |
2541 | flush = skb->len < mss; | 2577 | flush = skb_gro_len(skb) < mss; |
2542 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | | 2578 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | |
2543 | TCP_FLAG_SYN | TCP_FLAG_FIN); | 2579 | TCP_FLAG_SYN | TCP_FLAG_FIN); |
2544 | 2580 | ||