From 32c8d29b2bee8970908d8ff6c5a8cd20e1c4c249 Mon Sep 17 00:00:00 2001 From: bluhm Date: Mon, 22 May 2023 16:08:34 +0000 Subject: [PATCH] Fix TSO for traffic to a local address on a physical interface. When sending TCP packets with software TSO to the local address of a physical interface, the TCP checksum was miscalculated. As the small MSS is taken from the physical interface, but the large MTU of the loopback interface is used, large TSO packets are generated, but sent directly to the loopback interface. There we need the regular pseudo header checksum and not the modified without packet length. To avoid this confusion, use the same decision for checksum generation in in_proto_cksum_out() as for using hardware TSO in tcp_if_output_tso(). bug reported and tested by robert@ bket@ Hrvoje Popovski OK claudio@ jan@ --- sys/netinet/ip_output.c | 5 +++-- sys/netinet6/ip6_output.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index a44ee063d06..86288bc8892 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.387 2023/05/15 16:34:56 bluhm Exp $ */ +/* $OpenBSD: ip_output.c,v 1.388 2023/05/22 16:08:34 bluhm Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -1882,7 +1882,8 @@ in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp) u_int16_t csum = 0, offset; offset = ip->ip_hl << 2; - if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) { + if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && + in_ifcap_cksum(m, ifp, IFCAP_TSOv4)) { csum = in_cksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr, htonl(ip->ip_p)); } else if (ISSET(m->m_pkthdr.csum_flags, diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index add8fb22c66..05c11898e01 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_output.c,v 1.276 2023/05/15 16:34:57 bluhm Exp $ */ +/* $OpenBSD: ip6_output.c,v 1.277 2023/05/22 16:08:34 bluhm Exp $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */ /* @@ -2710,7 +2710,8 @@ in6_proto_cksum_out(struct mbuf *m, struct ifnet *ifp) u_int16_t csum; offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); - if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) { + if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) && + in_ifcap_cksum(m, ifp, IFCAP_TSOv6)) { csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst, htonl(0), htonl(nxt)); } else { -- 2.20.1