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/a2eb3a365374
branches: trunk
changeset: 351092:a2eb3a365374
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 2c46ae4fed8f -r a2eb3a365374 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 2c46ae4fed8f -r a2eb3a365374 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 2c46ae4fed8f -r a2eb3a365374 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 2c46ae4fed8f -r a2eb3a365374 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