The current goal of the Network SMP effort is to have a single CPU
process the IP forwarding path in a process context without holding
the KERNEL_LOCK(). To achieve this goal we're progressively moving
code from the softnet interrupt context to the if_input_task. In
the end we'll completely get rid of this soft-interrupt.
So now would be a good time to know if moving all the code currently
run in a soft-interrupt context to a task uncovers any bug. I'm
happily running the diff below on amd64 and macppc, it even gives me
a small performance boost.
I'd appreciate more tests especially on exotic archs.
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.429
diff -u -p -r1.429 if.c
--- net/if.c 16 Mar 2016 12:08:09 -0000 1.429
+++ net/if.c 18 Apr 2016 08:00:08 -0000
@@ -64,9 +64,12 @@
#include "bpfilter.h"
#include "bridge.h"
#include "carp.h"
+#include "ether.h"
#include "pf.h"
+#include "pfsync.h"
+#include "ppp.h"
+#include "pppoe.h"
#include "trunk.h"
-#include "ether.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -148,6 +151,7 @@ int if_group_egress_build(void);
void if_watchdog_task(void *);
void if_input_process(void *);
+void if_netisr(void *);
#ifdef DDB
void ifa_print_all(void);
@@ -216,13 +220,15 @@ void net_tick(void *);
int net_livelocked(void);
int ifq_congestion;
-struct taskq *softnettq;
+int netisr;
+struct taskq *softnettq;
+
+struct mbuf_queue if_input_queue = MBUF_QUEUE_INITIALIZER(8192, IPL_NET);
+struct task if_input_task = TASK_INITIALIZER(if_input_process,
&if_input_queue);
+struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
/*
* Network interface utility routines.
- *
- * Routines with ifa_ifwith* names take sockaddr *'s as
- * parameters.
*/
void
ifinit(void)
@@ -590,9 +596,6 @@ if_enqueue(struct ifnet *ifp, struct mbu
return (0);
}
-struct mbuf_queue if_input_queue = MBUF_QUEUE_INITIALIZER(8192, IPL_NET);
-struct task if_input_task = TASK_INITIALIZER(if_input_process,
&if_input_queue);
-
void
if_input(struct ifnet *ifp, struct mbuf_list *ml)
{
@@ -803,6 +806,50 @@ if_input_process(void *xmq)
if_put(ifp);
}
splx(s);
+}
+
+void
+if_netisr(void *unused)
+{
+ int n, t = 0;
+ int s;
+
+ KERNEL_LOCK();
+ s = splsoftnet();
+
+ while ((n = netisr) != 0) {
+ sched_pause();
+
+ atomic_clearbits_int(&netisr, n);
+
+ if (n & (1 << NETISR_IP))
+ ipintr();
+#ifdef INET6
+ if (n & (1 << NETISR_IPV6))
+ ip6intr();
+#endif
+#if NPPP > 0
+ if (n & (1 << NETISR_PPP))
+ pppintr();
+#endif
+#if NBRIDGE > 0
+ if (n & (1 << NETISR_BRIDGE))
+ bridgeintr();
+#endif
+#if NPPPOE > 0
+ if (n & (1 << NETISR_PPPOE))
+ pppoeintr();
+#endif
+ t |= n;
+ }
+
+#if NPFSYNC > 0
+ if (t & (1 << NETISR_PFSYNC))
+ pfsyncintr();
+#endif
+
+ splx(s);
+ KERNEL_UNLOCK();
}
void
Index: net/netisr.c
===================================================================
RCS file: net/netisr.c
diff -N net/netisr.c
--- net/netisr.c 8 Jan 2016 13:53:24 -0000 1.10
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2010 Owain G. Ainsworth <[email protected]>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <net/netisr.h>
-
-#include <machine/intr.h>
-
-#include "ppp.h"
-#include "bridge.h"
-#include "pppoe.h"
-#include "pfsync.h"
-
-void netintr(void *);
-
-int netisr;
-void *netisr_intr;
-
-void
-netintr(void *unused)
-{
- int n, t = 0;
-
- while ((n = netisr) != 0) {
- atomic_clearbits_int(&netisr, n);
-
- if (n & (1 << NETISR_IP))
- ipintr();
-#ifdef INET6
- if (n & (1 << NETISR_IPV6))
- ip6intr();
-#endif
-#if NPPP > 0
- if (n & (1 << NETISR_PPP))
- pppintr();
-#endif
-#if NBRIDGE > 0
- if (n & (1 << NETISR_BRIDGE))
- bridgeintr();
-#endif
-#if NPPPOE > 0
- if (n & (1 << NETISR_PPPOE))
- pppoeintr();
-#endif
- t |= n;
- }
-
-#if NPFSYNC > 0
- if (t & (1 << NETISR_PFSYNC))
- pfsyncintr();
-#endif
-}
-
-void
-netisr_init(void)
-{
- netisr_intr = softintr_establish(IPL_SOFTNET, netintr, NULL);
- if (netisr_intr == NULL)
- panic("can't establish softnet handler");
-}
Index: net/netisr.h
===================================================================
RCS file: /cvs/src/sys/net/netisr.h,v
retrieving revision 1.44
diff -u -p -r1.44 netisr.h
--- net/netisr.h 8 Jan 2016 13:53:24 -0000 1.44
+++ net/netisr.h 18 Apr 2016 07:52:28 -0000
@@ -61,7 +61,12 @@
#ifndef _LOCORE
#ifdef _KERNEL
+
+#include <sys/task.h>
+#include <sys/atomic.h>
+
extern int netisr; /* scheduling bits for network */
+extern struct task if_input_task_locked;
void ipintr(void);
void ip6intr(void);
@@ -70,16 +75,11 @@ void bridgeintr(void);
void pppoeintr(void);
void pfsyncintr(void);
-#include <machine/atomic.h>
-
-extern void *netisr_intr;
#define schednetisr(anisr)
\
do { \
atomic_setbits_int(&netisr, (1 << (anisr))); \
- softintr_schedule(netisr_intr); \
+ task_add(softnettq, &if_input_task_locked); \
} while (/* CONSTCOND */0)
-
-void netisr_init(void);
#endif /* _KERNEL */
#endif /*_LOCORE */
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.249
diff -u -p -r1.249 init_main.c
--- kern/init_main.c 19 Mar 2016 12:04:15 -0000 1.249
+++ kern/init_main.c 18 Apr 2016 07:48:40 -0000
@@ -394,7 +394,6 @@ main(void *framep)
* until everything is ready.
*/
s = splnet();
- netisr_init();
domaininit();
splx(s);