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