diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2001-06-23 02:27:12 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2001-06-23 02:27:12 +0000 |
commit | c2aa68d2ac00ee99e6cd348159b9357e348772df (patch) | |
tree | f76ac23aa90872946925525300f770dcad012bfb /sys/netinet | |
parent | b8794969a7662bd38ddaacd86161705cfdd40e16 (diff) |
TCP, UDP, IPv4 input hardware checksumming processing; also IPv4
output hardware checksumming. Not tested yet, but should be done
tonight.
Remain to be solved: interactions with bridge, TCP/UDP output
checksumming, interactions of TCP/UDP checksumming with routing
changes.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_input.c | 11 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 39 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 11 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 15 |
4 files changed, 56 insertions, 20 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 4af835b04b9..18dce3acddc 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.76 2001/06/19 00:48:23 deraadt Exp $ */ +/* $OpenBSD: ip_input.c,v 1.77 2001/06/23 02:27:09 angelos Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -332,9 +332,12 @@ ipv4_input(m) } } - if (in_cksum(m, hlen) != 0) { - ipstat.ips_badsum++; - goto bad; + if ((m->m_pkthdr.csum & M_IPV4_CSUM_IN_OK) == 0) { + if (m->m_pkthdr.csum & M_IPV4_CSUM_IN_BAD || + in_cksum(m, hlen) != 0) { + ipstat.ips_badsum++; + goto bad; + } } /* diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 9a52a837e2d..c6ca2c6e493 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.104 2001/06/19 18:49:53 jasoni Exp $ */ +/* $OpenBSD: ip_output.c,v 1.105 2001/06/23 02:27:10 angelos Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -592,12 +592,29 @@ sendit: if ((u_int16_t)ip->ip_len <= ifp->if_mtu) { ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_off = htons((u_int16_t)ip->ip_off); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m, hlen); + if (ifp->if_capabilities & IFCAP_CSUM_IPv4) + m->m_pkthdr.csum |= M_IPV4_CSUM_OUT; + else { + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m, hlen); + } error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt); goto done; } + /* Catch routing changes. */ + if (m->m_pkthdr.csum & M_TCPV4_CSUM_OUT && + !(ifp->if_capabilities & IFCAP_CSUM_TCPv4)) { + /* XXX Compute TCP checksum */ + m->m_pkthdr.csum &= ~M_TCPV4_CSUM_OUT; /* Clear */ + } + + if (m->m_pkthdr.csum & M_UDPV4_CSUM_OUT && + !(ifp->if_capabilities & IFCAP_CSUM_UDPv4)) { + /* XXX Compute UDP checksum */ + m->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */ + } + /* * Too large for interface; fragment if possible. * Must be able to put at least 8 bytes per fragment. @@ -659,8 +676,12 @@ sendit: m->m_pkthdr.len = mhlen + len; m->m_pkthdr.rcvif = (struct ifnet *)0; mhip->ip_off = htons((u_int16_t)mhip->ip_off); - mhip->ip_sum = 0; - mhip->ip_sum = in_cksum(m, mhlen); + if (ifp->if_capabilities & IFCAP_CSUM_IPv4) + m->m_pkthdr.csum |= M_IPV4_CSUM_OUT; + else { + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(m, mhlen); + } ipstat.ips_ofragments++; } /* @@ -672,8 +693,12 @@ sendit: m->m_pkthdr.len = hlen + firstlen; ip->ip_len = htons((u_int16_t)m->m_pkthdr.len); ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m, hlen); + if (ifp->if_capabilities & IFCAP_CSUM_IPv4) + m->m_pkthdr.csum |= M_IPV4_CSUM_OUT; + else { + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m, hlen); + } sendorfree: for (m = m0; m; m = m0) { m0 = m->m_nextpkt; diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 750b3e58b8f..1b92826a59c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.94 2001/06/12 10:59:53 angelos Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.95 2001/06/23 02:27:10 angelos Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -511,9 +511,12 @@ tcp_input(m, va_alist) bzero(ti->ti_x1, sizeof ti->ti_x1); ti->ti_len = (u_int16_t)tlen; HTONS(ti->ti_len); - if ((ti->ti_sum = in_cksum(m, len)) != 0) { - tcpstat.tcps_rcvbadsum++; - goto drop; + if ((m->m_pkthdr.csum & M_TCP_CSUM_IN_OK) == 0) { + if (m->m_pkthdr.csum & M_TCP_CSUM_IN_BAD || + (ti->ti_sum = in_cksum(m, len)) != 0) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } } break; } diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 568fd453545..0a25339bbe3 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.63 2001/06/19 00:48:23 deraadt Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.64 2001/06/23 02:27:11 angelos Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -300,10 +300,15 @@ udp_input(m, va_alist) bzero(((struct ipovly *)ip)->ih_x1, sizeof ((struct ipovly *)ip)->ih_x1); ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - if ((uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) != 0) { - udpstat.udps_badsum++; - m_freem(m); - return; + + if ((m->m_pkthdr.csum & M_UDP_CSUM_IN_OK) == 0) { + if (m->m_pkthdr.csum & M_UDP_CSUM_IN_BAD || + (uh->uh_sum = in_cksum(m, len + + sizeof (struct ip))) != 0) { + udpstat.udps_badsum++; + m_freem(m); + return; + } } } else udpstat.udps_nosum++; |