Network interface cloning (if_loop)

Max Laier max at love2party.net
Sat Jan 3 13:01:21 PST 2004


Here is the cloning for the loopback interface.
My problem is the right time to do the module init. I used SI_SUB_PSEUDO for 
now and tests went well. FreeBSD has an extra SI_SUB_PROTO* stage (i.e. 
attach at splimp()). Can somebody take a look?

-- 
Best regards,				| max at xxxxxxxxxxxxxx
Max Laier				| ICQ #67774661
http://pf4freebsd.love2party.net/	| mlaier at EFnet #DragonFlyBSD
Index: net/if_loop.c
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/net/if_loop.c,v
retrieving revision 1.8
diff -u -r1.8 if_loop.c
--- net/if_loop.c	6 Nov 2003 05:22:17 -0000	1.8
+++ net/if_loop.c	3 Jan 2004 15:07:25 -0000
@@ -48,7 +48,9 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/module.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 
@@ -87,15 +89,6 @@
 #include <netproto/atalk/at_var.h>
 #endif
 
-int loioctl (struct ifnet *, u_long, caddr_t);
-static void lortrequest (int, struct rtentry *, struct rt_addrinfo *);
-
-static void loopattach (void *);
-PSEUDO_SET(loopattach, if_loop);
-
-int looutput (struct ifnet *ifp,
-		struct mbuf *m, struct sockaddr *dst, struct rtentry *rt);
-
 #ifdef TINY_LOMTU
 #define	LOMTU	(1024+512)
 #elif defined(LARGE_LOMTU)
@@ -104,29 +97,93 @@
 #define LOMTU	16384
 #endif
 
-struct	ifnet loif[NLOOP];
+#define LONAME "lo"
 
