so stop that pseudo-header wankery. v6 doesn't have it at all. instead
of incrementally pre-computing a tiny part of the proto cksum, just do
it in in_proto_cksum_out when needed.
makes everything else in the stack super easy: need cksum? set flag,
done.
stack and pf cases tested with all 3 offloading variants (none /
needs-phdr / full).
and if sk(4) wouldn't be such a weird beast with it's
more-in-software-than-hw RX offloading in_cksum_addword could be
deleted too.
ok?
Index: net/if_pflow.c
===================================================================
RCS file: /cvs/src/sys/net/if_pflow.c,v
retrieving revision 1.36
diff -u -p -r1.36 if_pflow.c
--- net/if_pflow.c 17 Oct 2013 16:27:41 -0000 1.36
+++ net/if_pflow.c 18 Oct 2013 13:35:38 -0000
@@ -126,9 +126,6 @@ struct if_clone pflow_cloner =
IF_CLONE_INITIALIZER("pflow", pflow_clone_create,
pflow_clone_destroy);
-/* from udp_usrreq.c */
-extern int udpcksum;
-
void
pflowattach(int npflow)
{
@@ -1535,6 +1532,8 @@ pflow_sendout_mbuf(struct pflow_softc *s
ui->ui_dst = sc->sc_receiver_ip;
ui->ui_dport = sc->sc_receiver_port;
ui->ui_ulen = htons(sizeof(struct udphdr) + len);
+ ui->ui_sum = 0;
+ m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
ip = (struct ip *)ui;
ip->ip_v = IPVERSION;
@@ -1544,18 +1543,6 @@ pflow_sendout_mbuf(struct pflow_softc *s
ip->ip_tos = IPTOS_LOWDELAY;
ip->ip_ttl = IPDEFTTL;
ip->ip_len = htons(sizeof(struct udpiphdr) + len);
-
- /*
- * Compute the pseudo-header checksum; defer further checksumming
- * until ip_output() or hardware (if it exists).
- */
- if (udpcksum) {
- m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
- ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
- ui->ui_dst.s_addr, htons(len + sizeof(struct udphdr) +
- IPPROTO_UDP));
- } else
- ui->ui_sum = 0;
#if NBPFILTER > 0
if (ifp->if_bpf) {
Index: net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.844
diff -u -p -r1.844 pf.c
--- net/pf.c 17 Oct 2013 16:27:41 -0000 1.844
+++ net/pf.c 18 Oct 2013 13:15:04 -0000
@@ -6742,20 +6742,10 @@ pf_cksum(struct pf_pdesc *pd, struct mbu
switch (pd->proto) {
case IPPROTO_TCP:
pd->hdr.tcp->th_sum = 0;
- if (pd->af == AF_INET) {
- pd->hdr.tcp->th_sum = in_cksum_phdr(pd->src->v4.s_addr,
- pd->dst->v4.s_addr, htons(pd->tot_len -
- pd->off + IPPROTO_TCP));
- }
m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT;
break;
case IPPROTO_UDP:
pd->hdr.udp->uh_sum = 0;
- if (pd->af == AF_INET) {
- pd->hdr.udp->uh_sum = in_cksum_phdr(pd->src->v4.s_addr,
- pd->dst->v4.s_addr, htons(pd->tot_len -
- pd->off + IPPROTO_UDP));
- }
m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
break;
case IPPROTO_ICMP:
Index: net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.44
diff -u -p -r1.44 pipex.c
--- net/pipex.c 17 Oct 2013 16:27:43 -0000 1.44
+++ net/pipex.c 18 Oct 2013 13:34:13 -0000
@@ -1976,7 +1976,9 @@ pipex_l2tp_output(struct mbuf *m0, struc
udp->uh_sport = session->local.sin6.sin6_port;
udp->uh_dport = session->peer.sin6.sin6_port;
udp->uh_ulen = htons(plen);
+ udp->uh_sum = 0;
+ m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
m0->m_pkthdr.rcvif = session->pipex_iface->ifnet_this;
#if NPF > 0
pf_pkt_addr_changed(m0);
@@ -1991,13 +1993,6 @@ pipex_l2tp_output(struct mbuf *m0, struc
ip->ip_ttl = MAXTTL;
ip->ip_tos = 0;
- if (udpcksum) {
- udp->uh_sum = in_cksum_phdr(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(plen + IPPROTO_UDP));
- m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
- } else
- udp->uh_sum = 0;
-
if (ip_output(m0, NULL, NULL, IP_IPSECFLOW, NULL, NULL,
session->proto.l2tp.ipsecflowinfo) != 0) {
PIPEX_DBG((session, LOG_DEBUG, "ip_output failed."));
@@ -2017,10 +2012,6 @@ pipex_l2tp_output(struct mbuf *m0, struc
&session->peer.sin6, NULL, NULL);
/* ip6->ip6_plen will be filled in ip6_output. */
- udp->uh_sum = 0;
- if ((udp->uh_sum = in6_cksum(m0, IPPROTO_UDP,
- sizeof(struct ip6_hdr), plen)) == 0)
- udp->uh_sum = 0xffff;
if (ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL) != 0) {
PIPEX_DBG((session, LOG_DEBUG, "ip6_output failed."));
goto drop;
Index: netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.247
diff -u -p -r1.247 ip_output.c
--- netinet/ip_output.c 18 Oct 2013 09:04:03 -0000 1.247
+++ netinet/ip_output.c 18 Oct 2013 14:24:12 -0000
@@ -2083,6 +2083,25 @@ in_delayed_cksum(struct mbuf *m)
void
in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
{
+ /* some hw and in_delayed_cksum need the pseudo header cksum */
+ if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) {
+ struct ip *ip;
+ u_int16_t csum, offset;
+
+ ip = mtod(m, struct ip *);
+ offset = ip->ip_hl << 2;
+ csum = in_cksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+ htonl(ntohs(ip->ip_len) - offset + ip->ip_p));
+ if (ip->ip_p == IPPROTO_TCP)
+ offset += offsetof(struct tcphdr, th_sum);
+ else if (ip->ip_p == IPPROTO_UDP)
+ offset += offsetof(struct udphdr, uh_sum);
+ if ((offset + sizeof(u_int16_t)) > m->m_len)
+ m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
+ else
+ *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
+ }
+
if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
ifp->if_bridgeport != NULL) {
Index: netinet/tcp_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_output.c,v
retrieving revision 1.99
diff -u -p -r1.99 tcp_output.c
--- netinet/tcp_output.c 12 Aug 2013 21:57:16 -0000 1.99
+++ netinet/tcp_output.c 18 Oct 2013 13:22:08 -0000
@@ -947,28 +947,8 @@ send:
}
#endif /* TCP_SIGNATURE */
- /*
- * Put TCP length in extended header, and then
- * checksum extended header and data.
- */
- switch (tp->pf) {
- case 0: /*default to PF_INET*/
-#ifdef INET
- case AF_INET:
- /* Defer checksumming until later (ip_output() or hardware) */
- m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT;
- if (len + optlen)
- th->th_sum = in_cksum_addword(th->th_sum,
- htons((u_int16_t)(len + optlen)));
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr),
- hdrlen - sizeof(struct ip6_hdr) + len);
- break;
-#endif /* INET6 */
- }
+ /* Defer checksumming until later (ip_output() or hardware) */
+ m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT;
/*
* In transmit state, time the transmission and arrange for
Index: netinet/tcp_subr.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.120
diff -u -p -r1.120 tcp_subr.c
--- netinet/tcp_subr.c 1 Jun 2013 16:22:05 -0000 1.120
+++ netinet/tcp_subr.c 18 Oct 2013 14:45:09 -0000
@@ -257,9 +257,6 @@ tcp_template(tp)
th = (struct tcphdr *)(mtod(m, caddr_t) +
sizeof(struct ip));
- th->th_sum = in_cksum_phdr(ipovly->ih_src.s_addr,
- ipovly->ih_dst.s_addr,
- htons(sizeof (struct tcphdr) + IPPROTO_TCP));
}
break;
#endif /* INET */
@@ -281,7 +278,6 @@ tcp_template(tp)
th = (struct tcphdr *)(mtod(m, caddr_t) +
sizeof(struct ip6_hdr));
- th->th_sum = 0;
}
break;
#endif /* INET6 */
@@ -296,6 +292,7 @@ tcp_template(tp)
th->th_flags = 0;
th->th_win = 0;
th->th_urp = 0;
+ th->th_sum = 0;
return (m);
}
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.168
diff -u -p -r1.168 udp_usrreq.c
--- netinet/udp_usrreq.c 17 Oct 2013 16:27:44 -0000 1.168
+++ netinet/udp_usrreq.c 18 Oct 2013 13:31:29 -0000
@@ -1077,21 +1077,11 @@ udp_output(struct mbuf *m, ...)
ui->ui_sport = inp->inp_lport;
ui->ui_dport = inp->inp_fport;
ui->ui_ulen = ui->ui_len;
-
- /*
- * Compute the pseudo-header checksum; defer further checksumming
- * until ip_output() or hardware (if it exists).
- */
- if (udpcksum) {
- m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
- ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
- ui->ui_dst.s_addr, htons((u_int16_t)len +
- sizeof (struct udphdr) + IPPROTO_UDP));
- } else
- ui->ui_sum = 0;
((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl;
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos;
+ if (udpcksum)
+ m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
udpstat.udps_opackets++;