diff options
author | Jonathan Lemon <jlemon@FreeBSD.org> | 2000-03-27 19:14:27 +0000 |
---|---|---|
committer | Jonathan Lemon <jlemon@FreeBSD.org> | 2000-03-27 19:14:27 +0000 |
commit | db4f9cc70389b2004594fea6f910e5091855ddf8 (patch) | |
tree | 18fe751adcccc8aec961339214bd6bf346ee66d4 /sys/netinet/udp_usrreq.c | |
parent | 07b065a591b026c05dbb40e715987592c28db5cd (diff) | |
download | src-db4f9cc70389b2004594fea6f910e5091855ddf8.tar.gz src-db4f9cc70389b2004594fea6f910e5091855ddf8.zip |
Add support for offloading IP/TCP/UDP checksums to NIC hardware which
supports them.
Notes
Notes:
svn path=/head/; revision=58698
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r-- | sys/netinet/udp_usrreq.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 2ed9a363ebcc..b8700de91569 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -37,6 +37,7 @@ #include "opt_ipsec.h" #include "opt_inet6.h" +#include <stddef.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -76,6 +77,8 @@ #include <netinet6/ipsec.h> #endif /*IPSEC*/ +#include <machine/in_cksum.h> + /* * UDP protocol implementation. * Per RFC 768, August, 1980. @@ -208,9 +211,19 @@ udp_input(m, off, proto) * Checksum extended UDP header and data. */ if (uh->uh_sum) { - bzero(((struct ipovly *)ip)->ih_x1, 9); - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); + if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { + if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) + uh->uh_sum = m->m_pkthdr.csum_data; + else + uh->uh_sum = in_pseudo(ip->ip_src.s_addr, + ip->ip_dst.s_addr, htonl(ip->ip_len + + m->m_pkthdr.csum_data + IPPROTO_UDP)); + uh->uh_sum ^= 0xffff; + } else { + bzero(((struct ipovly *)ip)->ih_x1, 9); + ((struct ipovly *)ip)->ih_len = uh->uh_ulen; + uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); + } if (uh->uh_sum) { udpstat.udps_badsum++; m_freem(m); @@ -679,22 +692,24 @@ udp_output(inp, m, addr, control, p) * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); - bzero(ui->ui_x1, sizeof(ui->ui_x1)); + bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */ ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); ui->ui_src = inp->inp_laddr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; - ui->ui_ulen = ui->ui_len; + ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr)); /* - * Stuff checksum and output datagram. + * Set up checksum and output datagram. */ - ui->ui_sum = 0; if (udpcksum) { - if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) - ui->ui_sum = 0xffff; + ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr, + 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); + } else { + ui->ui_sum = 0; } ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */ |