]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
tcp: Allow full IP tos/IPv6 tclass to be reflected in L3 header
authorAlexander Duyck <alexanderduyck@fb.com>
Thu, 19 Nov 2020 21:23:51 +0000 (13:23 -0800)
committerJakub Kicinski <kuba@kernel.org>
Sat, 21 Nov 2020 02:09:47 +0000 (18:09 -0800)
An issue was recently found where DCTCP SYN/ACK packets did not have the
ECT bit set in the L3 header. A bit of code review found that the recent
change referenced below had gone though and added a mask that prevented the
ECN bits from being populated in the L3 header.

This patch addresses that by rolling back the mask so that it is only
applied to the flags coming from the incoming TCP request instead of
applying it to the socket tos/tclass field. Doing this the ECT bits were
restored in the SYN/ACK packets in my testing.

One thing that is not addressed by this patch set is the fact that
tcp_reflect_tos appears to be incompatible with ECN based congestion
avoidance algorithms. At a minimum the feature should likely be documented
which it currently isn't.

Fixes: ac8f1710c12b ("tcp: reflect tos value received in SYN to the socket")
Signed-off-by: Alexander Duyck <alexanderduyck@fb.com>
Acked-by: Wei Wang <weiwan@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c

index 7352c097ae48f7df6caba1ae5b98dccfecd79d1a..25d35a56ceba0582da560b239f8c51f135d9a751 100644 (file)
@@ -981,7 +981,8 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
        skb = tcp_make_synack(sk, dst, req, foc, synack_type, syn_skb);
 
        tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
-                       tcp_rsk(req)->syn_tos : inet_sk(sk)->tos;
+                       tcp_rsk(req)->syn_tos & ~INET_ECN_MASK :
+                       inet_sk(sk)->tos;
 
        if (skb) {
                __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
@@ -990,7 +991,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
                err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
                                            ireq->ir_rmt_addr,
                                            rcu_dereference(ireq->ireq_opt),
-                                           tos & ~INET_ECN_MASK);
+                                           tos);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
index 8db59f4e5f13a99571b26f618100e0f9510b7217..3d49e8d0afeebb1cb7133932dca9a1ac6d6884ab 100644 (file)
@@ -530,12 +530,12 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                rcu_read_lock();
                opt = ireq->ipv6_opt;
                tclass = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ?
-                               tcp_rsk(req)->syn_tos : np->tclass;
+                               tcp_rsk(req)->syn_tos & ~INET_ECN_MASK :
+                               np->tclass;
                if (!opt)
                        opt = rcu_dereference(np->opt);
                err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt,
-                              tclass & ~INET_ECN_MASK,
-                              sk->sk_priority);
+                              tclass, sk->sk_priority);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }