Hi, I noticed a missing checksum count in netstat tcp packets sent software-checksummed. Turns out that our syn cache does the checksum calculation by hand, instead of the established mechanism in ip output.
Just set the flag M_TCP_CSUM_OUT and let in_proto_cksum_out() do the work later. While there remove redundant code. The unhandled af case is handled in the first switch statement of the function. ok? bluhm Index: netinet/tcp_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.387 diff -u -p -r1.387 tcp_input.c --- netinet/tcp_input.c 14 Mar 2023 00:24:05 -0000 1.387 +++ netinet/tcp_input.c 22 May 2023 19:48:25 -0000 @@ -3990,14 +3990,11 @@ syn_cache_respond(struct syn_cache *sc, 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, } #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, 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); }