Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys fix: locking about IFQ_ENQUEUE and ALTQ
details: https://anonhg.NetBSD.org/src/rev/cb03c3802dbb
branches: trunk
changeset: 816214:cb03c3802dbb
user: knakahara <knakahara%NetBSD.org@localhost>
date: Wed Jun 22 10:44:31 2016 +0000
description:
fix: locking about IFQ_ENQUEUE and ALTQ
- If NET_MPSAFE is not defined, IFQ_LOCK is nop. Currently, that means
IFQ_ENQUEUE() of some paths such as bridge_enqueue() is called parallel
wrongly.
- If ALTQ is enabled, Tx processing should call if_transmit() (= IFQ_ENQUEUE
+ ifp->if_start()) instead of ifp->if_transmit() to call ALTQ_ENQUEUE()
and ALTQ_DEQUEUE().
Furthermore, ALTQ processing is always required KERNEL_LOCK currently.
diffstat:
sys/dev/usb/if_upl.c | 6 +++---
sys/net/if.c | 40 ++++++++++++++++++++++++++++++++++++----
sys/net/if.h | 4 ++--
sys/net/if_bridge.c | 6 +++---
sys/net/if_ieee1394subr.c | 6 +++---
sys/net/if_loop.c | 6 +++---
sys/net/if_vlan.c | 11 ++++++++---
sys/netipsec/ipsec_osdep.h | 4 ++--
8 files changed, 60 insertions(+), 23 deletions(-)
diffs (279 lines):
diff -r a60daf4c4cdf -r cb03c3802dbb sys/dev/usb/if_upl.c
--- a/sys/dev/usb/if_upl.c Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/dev/usb/if_upl.c Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_upl.c,v 1.54 2016/06/10 13:27:15 ozaki-r Exp $ */
+/* $NetBSD: if_upl.c,v 1.55 2016/06/22 10:44:31 knakahara Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.54 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.55 2016/06/22 10:44:31 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1003,7 +1003,7 @@
* Queue message on interface, and start output if interface
* not yet active.
*/
- error = (*ifp->if_transmit)(ifp, m);
+ error = if_transmit_lock(ifp, m);
return error;
}
diff -r a60daf4c4cdf -r cb03c3802dbb sys/net/if.c
--- a/sys/net/if.c Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/net/if.c Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.344 2016/06/21 10:25:27 ozaki-r Exp $ */
+/* $NetBSD: if.c,v 1.345 2016/06/22 10:44:32 knakahara Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.344 2016/06/21 10:25:27 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.345 2016/06/22 10:44:32 knakahara Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -199,6 +199,7 @@
static void if_free_sadl(struct ifnet *);
static void if_attachdomain1(struct ifnet *);
static int ifconf(u_long, void *);
+static int if_transmit(struct ifnet *, struct mbuf *);
static int if_clone_create(const char *);
static int if_clone_destroy(const char *);
static void if_link_state_change_si(void *);
@@ -2773,14 +2774,24 @@
/*
* wrapper function for the drivers which doesn't have if_transmit().
*/
-int
+static int
if_transmit(struct ifnet *ifp, struct mbuf *m)
{
int s, error;
s = splnet();
+ /*
+ * If NET_MPSAFE is not defined , IFQ_LOCK() is nop.
+ * use KERNEL_LOCK instead of ifq_lock.
+ */
+#ifndef NET_MPSAFE
+ KERNEL_LOCK(1, NULL);
+#endif
IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#ifndef NET_MPSAFE
+ KERNEL_UNLOCK_ONE(NULL);
+#endif
if (error != 0) {
/* mbuf is already freed */
goto out;
@@ -2798,6 +2809,27 @@
return error;
}
+int
+if_transmit_lock(struct ifnet *ifp, struct mbuf *m)
+{
+ int error;
+
+#ifdef ALTQ
+ KERNEL_LOCK(1, NULL);
+ if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
+ error = if_transmit(ifp, m);
+ KERNEL_UNLOCK_ONE(NULL);
+ } else {
+ KERNEL_UNLOCK_ONE(NULL);
+ error = (*ifp->if_transmit)(ifp, m);
+ }
+#else /* !ALTQ */
+ error = (*ifp->if_transmit)(ifp, m);
+#endif /* !ALTQ */
+
+ return error;
+}
+
/*
* Queue message on interface, and start output if interface
* not yet active.
@@ -2806,7 +2838,7 @@
ifq_enqueue(struct ifnet *ifp, struct mbuf *m)
{
- return (*ifp->if_transmit)(ifp, m);
+ return if_transmit_lock(ifp, m);
}
/*
diff -r a60daf4c4cdf -r cb03c3802dbb sys/net/if.h
--- a/sys/net/if.h Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/net/if.h Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.214 2016/06/21 10:25:27 ozaki-r Exp $ */
+/* $NetBSD: if.h,v 1.215 2016/06/22 10:44:32 knakahara Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -992,7 +992,7 @@
void if_clone_attach(struct if_clone *);
void if_clone_detach(struct if_clone *);
-int if_transmit(struct ifnet *, struct mbuf *);
+int if_transmit_lock(struct ifnet *, struct mbuf *);
int ifq_enqueue(struct ifnet *, struct mbuf *);
int ifq_enqueue2(struct ifnet *, struct ifqueue *, struct mbuf *);
diff -r a60daf4c4cdf -r cb03c3802dbb sys/net/if_bridge.c
--- a/sys/net/if_bridge.c Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/net/if_bridge.c Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bridge.c,v 1.128 2016/06/20 08:14:41 knakahara Exp $ */
+/* $NetBSD: if_bridge.c,v 1.129 2016/06/22 10:44:32 knakahara Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.128 2016/06/20 08:14:41 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.129 2016/06/22 10:44:32 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_bridge_ipf.h"
@@ -1396,7 +1396,7 @@
len = m->m_pkthdr.len;
mflags = m->m_flags;
- error = (*dst_ifp->if_transmit)(dst_ifp, m);
+ error = if_transmit_lock(dst_ifp, m);
if (error) {
/* mbuf is already freed */
sc->sc_if.if_oerrors++;
diff -r a60daf4c4cdf -r cb03c3802dbb sys/net/if_ieee1394subr.c
--- a/sys/net/if_ieee1394subr.c Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/net/if_ieee1394subr.c Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ieee1394subr.c,v 1.55 2016/04/28 01:37:17 knakahara Exp $ */
+/* $NetBSD: if_ieee1394subr.c,v 1.56 2016/06/22 10:44:32 knakahara Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ieee1394subr.c,v 1.55 2016/04/28 01:37:17 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ieee1394subr.c,v 1.56 2016/06/22 10:44:32 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -221,7 +221,7 @@
while ((m = m0) != NULL) {
m0 = m->m_nextpkt;
- error = (*ifp->if_transmit)(ifp, m);
+ error = if_transmit_lock(ifp, m);
if (error) {
/* mbuf is already freed */
goto bad;
diff -r a60daf4c4cdf -r cb03c3802dbb sys/net/if_loop.c
--- a/sys/net/if_loop.c Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/net/if_loop.c Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_loop.c,v 1.88 2016/06/20 06:52:44 knakahara Exp $ */
+/* $NetBSD: if_loop.c,v 1.89 2016/06/22 10:44:32 knakahara Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.88 2016/06/20 06:52:44 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.89 2016/06/22 10:44:32 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -256,7 +256,7 @@
}
*(mtod(m, uint32_t *)) = dst->sa_family;
- error = ifp->if_transmit(ifp, m);
+ error = if_transmit_lock(ifp, m);
goto out;
}
#endif /* ALTQ */
diff -r a60daf4c4cdf -r cb03c3802dbb sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/net/if_vlan.c Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vlan.c,v 1.89 2016/06/10 13:27:16 ozaki-r Exp $ */
+/* $NetBSD: if_vlan.c,v 1.90 2016/06/22 10:44:32 knakahara Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.89 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.90 2016/06/22 10:44:32 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -700,6 +700,10 @@
#ifdef ALTQ
/*
+ * KERNEL_LOCK is required for ALTQ even if NET_MPSAFE if defined.
+ */
+ KERNEL_LOCK(1, NULL);
+ /*
* If ALTQ is enabled on the parent interface, do
* classification; the queueing discipline might
* not require classification, but might require
@@ -716,6 +720,7 @@
#endif
}
}
+ KERNEL_UNLOCK_ONE(NULL);
#endif /* ALTQ */
bpf_mtap(ifp, m);
@@ -808,7 +813,7 @@
* would have. We are already running at splnet.
*/
if ((p->if_flags & IFF_RUNNING) != 0) {
- error = (*p->if_transmit)(p, m);
+ error = if_transmit_lock(p, m);
if (error) {
/* mbuf is already freed */
ifp->if_oerrors++;
diff -r a60daf4c4cdf -r cb03c3802dbb sys/netipsec/ipsec_osdep.h
--- a/sys/netipsec/ipsec_osdep.h Wed Jun 22 07:48:17 2016 +0000
+++ b/sys/netipsec/ipsec_osdep.h Wed Jun 22 10:44:31 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_osdep.h,v 1.25 2016/04/28 01:37:17 knakahara Exp $ */
+/* $NetBSD: ipsec_osdep.h,v 1.26 2016/06/22 10:44:32 knakahara Exp $ */
/* $FreeBSD: /repoman/r/ncvs/src/sys/netipsec/ipsec_osdep.h,v 1.1 2003/09/29 22:47:45 sam Exp $ */
/*
@@ -152,7 +152,7 @@
return (0);
}
if (ifp != NULL)
- (void)(*ifp->if_transmit)(ifp, m);
+ (void)if_transmit_lock(ifp, m);
KERNEL_UNLOCK_ONE(NULL);
splx(s);
Home |
Main Index |
Thread Index |
Old Index