Date: Mon, 25 Oct 2004 22:04:32 +0900 From: gnn@freebsd.org To: rwatson@freebsd.org Cc: kame <snap-users@kame.net> Subject: Updated scope6.c locking patch... Message-ID: <m2pt37dk4f.wl@minion.local.neville-neil.com>
next in thread | raw e-mail | index | archive | help
Hi Folks, Enclosed please find my updated patch for scope6 locking for the IPv6 code in FreeBSD-CURRENT. The major change was to remove the IFNET list locking because this actually needs to be done outside of the IPv6 code and to add address family (AF) data locking because that's something we can and should do within the scope6 code. I have tested this locally in the following way: 1) Open a shell on the machine (shell1) and do: shell1> ifconfig lo1 create shell1> while 1 shell1> scope6config -l 1 -s 2 -o 3 lo1 shell1> end 2) Open a second shell on the same machine (shell2) and do: shell2> ifconfig lo1 destroy shell2> ifconfig lo1 create etc. The messages in the shell1 window should switch between: lo1: 0, 6, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0 and scope6config: ioctl(SIOCSSCOPE6): Device not configured and the kernel should not panic ;-) Later, George --- sys/netinet6/scope6.c.orig +++ sys/netinet6/scope6.c @@ -71,7 +71,6 @@ scope6_ifattach(ifp) struct ifnet *ifp; { - int s = splnet(); struct scope6_id *sid; sid = (struct scope6_id *)malloc(sizeof(*sid), M_IFADDR, M_WAITOK); @@ -89,7 +88,6 @@ sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1; #endif - splx(s); return sid; } @@ -106,12 +104,17 @@ struct ifnet *ifp; struct scope6_id *idlist; { - int i, s; + int i; int error = 0; - struct scope6_id *sid = SID(ifp); + struct scope6_id *sid = NULL; + + IF_AFDATA_LOCK(ifp); + sid = SID(ifp); - if (!sid) /* paranoid? */ + if (!sid) { /* paranoid? */ + IF_AFDATA_UNLOCK(ifp); return (EINVAL); + } /* * XXX: We need more consistency checks of the relationship among @@ -123,8 +126,6 @@ * interface addresses, routing table entries, PCB entries... */ - s = splnet(); - SCOPE6_LOCK(); for (i = 0; i < 16; i++) { if (idlist->s6id_list[i] && @@ -135,7 +136,8 @@ */ if (i == IPV6_ADDR_SCOPE_INTFACELOCAL && idlist->s6id_list[i] != ifp->if_index) { - splx(s); + IF_AFDATA_UNLOCK(ifp); + SCOPE6_UNLOCK(); return (EINVAL); } @@ -147,7 +149,8 @@ * IDs, but we check the consistency for * safety in later use. */ - splx(s); + IF_AFDATA_UNLOCK(ifp); + SCOPE6_UNLOCK(); return (EINVAL); } @@ -160,7 +163,7 @@ } } SCOPE6_UNLOCK(); - splx(s); + IF_AFDATA_UNLOCK(ifp); return (error); } @@ -170,15 +173,20 @@ struct ifnet *ifp; struct scope6_id *idlist; { + /* We only need to lock the interface's afdata for SID() to work. */ + IF_AFDATA_LOCK(ifp); struct scope6_id *sid = SID(ifp); - if (sid == NULL) /* paranoid? */ + if (sid == NULL) { /* paranoid? */ + IF_AFDATA_UNLOCK(ifp); return (EINVAL); + } SCOPE6_LOCK(); *idlist = *sid; SCOPE6_UNLOCK(); + IF_AFDATA_UNLOCK(ifp); return (0); } @@ -259,7 +267,11 @@ { int scope; u_int32_t zoneid = 0; - struct scope6_id *sid = SID(ifp); + struct scope6_id *sid = NULL; + + IF_AFDATA_LOCK(ifp); + + sid = SID(ifp); #ifdef DIAGNOSTIC if (sid == NULL) { /* should not happen */ @@ -277,10 +289,12 @@ * interface. */ if (IN6_IS_ADDR_LOOPBACK(addr)) { - if (!(ifp->if_flags & IFF_LOOPBACK)) + if (!(ifp->if_flags & IFF_LOOPBACK)) { + IF_AFDATA_UNLOCK(ifp); return (-1); - else { + } else { *ret_id = 0; /* there's no ambiguity */ + IF_AFDATA_UNLOCK(ifp); return (0); } } @@ -315,6 +329,9 @@ SCOPE6_UNLOCK(); *ret_id = zoneid; + + IF_AFDATA_UNLOCK(ifp); + return (0); } @@ -323,7 +340,7 @@ struct ifnet *ifp; /* note that this might be NULL */ { /* - * Currently, this function just set the default "interfaces" + * Currently, this function just sets the default "interfaces" * and "links" according to the given interface. * We might eventually have to separate the notion of "link" from * "interface" and provide a user interface to set the default.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m2pt37dk4f.wl>