Merge tag 'acpi-5.18-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[platform/kernel/linux-starfive.git] / net / ipv4 / tcp.c
index 28ff2a8..cf18fbc 100644 (file)
@@ -688,7 +688,8 @@ static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
        return skb->len < size_goal &&
               sock_net(sk)->ipv4.sysctl_tcp_autocorking &&
               !tcp_rtx_queue_empty(sk) &&
-              refcount_read(&sk->sk_wmem_alloc) > skb->truesize;
+              refcount_read(&sk->sk_wmem_alloc) > skb->truesize &&
+              tcp_skb_can_collapse_to(skb);
 }
 
 void tcp_push(struct sock *sk, int flags, int mss_now,
@@ -894,8 +895,7 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now,
                return mss_now;
 
        /* 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);
+       new_size_goal = tcp_bound_to_half_wnd(tp, sk->sk_gso_max_size);
 
        /* We try hard to avoid divides here */
        size_goal = tp->gso_segs * mss_now;
@@ -4434,6 +4434,73 @@ int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, const struct tcp_md5sig_key *ke
 }
 EXPORT_SYMBOL(tcp_md5_hash_key);
 
+/* Called with rcu_read_lock() */
+enum skb_drop_reason
+tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,
+                    const void *saddr, const void *daddr,
+                    int family, int dif, int sdif)
+{
+       /*
+        * This gets called for each TCP segment that arrives
+        * so we want to be efficient.
+        * We have 3 drop cases:
+        * o No MD5 hash and one expected.
+        * o MD5 hash and we're not expecting one.
+        * o MD5 hash and its wrong.
+        */
+       const __u8 *hash_location = NULL;
+       struct tcp_md5sig_key *hash_expected;
+       const struct tcphdr *th = tcp_hdr(skb);
+       struct tcp_sock *tp = tcp_sk(sk);
+       int genhash, l3index;
+       u8 newhash[16];
+
+       /* sdif set, means packet ingressed via a device
+        * in an L3 domain and dif is set to the l3mdev
+        */
+       l3index = sdif ? dif : 0;
+
+       hash_expected = tcp_md5_do_lookup(sk, l3index, saddr, family);
+       hash_location = tcp_parse_md5sig_option(th);
+
+       /* We've parsed the options - do we have a hash? */
+       if (!hash_expected && !hash_location)
+               return SKB_NOT_DROPPED_YET;
+
+       if (hash_expected && !hash_location) {
+               NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
+               return SKB_DROP_REASON_TCP_MD5NOTFOUND;
+       }
+
+       if (!hash_expected && hash_location) {
+               NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
+               return SKB_DROP_REASON_TCP_MD5UNEXPECTED;
+       }
+
+       /* check the signature */
+       genhash = tp->af_specific->calc_md5_hash(newhash, hash_expected,
+                                                NULL, skb);
+
+       if (genhash || memcmp(hash_location, newhash, 16) != 0) {
+               NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
+               if (family == AF_INET) {
+                       net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s L3 index %d\n",
+                                       saddr, ntohs(th->source),
+                                       daddr, ntohs(th->dest),
+                                       genhash ? " tcp_v4_calc_md5_hash failed"
+                                       : "", l3index);
+               } else {
+                       net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u L3 index %d\n",
+                                       genhash ? "failed" : "mismatch",
+                                       saddr, ntohs(th->source),
+                                       daddr, ntohs(th->dest), l3index);
+               }
+               return SKB_DROP_REASON_TCP_MD5FAILURE;
+       }
+       return SKB_NOT_DROPPED_YET;
+}
+EXPORT_SYMBOL(tcp_inbound_md5_hash);
+
 #endif
 
 void tcp_done(struct sock *sk)