Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Defer some pr_input to workqueue



details:   https://anonhg.NetBSD.org/src/rev/2609444f5546
branches:  trunk
changeset: 821343:2609444f5546
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Thu Feb 02 02:52:10 2017 +0000

description:
Defer some pr_input to workqueue

pr_input is currently called in softint. Some pr_input such as ICMP, ICMPv6
and CARP can add/delete/update IP addresses and routing table entries. For
example, icmp6_redirect_input updates an a routing table entry and
nd6_ra_input may delete an IP address.

Basically such operations shouldn't be done in softint. That aside, we have
a reason to avoid the situation; psz/psref waits cannot be used in softint,
however they are required to work in such pr_input in the MP-safe world.

The change implements the workqueue pr_input framework called wqinput which
provides a means to defer pr_input of a protocol to workqueue easily.
Currently icmp_input, icmp6_input, carp_proto_input and carp6_proto_input
are deferred to workqueue by the framework.

Proposed and discussed on tech-kern and tech-net

diffstat:

 sys/net/files.net                         |    3 +-
 sys/netinet/ip_carp.c                     |   65 +++++--
 sys/netinet/ip_icmp.c                     |   36 ++-
 sys/netinet/wqinput.c                     |  267 ++++++++++++++++++++++++++++++
 sys/netinet/wqinput.h                     |   42 ++++
 sys/netinet6/icmp6.c                      |   30 ++-
 sys/rump/librump/rumpnet/Makefile.rumpnet |    5 +-
 7 files changed, 406 insertions(+), 42 deletions(-)

diffs (truncated from 703 to 300 lines):

diff -r fd82f215a629 -r 2609444f5546 sys/net/files.net
--- a/sys/net/files.net Wed Feb 01 21:59:09 2017 +0000
+++ b/sys/net/files.net Thu Feb 02 02:52:10 2017 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.net,v 1.11 2016/09/16 03:10:45 pgoyette Exp $
+#      $NetBSD: files.net,v 1.12 2017/02/02 02:52:10 ozaki-r Exp $
 
 # XXX CLEANUP
 define net
@@ -62,6 +62,7 @@
 file   netinet/ip_ecn.c                ipsec | gif | stf
 file   netinet/ip_encap.c              inet | inet6
 file   netinet/ip_etherip.c            etherip & inet
+file   netinet/wqinput.c               inet | inet6
 file   netinet6/ip6_etherip.c          etherip & inet6
 file   netinet6/in6_gif.c              gif & inet6
 
diff -r fd82f215a629 -r 2609444f5546 sys/netinet/ip_carp.c
--- a/sys/netinet/ip_carp.c     Wed Feb 01 21:59:09 2017 +0000
+++ b/sys/netinet/ip_carp.c     Thu Feb 02 02:52:10 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_carp.c,v 1.83 2017/01/16 15:44:47 christos Exp $    */
+/*     $NetBSD: ip_carp.c,v 1.84 2017/02/02 02:52:10 ozaki-r Exp $     */
 /*     $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $   */
 
 /*
@@ -33,7 +33,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.83 2017/01/16 15:44:47 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.84 2017/02/02 02:52:10 ozaki-r Exp $");
 
 /*
  * TODO:
@@ -70,6 +70,7 @@
 #include <net/netisr.h>
 #include <net/net_stats.h>
 #include <netinet/if_inarp.h>
+#include <netinet/wqinput.h>
 
 #if NFDDI > 0
 #include <net/if_fddi.h>
@@ -234,6 +235,14 @@
 
 static void    sysctl_net_inet_carp_setup(struct sysctllog **);
 
+/* workqueue-based pr_input */
+static struct wqinput *carp_wqinput;
+static void _carp_proto_input(struct mbuf *, int, int);
+#ifdef INET6
+static struct wqinput *carp6_wqinput;
+static void _carp6_proto_input(struct mbuf *, int, int);
+#endif
+
 struct if_clone carp_cloner =
     IF_CLONE_INITIALIZER("carp", carp_clone_create, carp_clone_destroy);
 
@@ -468,19 +477,15 @@
  * we have rearranged checks order compared to the rfc,
  * but it seems more efficient this way or not possible otherwise.
  */
-void
-carp_proto_input(struct mbuf *m, ...)
+static void
+_carp_proto_input(struct mbuf *m, int hlen, int proto)
 {
        struct ip *ip = mtod(m, struct ip *);
        struct carp_softc *sc = NULL;
        struct carp_header *ch;
        int iplen, len;
-       va_list ap;
        struct ifnet *rcvif;
 
-       va_start(ap, m);
-       va_end(ap);
-
        CARP_STATINC(CARP_STAT_IPACKETS);
        MCLAIM(m, &carp_proto_mowner_rx);
 
@@ -542,11 +547,17 @@
        carp_proto_input_c(m, ch, AF_INET);
 }
 
+void
+carp_proto_input(struct mbuf *m, ...)
+{
+
+       wqinput_input(carp_wqinput, m, 0, 0);
+}
+
 #ifdef INET6
-int
-carp6_proto_input(struct mbuf **mp, int *offp, int proto)
+static void
+_carp6_proto_input(struct mbuf *m, int off, int proto)
 {
-       struct mbuf *m = *mp;
        struct carp_softc *sc = NULL;
        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
        struct carp_header *ch;
@@ -558,7 +569,7 @@
 
        if (!carp_opts[CARPCTL_ALLOW]) {
                m_freem(m);
-               return (IPPROTO_DONE);
+               return;
        }
 
        rcvif = m_get_rcvif_NOMPSAFE(m);
@@ -569,7 +580,7 @@
                CARP_LOG(sc, ("packet received on non-carp interface: %s",
                    rcvif->if_xname));
                m_freem(m);
-               return (IPPROTO_DONE);
+               return;
        }
 
        /* verify that the IP TTL is 255 */
