--- zzzz-none-000/linux-3.10.107/net/ipv4/tcp.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/net/ipv4/tcp.c 2021-11-10 11:53:56.000000000 +0000 @@ -280,6 +280,10 @@ #include #include +#if defined(CONFIG_AVM_SCATTER_GATHER) +unsigned int avm_scatter_gather_optimization = 1; +module_param(avm_scatter_gather_optimization, uint, S_IRUSR | S_IWUSR); +#endif int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; int sysctl_tcp_min_tso_segs __read_mostly = 2; @@ -785,51 +789,32 @@ return NULL; } +/* Aus Commit 605ad7f184b60cfaacbc038aa6c55ee68dee3c89 uebernommen. + * Dadurch keine dauerhaften Geschwindigkeitseinbrueche auf 10MB/s mehr. + */ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, int large_allowed) { struct tcp_sock *tp = tcp_sk(sk); - u32 xmit_size_goal, old_size_goal; - - xmit_size_goal = mss_now; - - if (large_allowed && sk_can_gso(sk)) { - u32 gso_size, hlen; - - /* Maybe we should/could use sk->sk_prot->max_header here ? */ - hlen = inet_csk(sk)->icsk_af_ops->net_header_len + - inet_csk(sk)->icsk_ext_hdr_len + - tp->tcp_header_len; - - /* Goal is to send at least one packet per ms, - * not one big TSO packet every 100 ms. - * This preserves ACK clocking and is consistent - * with tcp_tso_should_defer() heuristic. - */ - gso_size = sk->sk_pacing_rate / (2 * MSEC_PER_SEC); - gso_size = max_t(u32, gso_size, - sysctl_tcp_min_tso_segs * mss_now); + u32 new_size_goal, size_goal; - xmit_size_goal = min_t(u32, gso_size, - sk->sk_gso_max_size - 1 - hlen); + if (!large_allowed || !sk_can_gso(sk)) + return mss_now; - xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); + /* Note : tcp_tso_autosize() will eventually split this later */ + new_size_goal = sk->sk_gso_max_size - 1 - MAX_TCP_HEADER; + new_size_goal = tcp_bound_to_half_wnd(tp, new_size_goal); - /* We try hard to avoid divides here */ - old_size_goal = tp->xmit_size_goal_segs * mss_now; - - if (likely(old_size_goal <= xmit_size_goal && - old_size_goal + mss_now > xmit_size_goal)) { - xmit_size_goal = old_size_goal; - } else { - tp->xmit_size_goal_segs = - min_t(u16, xmit_size_goal / mss_now, - sk->sk_gso_max_segs); - xmit_size_goal = tp->xmit_size_goal_segs * mss_now; - } + /* We try hard to avoid divides here */ + size_goal = tp->gso_segs * mss_now; + if (unlikely(new_size_goal < size_goal || + new_size_goal >= size_goal + mss_now)) { + tp->gso_segs = min_t(u16, new_size_goal / mss_now, + sk->sk_gso_max_segs); + size_goal = tp->gso_segs * mss_now; } - return max(xmit_size_goal, mss_now); + return max(size_goal, mss_now); } static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) @@ -851,6 +836,11 @@ ssize_t copied; long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); +#if defined(CONFIG_AVM_SCATTER_GATHER) + int send_entire_page = (size == PAGE_SIZE ); + int socket_is_corked = (tp->nonagle & TCP_NAGLE_CORK); +#endif + /* Wait for a connection to finish. One exception is TCP Fast Open * (passive side) where data is allowed to be sent before a connection * is fully established. @@ -906,7 +896,16 @@ get_page(page); skb_fill_page_desc(skb, i, page, offset, copy); } - skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + /* Das folgende Flag sorgt dafür dass alle fragmentierten SKBs vor dem Berechnen + * der Pruefsumme kopiert werden. Dieses Feature wurde in Kernel-Commit + * cef401de7be8c4e und c9af6db4c11ccc6c3e7f19bbc15d54023956f97c hinzugefuegt. + * Begruendung dafuer ist, dass die Daten theoretisch zwischen Berechnen der + * Pruefsumme und dem Absenden vom User veraendert werden koennen, was fuer + * ungueltige Pakete sorgt. + * Dies verlangsamt aber auch die Uebertragungsgeschwindigkeit um etwa 2,5MB/s + * und wurde deshalb deaktiviert. + */ + //skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; skb->len += copy; skb->data_len += copy; @@ -948,8 +947,23 @@ } out: - if (copied && !(flags & MSG_SENDPAGE_NOTLAST)) +#if defined(CONFIG_AVM_SCATTER_GATHER) + if ((copied && !(flags & MSG_SENDPAGE_NOTLAST) && !avm_scatter_gather_optimization) || + (copied && !send_entire_page) || + (copied && !socket_is_corked) ){ + /* + * CBU@AVM: + * This is a performance optimization for small instruction cache CPUs + * It seems to be save to skip tcp_push here, as __tcp_push_pending_frames + * is also called by: + * (1) tcp_rcv_established + * (2) tcp_fin handler + */ +#else + if (copied && !(flags & MSG_SENDPAGE_NOTLAST)){ +#endif tcp_push(sk, flags, mss_now, tp->nonagle); + } return copied; do_error: @@ -3398,6 +3412,7 @@ int max_rshare, max_wshare, cnt; unsigned int i; + BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE); BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); percpu_counter_init(&tcp_sockets_allocated, 0);