Pull up following revision(s) (requested by rmind in ticket #746): netbsd-6-0
authorriz <riz@NetBSD.org>
Sun, 16 Dec 2012 18:20:09 +0000
branchnetbsd-6-0
changeset 276241 a73228d74465
parent 276240 b90e45899582
child 276242 c4f631669252
Pull up following revision(s) (requested by rmind in ticket #746): sys/net/npf/npf_inet.c: revision 1.18 sys/net/npf/npf_mbuf.c: revision 1.8 sys/net/npf/npf.h: revision 1.23 npf_rwrcksum: handle delayed checksums in the network stack; also fix non-NPF_NAT_PORTS case and add some comments. PR/47235.
sys/net/npf/npf.h
sys/net/npf/npf_inet.c
sys/net/npf/npf_mbuf.c
--- a/sys/net/npf/npf.h	Sat Dec 15 23:35:13 2012 +0000
+++ b/sys/net/npf/npf.h	Sun Dec 16 18:20:09 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.h,v 1.14.2.6 2012/07/25 20:45:23 jdc Exp $	*/
+/*	$NetBSD: npf.h,v 1.14.2.6.4.1 2012/12/16 18:20:09 riz Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -141,6 +141,7 @@
 int		nbuf_fetch_datum(nbuf_t *, void *, size_t, void *);
 int		nbuf_store_datum(nbuf_t *, void *, size_t, void *);
 
+void		nbuf_cksum_barrier(nbuf_t *);
 int		nbuf_add_tag(nbuf_t *, uint32_t, uint32_t);
 int		nbuf_find_tag(nbuf_t *, uint32_t, void **);
 
--- a/sys/net/npf/npf_inet.c	Sat Dec 15 23:35:13 2012 +0000
+++ b/sys/net/npf/npf_inet.c	Sun Dec 16 18:20:09 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_inet.c,v 1.10.4.5 2012/07/25 20:45:23 jdc Exp $	*/
+/*	$NetBSD: npf_inet.c,v 1.10.4.5.4.1 2012/12/16 18:20:09 riz Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.10.4.5 2012/07/25 20:45:23 jdc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.10.4.5.4.1 2012/12/16 18:20:09 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -598,65 +598,80 @@
 {
 	const int proto = npf_cache_ipproto(npc);
 	npf_addr_t *oaddr;
-	in_port_t *oport;
-	uint16_t *cksum;
+	uint16_t *ocksum;
+	in_port_t oport;
 	u_int offby;
 
-	/* Checksum update for IPv4 header. */
+	/* XXX: NetBSD - process delayed checksums. */
+	if (di == PFIL_OUT && proto != IPPROTO_ICMP) {
+		nbuf_cksum_barrier(nbuf);
+		npc->npc_info &= ~(NPC_LAYER4 | NPC_TCP | NPC_UDP);
+		if (!npf_cache_all(npc, nbuf)) {
+			return false;
+		}
+	}
+
+	oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip;
+
 	if (npf_iscached(npc, NPC_IP4)) {
 		struct ip *ip = &npc->npc_ip.v4;
 		uint16_t ipsum;
 
-		oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip;
+		/* Recalculate IPv4 checksum, advance to it and rewrite. */
 		ipsum = npf_addr_cksum(ip->ip_sum, npc->npc_alen, oaddr, addr);
-
-		/* Advance to the IPv4 checksum and rewrite it. */
 		offby = offsetof(struct ip, ip_sum);
 		if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(ipsum), &ipsum))
 			return false;
-
 		ip->ip_sum = ipsum;
-		offby = npf_cache_hlen(npc) - offby;
 	} else {
 		/* No checksum for IPv6. */
 		KASSERT(npf_iscached(npc, NPC_IP6));
-		oaddr = NULL;
 		offby = 0;
-		return false;	/* XXX: Not yet supported. */
 	}
 
-	/* Determine whether TCP/UDP checksum update is needed. */
-	if (proto == IPPROTO_ICMP || port == 0) {
+	/* Nothing else to do for ICMP. */
+	if (proto == IPPROTO_ICMP) {
 		return true;
 	}
 	KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
+	offby = npf_cache_hlen(npc) - offby;
 
-	/* Calculate TCP/UDP checksum. */
+	/*
+	 * Calculate TCP/UDP checksum:
+	 * - Skip if UDP and the current checksum is zero.
+	 * - Fixup the IP address change.
+	 * - Fixup the port change, if required (non-zero).
+	 */
 	if (proto == IPPROTO_TCP) {
 		struct tcphdr *th = &npc->npc_l4.tcp;
 
-		cksum = &th->th_sum;
+		ocksum = &th->th_sum;
 		offby += offsetof(struct tcphdr, th_sum);
-		oport = (di == PFIL_OUT) ? &th->th_sport : &th->th_dport;
+		oport = (di == PFIL_OUT) ? th->th_sport : th->th_dport;
 	} else {
 		struct udphdr *uh = &npc->npc_l4.udp;
 
 		KASSERT(proto == IPPROTO_UDP);
-		cksum = &uh->uh_sum;
-		if (*cksum == 0) {
+		ocksum = &uh->uh_sum;
+		if (*ocksum == 0) {
 			/* No need to update. */
 			return true;
 		}
 		offby += offsetof(struct udphdr, uh_sum);
-		oport = (di == PFIL_OUT) ? &uh->uh_sport : &uh->uh_dport;
+		oport = (di == PFIL_OUT) ? uh->uh_sport : uh->uh_dport;
 	}
-	*cksum = npf_addr_cksum(*cksum, npc->npc_alen, oaddr, addr);
-	*cksum = npf_fixup16_cksum(*cksum, *oport, port);
+
+	uint16_t cksum = *ocksum;
+	cksum = npf_addr_cksum(cksum, npc->npc_alen, oaddr, addr);
+	if (port) {
+		cksum = npf_fixup16_cksum(cksum, oport, port);
+	}
 
 	/* Advance to TCP/UDP checksum and rewrite it. */
-	if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(uint16_t), cksum)) {
+	if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(cksum), &cksum)) {
 		return false;
 	}
+	*ocksum = cksum;
 	return true;
 }
 
--- a/sys/net/npf/npf_mbuf.c	Sat Dec 15 23:35:13 2012 +0000
+++ b/sys/net/npf/npf_mbuf.c	Sun Dec 16 18:20:09 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_mbuf.c,v 1.6.14.1 2012/06/26 00:07:16 riz Exp $	*/
+/*	$NetBSD: npf_mbuf.c,v 1.6.14.1.4.1 2012/12/16 18:20:09 riz Exp $	*/
 
 /*-
  * Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.6.14.1 2012/06/26 00:07:16 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.6.14.1.4.1 2012/12/16 18:20:09 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -233,6 +233,17 @@
 	return error;
 }
 
+void
+nbuf_cksum_barrier(nbuf_t *nbuf)
+{
+	struct mbuf *m = nbuf;
+
+	if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4 | M_CSUM_UDPv4)) {
+		in_delayed_cksum(m);
+		m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4 | M_CSUM_UDPv4);
+	}
+}
+
 /*
  * nbuf_add_tag: add a tag to specified network buffer.
  *