@@ -578,31 +589,40 @@
                CARP_LOG(sc, ("received ttl %d != %d on %s", ip6->ip6_hlim,
                    CARP_DFLTTL, rcvif->if_xname));
                m_freem(m);
-               return (IPPROTO_DONE);
+               return;
        }
 
        /* verify that we have a complete carp packet */
        len = m->m_len;
-       IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch));
+       IP6_EXTHDR_GET(ch, struct carp_header *, m, off, sizeof(*ch));
        if (ch == NULL) {
                CARP_STATINC(CARP_STAT_BADLEN);
                CARP_LOG(sc, ("packet size %u too small", len));
-               return (IPPROTO_DONE);
+               return;
        }
 
 
        /* verify the CARP checksum */
-       m->m_data += *offp;
+       m->m_data += off;
        if (carp_cksum(m, sizeof(*ch))) {
                CARP_STATINC(CARP_STAT_BADSUM);
                CARP_LOG(sc, ("checksum failed, on %s", rcvif->if_xname));
                m_freem(m);
-               return (IPPROTO_DONE);
+               return;
        }
-       m->m_data -= *offp;
+       m->m_data -= off;
 
        carp_proto_input_c(m, ch, AF_INET6);
-       return (IPPROTO_DONE);
+       return;
+}
+
+int
+carp6_proto_input(struct mbuf **mp, int *offp, int proto)
+{
+
+       wqinput_input(carp6_wqinput, *mp, *offp, proto);
+
+       return IPPROTO_DONE;
 }
 #endif /* INET6 */
 
@@ -2342,6 +2362,11 @@
        MOWNER_ATTACH(&carp_proto6_mowner_rx);
        MOWNER_ATTACH(&carp_proto6_mowner_tx);
 #endif
+
+       carp_wqinput = wqinput_create("carp", _carp_proto_input);
+#ifdef INET6
+       carp6_wqinput = wqinput_create("carp6", _carp6_proto_input);
+#endif
 }
 
 static void
diff -r fd82f215a629 -r 2609444f5546 sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c     Wed Feb 01 21:59:09 2017 +0000
+++ b/sys/netinet/ip_icmp.c     Thu Feb 02 02:52:10 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_icmp.c,v 1.155 2017/01/24 07:09:24 ozaki-r Exp $    */
+/*     $NetBSD: ip_icmp.c,v 1.156 2017/02/02 02:52:10 ozaki-r Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -94,7 +94,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.155 2017/01/24 07:09:24 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.156 2017/02/02 02:52:10 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ipsec.h"
@@ -125,6 +125,7 @@
 #include <netinet/in_proto.h>
 #include <netinet/icmp_var.h>
 #include <netinet/icmp_private.h>
+#include <netinet/wqinput.h>
 
 #ifdef IPSEC
 #include <netipsec/ipsec.h>
@@ -175,6 +176,10 @@
 
 static void sysctl_netinet_icmp_setup(struct sysctllog **);
 
+/* workqueue-based pr_input */
+static struct wqinput *icmp_wqinput;
+static void _icmp_input(struct mbuf *, int, int);
+
 void
 icmp_init(void)
 {
@@ -191,6 +196,7 @@
        }
 
        icmpstat_percpu = percpu_alloc(sizeof(uint64_t) * ICMP_NSTATS);
+       icmp_wqinput = wqinput_create("icmp", _icmp_input);
 }
 
 /*
@@ -384,10 +390,9 @@
 /*
  * Process a received ICMP message.
  */
-void
-icmp_input(struct mbuf *m, ...)
+static void
+_icmp_input(struct mbuf *m, int hlen, int proto)
 {
-       int proto;
        struct icmp *icp;
        struct ip *ip = mtod(m, struct ip *);
        int icmplen;
@@ -395,15 +400,8 @@
        struct in_ifaddr *ia;
        void *(*ctlfunc)(int, const struct sockaddr *, void *);
        int code;
-       int hlen;
-       va_list ap;
        struct rtentry *rt;
 
-       va_start(ap, m);
-       hlen = va_arg(ap, int);
-       proto = va_arg(ap, int);
-       va_end(ap);
-
        /*
         * Locate icmp structure in mbuf, and check
         * that not corrupted and of at least minimum length.
@@ -685,6 +683,20 @@
        return;
 }
 
+void
+icmp_input(struct mbuf *m, ...)
+{
+       int hlen, proto;
+       va_list ap;
+
+       va_start(ap, m);
+       hlen = va_arg(ap, int);
+       proto = va_arg(ap, int);
+       va_end(ap);
+
+       wqinput_input(icmp_wqinput, m, hlen, proto);
+}
+
 /*
  * Reflect the ip packet back to the source
  */
diff -r fd82f215a629 -r 2609444f5546 sys/netinet/wqinput.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/netinet/wqinput.c     Thu Feb 02 02:52:10 2017 +0000
@@ -0,0 +1,267 @@
+/*     $NetBSD: wqinput.c,v 1.1 2017/02/02 02:52:10 ozaki-r Exp $      */
+
+/*-
+ * Copyright (c) 2017 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS



Home | Main Index | Thread Index | Old Index