Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net/npf npf_rwrcksum: handle delayed checksums in the ne...
details: https://anonhg.NetBSD.org/src/rev/a3854e7a03a9
branches: trunk
changeset: 783179:a3854e7a03a9
user: rmind <rmind%NetBSD.org@localhost>
date: Mon Dec 10 01:11:13 2012 +0000
description:
npf_rwrcksum: handle delayed checksums in the network stack; also fix
non-NPF_NAT_PORTS case and add some comments. PR/47235.
diffstat:
sys/net/npf/npf.h | 3 +-
sys/net/npf/npf_inet.c | 61 +++++++++++++++++++++++++++++++------------------
sys/net/npf/npf_mbuf.c | 15 ++++++++++-
3 files changed, 53 insertions(+), 26 deletions(-)
diffs (173 lines):
diff -r ffee8641dc01 -r a3854e7a03a9 sys/net/npf/npf.h
--- a/sys/net/npf/npf.h Mon Dec 10 00:34:56 2012 +0000
+++ b/sys/net/npf/npf.h Mon Dec 10 01:11:13 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: npf.h,v 1.22 2012/10/29 02:27:11 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.23 2012/12/10 01:11:13 rmind Exp $ */
/*-
* Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -146,6 +146,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 **);
diff -r ffee8641dc01 -r a3854e7a03a9 sys/net/npf/npf_inet.c
--- a/sys/net/npf/npf_inet.c Mon Dec 10 00:34:56 2012 +0000
+++ b/sys/net/npf/npf_inet.c Mon Dec 10 01:11:13 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_inet.c,v 1.17 2012/09/16 13:47:41 rmind Exp $ */
+/* $NetBSD: npf_inet.c,v 1.18 2012/12/10 01:11:13 rmind 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.17 2012/09/16 13:47:41 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.18 2012/12/10 01:11:13 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -597,65 +597,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;
}
diff -r ffee8641dc01 -r a3854e7a03a9 sys/net/npf/npf_mbuf.c
--- a/sys/net/npf/npf_mbuf.c Mon Dec 10 00:34:56 2012 +0000
+++ b/sys/net/npf/npf_mbuf.c Mon Dec 10 01:11:13 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_mbuf.c,v 1.7 2012/04/14 19:01:21 rmind Exp $ */
+/* $NetBSD: npf_mbuf.c,v 1.8 2012/12/10 01:11:13 rmind 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.7 2012/04/14 19:01:21 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.8 2012/12/10 01:11:13 rmind 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.
*
Home |
Main Index |
Thread Index |
Old Index