summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorhsu <hsu@FreeBSD.org>2002-12-22 05:35:03 +0000
committerhsu <hsu@FreeBSD.org>2002-12-22 05:35:03 +0000
commit82e1e3bab0d3abe1018a0b56559c154485f2f676 (patch)
treed0f9ee7e6f9d8014e6f8f94ab6965e85c268792e /sys/net
parent2afef11c570b7b725c3145fc710f8dcd8d7ed4e0 (diff)
downloadFreeBSD-src-82e1e3bab0d3abe1018a0b56559c154485f2f676.zip
FreeBSD-src-82e1e3bab0d3abe1018a0b56559c154485f2f676.tar.gz
SMP locking for ifnet list.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bridge.c32
-rw-r--r--sys/net/if.c20
-rw-r--r--sys/net/if_ef.c5
-rw-r--r--sys/net/if_var.h7
-rw-r--r--sys/net/rtsock.c7
5 files changed, 58 insertions, 13 deletions
diff --git a/sys/net/bridge.c b/sys/net/bridge.c
index 295c208..13c36cd 100644
--- a/sys/net/bridge.c
+++ b/sys/net/bridge.c
@@ -302,6 +302,7 @@ bridge_off(void)
int i, s;
DEB(printf("bridge_off: n_clusters %d\n", n_clusters);)
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
struct bdg_softc *b;
@@ -322,6 +323,7 @@ bridge_off(void)
b->cluster = NULL;
bdg_stats.s[ifp->if_index].name[0] = '\0';
}
+ IFNET_RUNLOCK();
/* flush_tables */
s = splimp();
@@ -345,6 +347,7 @@ bridge_on(void)
struct ifnet *ifp ;
int s ;
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
struct bdg_softc *b = &ifp2sc[ifp->if_index];
@@ -370,6 +373,7 @@ bridge_on(void)
b->flags &= ~IFF_MUTE;
}
}
+ IFNET_RUNLOCK();
}
/**
@@ -435,6 +439,7 @@ parse_bdg_cfg()
/*
* now search in interface list for a matching name
*/
+ IFNET_RLOCK(); /* could sleep XXX */
TAILQ_FOREACH(ifp, &ifnet, if_link) {
char buf[IFNAMSIZ];
@@ -460,6 +465,7 @@ parse_bdg_cfg()
break ;
}
}
+ IFNET_RUNLOCK();
if (!found)
printf("interface %s Not found in bridge\n", beg);
*p = c;
@@ -847,17 +853,10 @@ bdg_forward(struct mbuf *m0, struct ifnet *dst)
printf("xx ouch, bdg_forward for local pkt\n");
return m0;
}
- if (dst == BDG_BCAST || dst == BDG_MCAST || dst == BDG_UNKNOWN) {
- ifp = TAILQ_FIRST(&ifnet) ; /* scan all ports */
- once = 0 ;
- if (dst != BDG_UNKNOWN) /* need a copy for the local stack */
- shared = 1 ;
- } else {
- ifp = dst ;
- once = 1 ;
+ if (dst == BDG_BCAST || dst == BDG_MCAST) {
+ /* need a copy for the local stack */
+ shared = 1 ;
}
- if ((uintptr_t)(ifp) <= (u_int)BDG_FORWARD)
- panic("bdg_forward: bad dst");
/*
* Do filtering in a very similar way to what is done in ip_output.
@@ -1023,6 +1022,17 @@ forward:
real_dst = src ;
last = NULL;
+ IFNET_RLOCK();
+ if (dst == BDG_BCAST || dst == BDG_MCAST || dst == BDG_UNKNOWN) {
+ ifp = TAILQ_FIRST(&ifnet) ; /* scan all ports */
+ once = 0 ;
+ } else {
+ ifp = dst ;
+ once = 1 ;
+ }
+ if ((uintptr_t)(ifp) <= (u_int)BDG_FORWARD)
+ panic("bdg_forward: bad dst");
+
for (;;) {
if (last) { /* need to forward packet leftover from previous loop */
struct mbuf *m ;
@@ -1032,6 +1042,7 @@ forward:
} else {
m = m_copypacket(m0, M_DONTWAIT);
if (m == NULL) {
+ IFNET_RUNLOCK();
printf("bdg_forward: sorry, m_copypacket failed!\n");
bdg_dropped++ ;
return m0 ; /* the original is still there... */
@@ -1062,6 +1073,7 @@ forward:
if (ifp == NULL)
once = 1 ;
}
+ IFNET_RUNLOCK();
DEB(bdg_fw_ticks += (u_long)(rdtsc() - ticks) ; bdg_fw_count++ ;
if (bdg_fw_count != 0) bdg_fw_avg = bdg_fw_ticks/bdg_fw_count; )
return m0 ;
diff --git a/sys/net/if.c b/sys/net/if.c
index 10c6c10..42f2590 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -102,6 +102,7 @@ int if_index = 0;
struct ifindex_entry *ifindex_table = NULL;
int ifqmaxlen = IFQ_MAXLEN;
struct ifnethead ifnet; /* depend on static init XXX */
+struct mtx ifnet_lock;
int if_cloners_count;
LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
@@ -263,6 +264,7 @@ if_init(dummy)
void *dummy;
{
+ IFNET_LOCK_INIT();
TAILQ_INIT(&ifnet);
SLIST_INIT(&ifklist);
if_grow(); /* create initial table */
@@ -295,6 +297,7 @@ if_check(dummy)
int s;
s = splimp();
+ IFNET_RLOCK(); /* could sleep on rare error; mostly okay XXX */
TAILQ_FOREACH(ifp, &ifnet, if_link) {
if (ifp->if_snd.ifq_maxlen == 0) {
printf("%s%d XXX: driver didn't set ifq_maxlen\n",
@@ -308,6 +311,7 @@ if_check(dummy)
MTX_NETWORK_LOCK, MTX_DEF);
}
}
+ IFNET_RUNLOCK();
splx(s);
if_slowtimo(0);
}
@@ -376,7 +380,9 @@ if_attach(ifp)
register struct sockaddr_dl *sdl;
register struct ifaddr *ifa;
+ IFNET_WLOCK();
TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
+ IFNET_WUNLOCK();
/*
* XXX -
* The old code would work if the interface passed a pre-existing
@@ -537,7 +543,9 @@ if_detach(ifp)
mac_destroy_ifnet(ifp);
#endif /* MAC */
KNOTE(&ifp->if_klist, NOTE_EXIT);
+ IFNET_WLOCK();
TAILQ_REMOVE(&ifnet, ifp, if_link);
+ IFNET_WUNLOCK();
mtx_destroy(&ifp->if_snd.ifq_mtx);
splx(s);
}
@@ -846,6 +854,7 @@ ifa_ifwithaddr(addr)
struct ifnet *ifp;
struct ifaddr *ifa;
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link)
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
@@ -861,6 +870,7 @@ ifa_ifwithaddr(addr)
}
ifa = NULL;
done:
+ IFNET_RUNLOCK();
return (ifa);
}
@@ -875,6 +885,7 @@ ifa_ifwithdstaddr(addr)
struct ifnet *ifp;
struct ifaddr *ifa;
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
continue;
@@ -887,6 +898,7 @@ ifa_ifwithdstaddr(addr)
}
ifa = NULL;
done:
+ IFNET_RUNLOCK();
return (ifa);
}
@@ -918,6 +930,7 @@ ifa_ifwithnet(addr)
* Scan though each interface, looking for ones that have
* addresses in this address family.
*/
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
register char *cp, *cp2, *cp3;
@@ -980,6 +993,7 @@ next: continue;
}
ifa = ifa_maybe;
done:
+ IFNET_RUNLOCK();
return (ifa);
}
@@ -1162,12 +1176,14 @@ if_slowtimo(arg)
register struct ifnet *ifp;
int s = splimp();
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
if (ifp->if_watchdog)
(*ifp->if_watchdog)(ifp);
}
+ IFNET_RUNLOCK();
splx(s);
timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
}
@@ -1192,6 +1208,7 @@ ifunit(const char *name)
* Devices should really be known as /dev/fooN, not /dev/net/fooN.
*/
snprintf(namebuf, IFNAMSIZ, "%s/%s", net_cdevsw.d_name, name);
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
dev = ifdev_byindex(ifp->if_index);
if (strcmp(devtoname(dev), namebuf) == 0)
@@ -1199,6 +1216,7 @@ ifunit(const char *name)
if (dev_named(dev, name))
break;
}
+ IFNET_RUNLOCK();
return (ifp);
}
@@ -1625,6 +1643,7 @@ ifconf(cmd, data)
int space = ifc->ifc_len, error = 0;
ifrp = ifc->ifc_req;
+ IFNET_RLOCK(); /* could sleep XXX */
TAILQ_FOREACH(ifp, &ifnet, if_link) {
char workbuf[64];
int ifnlen, addrs;
@@ -1695,6 +1714,7 @@ ifconf(cmd, data)
ifrp++;
}
}
+ IFNET_RUNLOCK();
ifc->ifc_len -= space;
return (error);
}
diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c
index d297faf..b064d38 100644
--- a/sys/net/if_ef.c
+++ b/sys/net/if_ef.c
@@ -163,8 +163,9 @@ ef_detach(struct efnet *sc)
}
}
}
-
+ IFNET_WLOCK();
TAILQ_REMOVE(&ifnet, ifp, if_link);
+ IFNET_WUNLOCK();
splx(s);
return 0;
}
@@ -508,6 +509,7 @@ ef_load(void)
struct ef_link *efl = NULL;
int error = 0, d;
+ IFNET_RLOCK();
TAILQ_FOREACH(ifp, &ifnet, if_link) {
if (ifp->if_type != IFT_ETHER) continue;
EFDEBUG("Found interface %s%d\n", ifp->if_name, ifp->if_unit);
@@ -538,6 +540,7 @@ ef_load(void)
efcount++;
SLIST_INSERT_HEAD(&efdev, efl, el_next);
}
+ IFNET_RUNLOCK();
if (error) {
if (efl)
SLIST_INSERT_HEAD(&efdev, efl, el_next);
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 3e3300e..fa4082b 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -410,6 +410,13 @@ struct ifmultiaddr {
IFA_UNLOCK(ifa); \
} while (0)
+extern struct mtx ifnet_lock;
+#define IFNET_LOCK_INIT() mtx_init(&ifnet_lock, "ifnet", NULL, MTX_DEF)
+#define IFNET_WLOCK() mtx_lock(&ifnet_lock)
+#define IFNET_WUNLOCK() mtx_unlock(&ifnet_lock)
+#define IFNET_RLOCK() IFNET_WLOCK()
+#define IFNET_RUNLOCK() IFNET_WUNLOCK()
+
struct ifindex_entry {
struct ifnet *ife_ifnet;
struct ifaddr *ife_ifnet_addr;
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index d8ec489..40f2ee1 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -414,11 +414,12 @@ route_output(m, so)
/* new gateway could require new ifaddr, ifp;
flags may also be different; ifp may be specified
by ll sockaddr when protocol address is ambiguous */
-#define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
+/* compare two sockaddr structures */
+#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
if ((rt->rt_flags & RTF_GATEWAY && gate != NULL) ||
ifpaddr != NULL ||
(ifaaddr != NULL &&
- !equal(ifaaddr, rt->rt_ifa->ifa_addr))) {
+ !sa_equal(ifaaddr, rt->rt_ifa->ifa_addr))) {
if ((error = rt_getifa(&info)) != 0)
senderr(error);
}
@@ -946,6 +947,7 @@ sysctl_iflist(af, w)
int len, error = 0;
bzero((caddr_t)&info, sizeof(info));
+ /* IFNET_RLOCK(); */ /* could sleep XXX */
TAILQ_FOREACH(ifp, &ifnet, if_link) {
if (w->w_arg && w->w_arg != ifp->if_index)
continue;
@@ -991,6 +993,7 @@ sysctl_iflist(af, w)
ifaaddr = netmask = brdaddr = 0;
}
done:
+ /* IFNET_RUNLOCK(); */ /* XXX */
return (error);
}
OpenPOWER on IntegriCloud