From eb45cfdb2f086f4326781f6af8406f5aa13f13e2 Mon Sep 17 00:00:00 2001 From: bluhm Date: Tue, 30 May 2023 19:32:57 +0000 Subject: [PATCH] Use generic checksum calculation for TCP SYN+ACK packets. Our syn cache did checksum calculation by hand, instead of the established mechanism in ip output. The software-checksummed counter increased once per incoming TCP connection. Just set the flag M_TCP_CSUM_OUT in syn_cache_respond() and let in_proto_cksum_out() do the work later. Then hardware checksumming is used where available. Also remove redundant code. The unhandled af case is handled in the first switch statement of the function. tested by Hrvoje Popovski; OK mvs@ --- sys/netinet/tcp_input.c | 41 ++++++----------------------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 1077746e8dc..5986da0ddb6 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.387 2023/03/14 00:24:05 yasuoka Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.388 2023/05/30 19:32:57 bluhm Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -3990,14 +3990,11 @@ syn_cache_respond(struct syn_cache *sc, struct mbuf *m, uint32_t now) ip6->ip6_dst = sc->sc_src.sin6.sin6_addr; ip6->ip6_src = sc->sc_dst.sin6.sin6_addr; ip6->ip6_nxt = IPPROTO_TCP; - /* ip6_plen will be updated in ip6_output() */ th = (struct tcphdr *)(ip6 + 1); th->th_dport = sc->sc_src.sin6.sin6_port; th->th_sport = sc->sc_dst.sin6.sin6_port; break; #endif - default: - unhandled_af(sc->sc_src.sa.sa_family); } th->th_seq = htonl(sc->sc_iss); @@ -4096,21 +4093,7 @@ syn_cache_respond(struct syn_cache *sc, struct mbuf *m, uint32_t now) } #endif /* TCP_SIGNATURE */ - /* Compute the packet's checksum. */ - switch (sc->sc_src.sa.sa_family) { - case AF_INET: - ip->ip_len = htons(tlen - hlen); - th->th_sum = 0; - th->th_sum = in_cksum(m, tlen); - break; -#ifdef INET6 - case AF_INET6: - ip6->ip6_plen = htons(tlen - hlen); - th->th_sum = 0; - th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen, tlen - hlen); - break; -#endif - } + SET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT); /* use IPsec policy and ttl from listening socket, on SYN ACK */ inp = sc->sc_tp ? sc->sc_tp->t_inpcb : NULL; @@ -4125,34 +4108,22 @@ syn_cache_respond(struct syn_cache *sc, struct mbuf *m, uint32_t now) ip->ip_ttl = inp ? inp->inp_ip.ip_ttl : ip_defttl; if (inp != NULL) ip->ip_tos = inp->inp_ip.ip_tos; - break; -#ifdef INET6 - case AF_INET6: - ip6->ip6_vfc &= ~IPV6_VERSION_MASK; - ip6->ip6_vfc |= IPV6_VERSION; - ip6->ip6_plen = htons(tlen - hlen); - /* ip6_hlim will be initialized afterwards */ - /* leave flowlabel = 0, it is legal and require no state mgmt */ - break; -#endif - } - switch (sc->sc_src.sa.sa_family) { - case AF_INET: error = ip_output(m, sc->sc_ipopts, &sc->sc_route4, (ip_mtudisc ? IP_MTUDISC : 0), NULL, inp, 0); break; #ifdef INET6 case AF_INET6: + ip6->ip6_vfc &= ~IPV6_VERSION_MASK; + ip6->ip6_vfc |= IPV6_VERSION; + /* ip6_plen will be updated in ip6_output() */ ip6->ip6_hlim = in6_selecthlim(inp); + /* leave flowlabel = 0, it is legal and require no state mgmt */ error = ip6_output(m, NULL /*XXX*/, &sc->sc_route6, 0, NULL, NULL); break; #endif - default: - error = EAFNOSUPPORT; - break; } return (error); } -- 2.20.1