aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/udp_usrreq.c
diff options
context:
space:
mode:
authorJonathan Lemon <jlemon@FreeBSD.org>2000-03-27 19:14:27 +0000
committerJonathan Lemon <jlemon@FreeBSD.org>2000-03-27 19:14:27 +0000
commitdb4f9cc70389b2004594fea6f910e5091855ddf8 (patch)
tree18fe751adcccc8aec961339214bd6bf346ee66d4 /sys/netinet/udp_usrreq.c
parent07b065a591b026c05dbb40e715987592c28db5cd (diff)
downloadsrc-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.c35
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 */