summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2013-10-19 10:38:56 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2013-10-19 10:38:56 +0000
commit5020dd8837f56b45edd717dde5f5ff870fc14dcf (patch)
tree6cda27f1c1cb19b88ba176bb0ebd3e80ca590413 /sys/netinet
parentb6ce80a2aefa4b19550d5c0ed14e253f64a6b65e (diff)
make in_proto_cksum_out not rely on the pseudo header checksum to be
already there, just compute it - it's dirt cheap. since that happens very late in ip_output, the rest of the stack doesn't have to care about checksums at all any more, if something needs to be checksummed, just set the flag on the pkthdr mbuf to indicate so. stop pre-computing the pseudo header checksum and incrementally updating it in the tcp and udp stacks. ok lteo florian
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_output.c21
-rw-r--r--sys/netinet/tcp_output.c26
-rw-r--r--sys/netinet/tcp_subr.c7
-rw-r--r--sys/netinet/udp_usrreq.c16
4 files changed, 28 insertions, 42 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 01cdd2c5307..52f99148f70 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.247 2013/10/18 09:04:03 mpi Exp $ */
+/* $OpenBSD: ip_output.c,v 1.248 2013/10/19 10:38:54 henning Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -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) {
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 9d5b469a51f..d3b8c768bd9 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.99 2013/08/12 21:57:16 bluhm Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.100 2013/10/19 10:38:55 henning Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -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
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index ff9249bb62e..1546619145c 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.120 2013/06/01 16:22:05 bluhm Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.121 2013/10/19 10:38:55 henning Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -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);
}
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index e2e3e9f61f3..0604b9f0c8a 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.168 2013/10/17 16:27:44 bluhm Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.169 2013/10/19 10:38:55 henning Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -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++;