-/* ARGSUSED */
-static void
-loopattach(dummy)
-	void *dummy;
-{
+struct lo_softc {
+	struct ifnet sc_if;		/* network-visible interface */
+	LIST_ENTRY(lo_softc) sc_next;
+};
+
+int		loioctl (struct ifnet *, u_long, caddr_t);
+static void	lortrequest (int, struct rtentry *, struct rt_addrinfo *);
+int 		looutput (struct ifnet *ifp,
+		    struct mbuf *m, struct sockaddr *dst, struct rtentry *rt);
+int		lo_clone_create (struct if_clone *, int);
+void		lo_clone_destroy (struct ifnet *);
+
+struct	ifnet *loif = NULL;
+
+static MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface");
+
+static LIST_HEAD(lo_list, lo_softc) lo_list;
+
+struct if_clone lo_cloner = IF_CLONE_INITIALIZER(LONAME,
+    lo_clone_create, lo_clone_destroy, NLOOP, IF_MAXUNIT);
+
+void
+lo_clone_destroy(ifp)
 	struct ifnet *ifp;
-	int i = 0;
+{
+	struct lo_softc *sc = ifp->if_softc;
+	
+	KASSERT(loif != ifp, ("%s: destroying lo0", __func__));
+	
+	bpfdetach(ifp);
+	if_detach(ifp);
+	LIST_REMOVE(sc, sc_next);
+	free(sc, M_LO);
+}
 
-	for (ifp = loif; i < NLOOP; ifp++) {
-	    ifp->if_name = "lo";
-	    ifp->if_unit = i++;
-	    ifp->if_mtu = LOMTU;
-	    ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
-	    ifp->if_ioctl = loioctl;
-	    ifp->if_output = looutput;
-	    ifp->if_type = IFT_LOOP;
-	    ifp->if_snd.ifq_maxlen = ifqmaxlen;
-	    if_attach(ifp);
-	    bpfattach(ifp, DLT_NULL, sizeof(u_int));
+int
+lo_clone_create(ifc, unit)
+	struct if_clone *ifc;
+	int unit;
+{
+	struct lo_softc *sc;
+	
+	MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO);
+	
+	sc->sc_if.if_name = LONAME;
+	sc->sc_if.if_unit = unit;
+	sc->sc_if.if_mtu = LOMTU;
+	sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST;
+	sc->sc_if.if_ioctl = loioctl;
+	sc->sc_if.if_output = looutput;
+	sc->sc_if.if_type = IFT_LOOP;
+	sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
+	sc->sc_if.if_softc = sc;
+	if_attach(&sc->sc_if);
+	bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
+	LIST_INSERT_HEAD(&lo_list, sc, sc_next);
+	if (loif == NULL)
+		loif = &sc->sc_if;
+
+	return (0);
+}
+
+static int
+loop_modevent(module_t mod, int type, void *data)
+{
+	switch (type) {
+	case MOD_LOAD:
+		LIST_INIT(&lo_list);
+		if_clone_attach(&lo_cloner);
+		break;
+	case MOD_UNLOAD:
+		printf("if_loop unload: not possible for this module type\n");
+		return EINVAL;
 	}
+	return 0;
 }
+
+static moduledata_t loop_mod = {
+	"loop",
+	loop_modevent,
+	0
+};
+
+DECLARE_MODULE(loop, loop_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+	/* XXX: SI_SUB_PROTO_IF, SI_ORDER_FIRST might suit better here? */
 
 int
 looutput(ifp, m, dst, rt)
Index: net/if_var.h
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/net/if_var.h,v
retrieving revision 1.6
diff -u -r1.6 if_var.h
--- net/if_var.h	30 Dec 2003 01:01:48 -0000	1.6
+++ net/if_var.h	3 Jan 2004 14:52:42 -0000
@@ -387,7 +387,7 @@
 extern	struct ifnethead ifnet;
 extern struct	ifnet	**ifindex2ifnet;
 extern	int ifqmaxlen;
-extern	struct ifnet loif[];
+extern	struct ifnet *loif;
 extern	int if_index;
 extern	struct ifaddr **ifnet_addrs;
 
Index: net/net_osdep.h
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/net/net_osdep.h,v
retrieving revision 1.4
diff -u -r1.4 net_osdep.h
--- net/net_osdep.h	26 Aug 2003 20:49:47 -0000	1.4
+++ net/net_osdep.h	3 Jan 2004 14:54:28 -0000
@@ -201,6 +201,7 @@
  *	BSDI3: struct ifnet loif;
  *	BSDI4: struct ifnet *loifp;
  *	NetBSD, OpenBSD 2.8, FreeBSD2: struct ifnet loif[NLOOP];
+ *	DragonFlyBSD: struct ifnet *loif;
  *	OpenBSD 2.9: struct ifnet *lo0ifp;
  *
  *	odd thing is that many of them refers loif as ifnet *loif,
Index: netinet6/in6_pcb.c
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.10
diff -u -r1.10 in6_pcb.c
--- netinet6/in6_pcb.c	23 Aug 2003 11:02:45 -0000	1.10
+++ netinet6/in6_pcb.c	3 Jan 2004 14:59:51 -0000
@@ -472,7 +472,7 @@
 		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
 
 		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
-			ifp = &loif[0];
+			ifp = loif;
 		}
 
 		if (ifp) {
Index: netinet6/in6_src.c
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/netinet6/in6_src.c,v
retrieving revision 1.5
diff -u -r1.5 in6_src.c
--- netinet6/in6_src.c	7 Aug 2003 21:17:33 -0000	1.5
+++ netinet6/in6_src.c	3 Jan 2004 15:00:08 -0000
@@ -196,7 +196,7 @@
 		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
 
 		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
-			ifp = &loif[0];
+			ifp = loif;
 		}
 
 		if (ifp) {
Index: netinet6/ip6_input.c
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.11
diff -u -r1.11 ip6_input.c
--- netinet6/ip6_input.c	2 Dec 2003 08:00:22 -0000	1.11
+++ netinet6/ip6_input.c	3 Jan 2004 15:00:52 -0000
@@ -220,7 +220,7 @@
 	 * to route local address of p2p link to loopback,
 	 * assign loopback address first.
 	 */
-	in6_ifattach(&loif[0], NULL);
+	in6_ifattach(loif, NULL);
 
 	/* nd6_timer_init */
 	callout_init(&nd6_timer_ch);
@@ -286,7 +286,7 @@
 #define M2MMAX	(sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
 		if (m->m_next) {
 			if (m->m_flags & M_LOOP) {
-				ip6stat.ip6s_m2m[loif[0].if_index]++;	/* XXX */
+				ip6stat.ip6s_m2m[loif->if_index]++;	/* XXX */
 			} else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
 				ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
 			else
Index: netinet6/ip6_output.c
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.9
diff -u -r1.9 ip6_output.c
--- netinet6/ip6_output.c	2 Dec 2003 08:00:22 -0000	1.9
+++ netinet6/ip6_output.c	3 Jan 2004 15:01:46 -0000
@@ -678,7 +678,7 @@
 				in6_ifstat_inc(ifp, ifs6_out_discard);
 				goto bad;
 			} else {
-				ifp = &loif[0];
+				ifp = loif;
 			}
 		}
 
@@ -2061,7 +2061,7 @@
 			 *   XXX: is it a good approach?
 			 */
 			if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
-				ifp = &loif[0];
+				ifp = loif;
 			} else {
 				ro.ro_rt = NULL;
 				dst = (struct sockaddr_in6 *)&ro.ro_dst;
@@ -2494,7 +2494,7 @@
  * Routine called from ip6_output() to loop back a copy of an IP6 multicast
  * packet to the input queue of a specified interface.  Note that this
  * calls the output routine of the loopback "driver", but with an interface
- * pointer that might NOT be &loif -- easier than replicating that code here.
+ * pointer that might NOT be loif -- easier than replicating that code here.
  */
 void
 ip6_mloopback(ifp, m, dst)
Index: netinet6/nd6.c
===================================================================
RCS file: /home/mlaier/.dfcvs/src/sys/netinet6/nd6.c,v
retrieving revision 1.5
diff -u -r1.5 nd6.c
--- netinet6/nd6.c	23 Aug 2003 11:02:45 -0000	1.5
+++ netinet6/nd6.c	3 Jan 2004 15:02:25 -0000
@@ -1265,7 +1265,7 @@
 				SDL(gate)->sdl_alen = ifp->if_addrlen;
 			}
 			if (nd6_useloopback) {
-				rt->rt_ifp = &loif[0];	/* XXX */
+				rt->rt_ifp = loif;	/* XXX */
 				/*
 				 * Make sure rt_ifa be equal to the ifaddr
 				 * corresponding to the address.




More information about the Submit mailing list