PERFORCE change 37246 for review

Sam Leffler sam at FreeBSD.org
Sat Aug 30 14:57:16 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=37246

Change 37246 by sam at sam_ebb on 2003/08/30 14:56:51

	checkpoint locking: untested

Affected files ...

.. //depot/projects/netperf/sys/net/if_vlan.c#2 edit

Differences ...

==== //depot/projects/netperf/sys/net/if_vlan.c#2 (text+ko) ====

@@ -104,6 +104,18 @@
 static MALLOC_DEFINE(M_VLAN, "vlan", "802.1Q Virtual LAN Interface");
 static LIST_HEAD(, ifvlan) ifv_list;
 
+/*
+ * Locking: one lock is used to guard both the ifv_list and modification
+ * to vlan data structures.  We are rather conservative here; probably
+ * more than necessary.
+ */
+static struct mtx ifv_mtx;
+#define	VLAN_LOCK_INIT()	mtx_init(&ifv_mtx, "vlan", NULL, MTX_DEF)
+#define	VLAN_LOCK_DESTROY()	mtx_destroy(&ifv_mtx)
+#define	VLAN_LOCK_ASSERT()	mtx_assert(&ifv_mtx, MA_OWNED)
+#define	VLAN_LOCK()	mtx_lock(&ifv_mtx)
+#define	VLAN_UNLOCK()	mtx_lock(&ifv_mtx)
+
 static	int vlan_clone_create(struct if_clone *, int);
 static	void vlan_clone_destroy(struct ifnet *);
 static	void vlan_start(struct ifnet *ifp);
@@ -135,6 +147,8 @@
 	struct sockaddr_dl	sdl;
 	int			error;
 
+	VLAN_LOCK_ASSERT();
+
 	/* Find the parent. */
 	sc = ifp->if_softc;
 	ifp_p = sc->ifv_p;
@@ -204,6 +218,7 @@
 	switch (type) { 
 	case MOD_LOAD: 
 		LIST_INIT(&ifv_list);
+		VLAN_LOCK_INIT();
 		vlan_input_p = vlan_input;
 		if_clone_attach(&vlan_cloner);
 		break; 
@@ -212,6 +227,7 @@
 		vlan_input_p = NULL;
 		while (!LIST_EMPTY(&ifv_list))
 			vlan_clone_destroy(&LIST_FIRST(&ifv_list)->ifv_if);
+		VLAN_LOCK_DESTROY();
 		break;
 	} 
 	return 0; 
@@ -230,16 +246,11 @@
 {
 	struct ifvlan *ifv;
 	struct ifnet *ifp;
-	int s;
 
 	ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO);
 	ifp = &ifv->ifv_if;
 	SLIST_INIT(&ifv->vlan_mc_listhead);
 
-	s = splnet();
-	LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list);
-	splx(s);
-
 	ifp->if_softc = ifv;
 	ifp->if_name = "vlan";
 	ifp->if_unit = unit;
@@ -258,6 +269,10 @@
 	ifp->if_type = IFT_L2VLAN;
 	ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN;
 
+	VLAN_LOCK();
+	LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list);
+	VLAN_UNLOCK();
+
 	return (0);
 }
 
@@ -265,12 +280,11 @@
 vlan_clone_destroy(struct ifnet *ifp)
 {
 	struct ifvlan *ifv = ifp->if_softc;
-	int s;
 
-	s = splnet();
+	VLAN_LOCK();
 	LIST_REMOVE(ifv, ifv_list);
 	vlan_unconfig(ifp);
-	splx(s);
+	VLAN_UNLOCK();
 
 	ether_ifdetach(ifp);
 
@@ -427,16 +441,18 @@
 		}
 	}
 
-	for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
-	    ifv = LIST_NEXT(ifv, ifv_list))
+	VLAN_LOCK();
+	LIST_FOREACH(ifv, &ifv_list, ifv_list)
 		if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
 			break;
 
 	if (ifv == NULL || (ifv->ifv_if.if_flags & IFF_UP) == 0) {
+		VLAN_UNLOCK();
 		m_freem(m);
 		ifp->if_noproto++;
 		return;	
 	}
