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