summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2016-12-19 08:36:51 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2016-12-19 08:36:51 +0000
commit347b9bada49618963c84880ec8c3c23c96aa0017 (patch)
treed431218ec3017a484e7de695c002a79a0e68cc86 /sys/net
parentc22be17b5bebb223df391aa82dfc7704004aafa7 (diff)
Introduce the NET_LOCK() a rwlock used to serialize accesses to the parts
of the network stack that are not yet ready to be executed in parallel or where new sleeping points are not possible. This first pass replace all the entry points leading to ip_output(). This is done to not introduce new sleeping points when trying to acquire ART's write lock, needed when a new L2 entry is created via the RT_RESOLVE. Inputs from and ok bluhm@, ok dlg@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c31
-rw-r--r--sys/net/if_spppsubr.c16
-rw-r--r--sys/net/raw_usrreq.c4
-rw-r--r--sys/net/route.c10
-rw-r--r--sys/net/rtsock.c4
5 files changed, 38 insertions, 27 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 5864e6bc3d3..1e103564710 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.465 2016/12/12 09:51:30 mpi Exp $ */
+/* $OpenBSD: if.c,v 1.466 2016/12/19 08:36:49 mpi Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -161,7 +161,7 @@ void if_netisr(void *);
void ifa_print_all(void);
#endif
-void if_start_locked(struct ifnet *ifp);
+void if_start_locked(struct ifnet *);
/*
* interface index map
@@ -229,6 +229,12 @@ struct taskq *softnettq;
struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
+
+/*
+ * Serialize socket operations to ensure no new sleeping points
+ * are introduced in IP output paths.
+ */
+struct rwlock netlock = RWLOCK_INITIALIZER("netlock");
/*
* Network interface utility routines.
*/
@@ -845,10 +851,15 @@ if_netisr(void *unused)
int s;
KERNEL_LOCK();
- s = splsoftnet();
+ NET_LOCK(s);
while ((n = netisr) != 0) {
- sched_pause();
+ /* Like sched_pause() but with a rwlock dance. */
+ if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD) {
+ NET_UNLOCK(s);
+ yield();
+ NET_LOCK(s);
+ }
atomic_clearbits_int(&netisr, n);
@@ -886,7 +897,7 @@ if_netisr(void *unused)
pfsyncintr();
#endif
- splx(s);
+ NET_UNLOCK(s);
KERNEL_UNLOCK();
}
@@ -1392,7 +1403,7 @@ if_downall(void)
struct ifnet *ifp;
int s;
- s = splnet();
+ NET_LOCK(s);
TAILQ_FOREACH(ifp, &ifnet, if_list) {
if ((ifp->if_flags & IFF_UP) == 0)
continue;
@@ -1405,7 +1416,7 @@ if_downall(void)
(caddr_t)&ifrq);
}
}
- splx(s);
+ NET_UNLOCK(s);
}
/*
@@ -1465,9 +1476,9 @@ if_linkstate_task(void *xifidx)
if (ifp == NULL)
return;
- s = splsoftnet();
+ NET_LOCK(s);
if_linkstate(ifp);
- splx(s);
+ NET_UNLOCK(s);
if_put(ifp);
}
@@ -1475,7 +1486,7 @@ if_linkstate_task(void *xifidx)
void
if_linkstate(struct ifnet *ifp)
{
- splsoftassert(IPL_SOFTNET);
+ NET_ASSERT_LOCKED();
rt_ifmsg(ifp);
#ifndef SMALL_KERNEL
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index b0046bffa40..06524edc001 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_spppsubr.c,v 1.156 2016/11/16 14:25:19 mpi Exp $ */
+/* $OpenBSD: if_spppsubr.c,v 1.157 2016/12/19 08:36:49 mpi Exp $ */
/*
* Synchronous PPP link level subroutines.
*
@@ -4193,7 +4193,7 @@ sppp_set_ip_addrs(void *arg1)
struct sockaddr_in *si;
struct sockaddr_in *dest;
int s;
-
+
sppp_get_ip_addrs(sp, &myaddr, &hisaddr, NULL);
if ((sp->ipcp.flags & IPCP_MYADDR_DYN) &&
(sp->ipcp.flags & IPCP_MYADDR_SEEN))
@@ -4202,8 +4202,8 @@ sppp_set_ip_addrs(void *arg1)
(sp->ipcp.flags & IPCP_HISADDR_SEEN))
hisaddr = sp->ipcp.req_hisaddr;
- s = splsoftnet();
+ NET_LOCK(s);
/*
* Pick the first AF_INET address from the list,
* aliases don't make any sense on a p2p link anyway.
@@ -4242,12 +4242,12 @@ sppp_set_ip_addrs(void *arg1)
if (debug && error) {
log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addrs: in_ifinit "
" failed, error=%d\n", SPP_ARGS(ifp), error);
- splx(s);
+ NET_UNLOCK(s);
return;
}
sppp_update_gw(ifp);
}
- splx(s);
+ NET_UNLOCK(s);
}
/*
@@ -4266,7 +4266,7 @@ sppp_clear_ip_addrs(void *arg1)
u_int32_t remote;
int s;
- s = splsoftnet();
+ NET_LOCK(s);
if (sp->ipcp.flags & IPCP_HISADDR_DYN)
remote = sp->ipcp.saved_hisaddr;
@@ -4303,12 +4303,12 @@ sppp_clear_ip_addrs(void *arg1)
if (debug && error) {
log(LOG_DEBUG, SPP_FMT "sppp_clear_ip_addrs: in_ifinit "
" failed, error=%d\n", SPP_ARGS(ifp), error);
- splx(s);
+ NET_UNLOCK(s);
return;
}
sppp_update_gw(ifp);
}
- splx(s);
+ NET_UNLOCK(s);
}
diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c
index 837c1f0901a..32047c97c65 100644
--- a/sys/net/raw_usrreq.c
+++ b/sys/net/raw_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_usrreq.c,v 1.26 2016/11/21 09:09:06 mpi Exp $ */
+/* $OpenBSD: raw_usrreq.c,v 1.27 2016/12/19 08:36:49 mpi Exp $ */
/* $NetBSD: raw_usrreq.c,v 1.11 1996/02/13 22:00:43 christos Exp $ */
/*
@@ -139,7 +139,7 @@ raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
int error = 0;
int len;
- splsoftassert(IPL_SOFTNET);
+ NET_ASSERT_LOCKED();
if (req == PRU_CONTROL)
return (EOPNOTSUPP);
diff --git a/sys/net/route.c b/sys/net/route.c
index fdbb8a1160b..58076e56182 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.344 2016/12/17 14:26:53 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.345 2016/12/19 08:36:49 mpi Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -552,7 +552,7 @@ rtredirect(struct sockaddr *dst, struct sockaddr *gateway,
int flags = RTF_GATEWAY|RTF_HOST;
uint8_t prio = RTP_NONE;
- splsoftassert(IPL_SOFTNET);
+ NET_ASSERT_LOCKED();
/* verify the gateway is directly reachable */
rt = rtalloc(gateway, 0, rdomain);
@@ -1501,7 +1501,7 @@ rt_timer_queue_destroy(struct rttimer_queue *rtq)
{
struct rttimer *r;
- splsoftassert(IPL_SOFTNET);
+ NET_ASSERT_LOCKED();
while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) {
LIST_REMOVE(r, rtt_link);
@@ -1595,7 +1595,7 @@ rt_timer_timer(void *arg)
current_time = time_uptime;
- s = splsoftnet();
+ NET_LOCK(s);
for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL;
rtq = LIST_NEXT(rtq, rtq_link)) {
while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL &&
@@ -1610,7 +1610,7 @@ rt_timer_timer(void *arg)
printf("rt_timer_timer: rtq_count reached 0\n");
}
}
- splx(s);
+ NET_UNLOCK(s);
timeout_add_sec(to, 1);
}
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index b6dc80aadde..92504f51f3d 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.210 2016/11/29 10:22:30 jsg Exp $ */
+/* $OpenBSD: rtsock.c,v 1.211 2016/12/19 08:36:49 mpi Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -152,7 +152,7 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
int af;
int error = 0;
- splsoftassert(IPL_SOFTNET);
+ NET_ASSERT_LOCKED();
rp = sotorawcb(so);