+	VLAN_UNLOCK();		/* XXX extend below? */
 
 	if (mtag == NULL) {
 		/*
@@ -463,6 +479,8 @@
 	struct ifaddr *ifa1, *ifa2;
 	struct sockaddr_dl *sdl1, *sdl2;
 
+	VLAN_LOCK_ASSERT();
+
 	if (p->if_data.ifi_type != IFT_ETHER)
 		return EPROTONOSUPPORT;
 	if (ifv->ifv_p)
@@ -558,6 +576,8 @@
 	struct ifnet *p;
 	int error;
 
+	VLAN_LOCK_ASSERT();
+
 	ifv = ifp->if_softc;
 	p = ifv->ifv_p;
 
@@ -623,6 +643,8 @@
 	struct ifvlan *ifv = ifp->if_softc;
 	int error = 0;
 
+	VLAN_LOCK_ASSERT();
+
 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
 		if ((ifv->ifv_flags & IFVF_PROMISC) == 0) {
 			error = ifpromisc(ifv->ifv_p, 1);
@@ -680,8 +702,11 @@
 		break;
 
 	case SIOCGIFMEDIA:
+		VLAN_LOCK();
 		if (ifv->ifv_p != NULL) {
-			error = (ifv->ifv_p->if_ioctl)(ifv->ifv_p, SIOCGIFMEDIA, data);
+			error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p,
+					SIOCGIFMEDIA, data);
+			VLAN_UNLOCK();
 			/* Limit the result to the parent's current config. */
 			if (error == 0) {
 				struct ifmediareq *ifmr;
@@ -694,8 +719,10 @@
 						sizeof(int));
 				}
 			}
-		} else
+		} else {
+			VLAN_UNLOCK();
 			error = EINVAL;
+		}
 		break;
 
 	case SIOCSIFMEDIA:
@@ -706,6 +733,7 @@
 		/*
 		 * Set the interface MTU.
 		 */
+		VLAN_LOCK();
 		if (ifv->ifv_p != NULL) {
 			if (ifr->ifr_mtu >
 			     (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) ||
@@ -716,6 +744,7 @@
 				ifp->if_mtu = ifr->ifr_mtu;
 		} else
 			error = EINVAL;
+		VLAN_UNLOCK();
 		break;
 
 	case SIOCSETVLAN:
@@ -723,12 +752,11 @@
 		if (error)
 			break;
 		if (vlr.vlr_parent[0] == '\0') {
+			VLAN_LOCK();
 			vlan_unconfig(ifp);
-			if (ifp->if_flags & IFF_UP) {
-				int s = splimp();
+			VLAN_UNLOCK();
+			if (ifp->if_flags & IFF_UP)
 				if_down(ifp);
-				splx(s);
-			}		
 			ifp->if_flags &= ~IFF_RUNNING;
 			break;
 		}
@@ -745,23 +773,29 @@
 			error = EINVAL;
 			break;
 		}
+		VLAN_LOCK();
 		error = vlan_config(ifv, p);
-		if (error)
+		if (error) {
+			VLAN_UNLOCK();
 			break;
+		}
 		ifv->ifv_tag = vlr.vlr_tag;
 		ifp->if_flags |= IFF_RUNNING;
 
 		/* Update promiscuous mode, if necessary. */
 		vlan_set_promisc(ifp);
+		VLAN_UNLOCK();
 		break;
 		
 	case SIOCGETVLAN:
 		bzero(&vlr, sizeof vlr);
+		VLAN_LOCK();
 		if (ifv->ifv_p) {
 			snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
 			    "%s%d", ifv->ifv_p->if_name, ifv->ifv_p->if_unit);
 			vlr.vlr_tag = ifv->ifv_tag;
 		}
+		VLAN_UNLOCK();
 		error = copyout(&vlr, ifr->ifr_data, sizeof vlr);
 		break;
 		
@@ -770,13 +804,17 @@
 		 * For promiscuous mode, we enable promiscuous mode on
 		 * the parent if we need promiscuous on the VLAN interface.
 		 */
+		VLAN_LOCK();
 		if (ifv->ifv_p != NULL)
 			error = vlan_set_promisc(ifp);
+		VLAN_UNLOCK();
 		break;
 
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
+		VLAN_LOCK();
 		error = vlan_setmulti(ifp);
+		VLAN_UNLOCK();
 		break;
 	default:
 		error = EINVAL;


More information about the p4-projects mailing list