mbuf: Save linker layer, IP and TCP/UDP header length
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 1 Aug 2012 02:35:06 +0000 (10:35 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 1 Aug 2012 02:54:40 +0000 (10:54 +0800)
This could ease most drivers's TSO operation and avoid extra data
area accessing during TSO setting up.

This could also help Intel's 1000M/10G drivers' hardware checksum
offloading, which requires protocol header length.

sys/net/if_ethersubr.c
sys/net/pf/pf.c
sys/net/vlan/if_vlan_ether.c
sys/netinet/ip_output.c
sys/netinet/tcp_output.c
sys/netinet/tcp_subr.c
sys/netinet/tcp_syncache.c
sys/netinet/udp_usrreq.c
sys/sys/mbuf.h

index 256bfa1..6923356 100644 (file)
@@ -220,6 +220,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
        M_PREPEND(m, sizeof(struct ether_header), MB_DONTWAIT);
        if (m == NULL)
                return (ENOBUFS);
+       m->m_pkthdr.csum_lhlen = sizeof(struct ether_header);
        eh = mtod(m, struct ether_header *);
        edst = eh->ether_dhost;
 
index 1fb85c1..4bcaed3 100644 (file)
@@ -5537,6 +5537,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
                sw_csum &= ~CSUM_DELAY_DATA;
        }
        m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
+       m0->m_pkthdr.csum_iphlen = (ip->ip_hl << 2);
 
        if (ip->ip_len <= ifp->if_mtu ||
            (ifp->if_hwassist & CSUM_FRAGMENT &&
index ace6e41..a779852 100644 (file)
@@ -99,6 +99,7 @@ vlan_start_dispatch(netmsg_t msg)
                        if_printf(ifp, "vlan%u m_pullup failed", vlantag);
                        goto back;
                }
+               m->m_pkthdr.csum_lhlen = sizeof(struct ether_vlan_header);
 
                /*
                 * Transform the Ethernet header into an Ethernet header
index 042a9b4..5ccbb60 100644 (file)
@@ -922,6 +922,7 @@ pass:
        } else {
                sw_csum = 0;
        }
+       m->m_pkthdr.csum_iphlen = hlen;
 
        /*
         * If small enough for interface, or the interface will take
@@ -1188,6 +1189,7 @@ smart_frag_failure:
                m->m_pkthdr.len = mhlen + len;
                m->m_pkthdr.rcvif = NULL;
                m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
+               m->m_pkthdr.csum_iphlen = mhlen;
                mhip->ip_off = htons(mhip->ip_off);
                mhip->ip_sum = 0;
                if (sw_csum & CSUM_DELAY_IP)
index 6c9c5aa..9946203 100644 (file)
@@ -1023,12 +1023,14 @@ after_th:
                            sizeof(struct ip6_hdr),
                            sizeof(struct tcphdr) + optlen + len);
                } else {
-                       m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+                       m->m_pkthdr.csum_thlen = sizeof(struct tcphdr) + optlen;
                        if (use_tso) {
                                m->m_pkthdr.csum_flags = CSUM_TSO;
                                m->m_pkthdr.segsz = segsz;
                        } else {
                                m->m_pkthdr.csum_flags = CSUM_TCP;
+                               m->m_pkthdr.csum_data =
+                                   offsetof(struct tcphdr, th_sum);
                                if (len + optlen) {
                                        th->th_sum = in_addword(th->th_sum,
                                            htons((u_short)(optlen + len)));
index 6383fff..9a88fc7 100644 (file)
@@ -662,6 +662,7 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
                    htons((u_short)(tlen - sizeof(struct ip) + ip->ip_p)));
                m->m_pkthdr.csum_flags = CSUM_TCP;
                m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+               m->m_pkthdr.csum_thlen = sizeof(struct tcphdr);
        }
 #ifdef TCPDEBUG
        if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
index 5eeaaa6..5dbac2b 100644 (file)
@@ -1323,6 +1323,7 @@ no_options:
                                       htons(tlen - hlen + IPPROTO_TCP));
                m->m_pkthdr.csum_flags = CSUM_TCP;
                m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+               m->m_pkthdr.csum_thlen = sizeof(struct tcphdr) + optlen;
                error = ip_output(m, sc->sc_ipopts, &sc->sc_route,
                                  IP_DEBUGROUTE, NULL, sc->sc_tp->t_inpcb);
        }
index e5547dd..7160958 100644 (file)
@@ -895,6 +895,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *dstaddr,
                    htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
                m->m_pkthdr.csum_flags = CSUM_UDP;
                m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+               m->m_pkthdr.csum_thlen = sizeof(struct udphdr);
        } else {
                ui->ui_sum = 0;
        }
index 2040ff1..74c5ff8 100644 (file)
@@ -162,6 +162,11 @@ struct pkthdr {
        /* variables for hardware checksum */
        int     csum_flags;             /* flags regarding checksum */
        int     csum_data;              /* data field used by csum routines */
+       uint16_t csum_iphlen;           /* IP header length */
+                                       /* valid if CSUM IP|UDP|TCP|TSO */
+       uint8_t csum_thlen;             /* TCP/UDP header length */
+                                       /* valid if CSUM UDP|TCP|TSO */
+       uint8_t csum_lhlen;             /* link header length */
 
        /* firewall flags */
        uint32_t fw_flags;              /* flags for PF */