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);
}