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++;
 

Reply via email to