Subject: lo(4) as a clonable interface
To: None <tech-net@NetBSD.org>
From: Peter Postma <peter@pointless.nl>
List: tech-net
Date: 07/23/2004 18:34:58
--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi all,
The attached patch converts lo(4) into a clonable interface.
So there's no longer need to rebuild the kernel to add additional loopback
interfaces.
Can someone please review the patch before I'm going send-pr it?
--
Peter Postma
--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="if_loop.diff"
Index: net/if.c
===================================================================
RCS file: /cvsroot/src/sys/net/if.c,v
retrieving revision 1.143
diff -u -r1.143 if.c
--- net/if.c 22 Jun 2004 12:50:41 -0000 1.143
+++ net/if.c 23 Jul 2004 15:42:06 -0000
@@ -271,6 +271,7 @@
size_t if_indexlim = 0;
struct ifaddr **ifnet_addrs = NULL;
struct ifnet **ifindex2ifnet = NULL;
+struct ifnet *lo0ifp;
/*
* Allocate the link level name for the specified interface. This
Index: net/if.h
===================================================================
RCS file: /cvsroot/src/sys/net/if.h,v
retrieving revision 1.96
diff -u -r1.96 if.h
--- net/if.h 21 Apr 2004 04:17:28 -0000 1.96
+++ net/if.h 23 Jul 2004 15:42:06 -0000
@@ -733,9 +733,7 @@
extern struct ifnet_head ifnet;
extern struct ifnet **ifindex2ifnet;
-#if 0
-struct ifnet loif[];
-#endif
+extern struct ifnet *lo0ifp;
extern size_t if_indexlim;
char *ether_sprintf __P((const u_char *));
Index: net/if_loop.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_loop.c,v
retrieving revision 1.50
diff -u -r1.50 if_loop.c
--- net/if_loop.c 21 Apr 2004 18:40:39 -0000 1.50
+++ net/if_loop.c 23 Jul 2004 15:42:07 -0000
@@ -75,7 +75,6 @@
#include "opt_mbuftrace.h"
#include "bpfilter.h"
-#include "loop.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -140,50 +139,99 @@
#define LOMTU_MAX (65536 + MHLEN + MLEN)
#endif
-struct ifnet loif[NLOOP];
-#ifdef MBUFTRACE
-struct mowner lomowner[NLOOP];
-#endif
-
#ifdef ALTQ
void lostart(struct ifnet *);
#endif
+struct loop_softc {
+ LIST_ENTRY(loop_softc) sc_list;
+ struct ifnet sc_if;
+};
+
+LIST_HEAD(, loop_softc) loop_softc_list;
+
+int loop_clone_create(struct if_clone *, int);
+void loop_clone_destroy(struct ifnet *);
+
+struct if_clone loop_cloner =
+ IF_CLONE_INITIALIZER("lo", loop_clone_create, loop_clone_destroy);
+
void
-loopattach(n)
- int n;
+loopattach(int n)
{
- int i;
- struct ifnet *ifp;
+ LIST_INIT(&loop_softc_list);
+
+ (void)loop_clone_create(&loop_cloner, 0); /* lo0 always exists */
+ if_clone_attach(&loop_cloner);
+}
- for (i = 0; i < NLOOP; i++) {
- ifp = &loif[i];
- snprintf(ifp->if_xname, sizeof(ifp->if_xname), "lo%d", i);
- ifp->if_softc = NULL;
- ifp->if_mtu = LOMTU;
- ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
- ifp->if_ioctl = loioctl;
- ifp->if_output = looutput;
+int
+loop_clone_create(struct if_clone *ifc, int unit)
+{
+ struct loop_softc *sc;
+
+ sc = malloc(sizeof(struct loop_softc), M_DEVBUF, M_WAITOK);
+ if (sc == NULL)
+ return (ENOMEM);
+ (void)memset(sc, 0, sizeof(struct loop_softc));
+
+ snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname), "%s%d",
+ ifc->ifc_name, unit);
+
+ sc->sc_if.if_softc = sc;
+ 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;
#ifdef ALTQ
- ifp->if_start = lostart;
+ sc->sc_if.if_start = lostart;
#endif
- ifp->if_type = IFT_LOOP;
- ifp->if_hdrlen = 0;
- ifp->if_addrlen = 0;
- ifp->if_dlt = DLT_NULL;
- IFQ_SET_READY(&ifp->if_snd);
- if_attach(ifp);
- if_alloc_sadl(ifp);
+ sc->sc_if.if_type = IFT_LOOP;
+ sc->sc_if.if_hdrlen = 0;
+ sc->sc_if.if_addrlen = 0;
+ sc->sc_if.if_dlt = DLT_NULL;
+ IFQ_SET_READY(&sc->sc_if.if_snd);
+ if (unit == 0)
+ lo0ifp = &sc->sc_if;
+ if_attach(&sc->sc_if);
+ if_alloc_sadl(&sc->sc_if);
#if NBPFILTER > 0
- bpfattach(ifp, DLT_NULL, sizeof(u_int));
+ bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
#endif
#ifdef MBUFTRACE
- ifp->if_mowner = &lomowner[i];
- strlcpy(ifp->if_mowner->mo_name, ifp->if_xname,
- sizeof(ifp->if_mowner->mo_name));
- MOWNER_ATTACH(&lomowner[i]);
+ sc->sc_if.if_mowner = malloc(sizeof(struct mowner), M_DEVBUF, M_WAITOK);
+ if (sc->sc_if.if_mowner == NULL)
+ return (ENOMEM);
+ (void)memset(sc->sc_if.if_mowner, 0, sizeof(struct mowner));
+ strlcpy(sc->sc_if.if_mowner->mo_name, sc->sc_if.if_xname,
+ sizeof(sc->sc_if.if_mowner->mo_name));
+ MOWNER_ATTACH(sc->sc_if.if_mowner);
#endif
- }
+ LIST_INSERT_HEAD(&loop_softc_list, sc, sc_list);
+
+ return (0);
+}
+
+void
+loop_clone_destroy(struct ifnet *ifp)
+{
+ struct loop_softc *sc = ifp->if_softc;
+
+ if (ifp == lo0ifp) /* don't kill lo0 */
+ return;
+
+#ifdef MBUFTRACE
+ MOWNER_DETACH(ifp->if_mowner);
+ free(ifp->if_mowner, M_DEVBUF);
+#endif
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+
+ LIST_REMOVE(sc, sc_list);
+ free(sc, M_DEVBUF);
}
int
@@ -406,9 +454,8 @@
struct rt_addrinfo *info;
{
- struct ifnet *ifp = &loif[0];
if (rt)
- rt->rt_rmx.rmx_mtu = ifp->if_mtu;
+ rt->rt_rmx.rmx_mtu = lo0ifp->if_mtu;
}
Index: net/net_osdep.h
===================================================================
RCS file: /cvsroot/src/sys/net/net_osdep.h,v
retrieving revision 1.8
diff -u -r1.8 net_osdep.h
--- net/net_osdep.h 14 May 2003 22:45:02 -0000 1.8
+++ net/net_osdep.h 23 Jul 2004 15:42:07 -0000
@@ -195,8 +195,8 @@
* - struct ifnet for loopback interface
* BSDI3: struct ifnet loif;
* BSDI4: struct ifnet *loifp;
- * NetBSD, OpenBSD 2.8, FreeBSD2: struct ifnet loif[NLOOP];
- * OpenBSD 2.9: struct ifnet *lo0ifp;
+ * NetBSD 2.0, OpenBSD 2.8, FreeBSD2: struct ifnet loif[NLOOP];
+ * NetBSD 3.0, OpenBSD 2.9: struct ifnet *lo0ifp;
*
* odd thing is that many of them refers loif as ifnet *loif,
* not loif[NLOOP], from outside of if_loop.c.
Index: netinet/if_arp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/if_arp.c,v
retrieving revision 1.98
diff -u -r1.98 if_arp.c
--- netinet/if_arp.c 25 May 2004 04:33:59 -0000 1.98
+++ netinet/if_arp.c 23 Jul 2004 15:42:08 -0000
@@ -152,9 +152,6 @@
int, int));
static void in_arpinput __P((struct mbuf *));
-#if NLOOP > 0
-extern struct ifnet loif[NLOOP];
-#endif
LIST_HEAD(, llinfo_arp) llinfo_arp;
struct ifqueue arpintrq = {0, 0, 0, 50};
int arp_inuse, arp_allocated, arp_intimer;
@@ -552,7 +549,7 @@
if (ia) {
/*
* This test used to be
- * if (loif.if_flags & IFF_UP)
+ * if (lo0ifp->if_flags & IFF_UP)
* It allowed local traffic to be forced through
* the hardware by configuring the loopback down.
* However, it causes problems during network
@@ -573,7 +570,7 @@
SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen);
#if NLOOP > 0
if (useloopback)
- rt->rt_ifp = &loif[0];
+ rt->rt_ifp = lo0ifp;
#endif
/*
* make sure to set rt->rt_ifa to the interface
Index: netinet/ip_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_output.c,v
retrieving revision 1.134
diff -u -r1.134 ip_output.c
--- netinet/ip_output.c 6 Jul 2004 04:30:27 -0000 1.134
+++ netinet/ip_output.c 23 Jul 2004 15:42:09 -0000
@@ -1832,7 +1832,7 @@
* Routine called from ip_output() to loop back a copy of an IP 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 lo0ifp -- easier than replicating that code here.
*/
static void
ip_mloopback(ifp, m, dst)
Index: netinet6/in6_pcb.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.65
diff -u -r1.65 in6_pcb.c
--- netinet6/in6_pcb.c 24 Jun 2004 16:49:51 -0000 1.65
+++ netinet6/in6_pcb.c 23 Jul 2004 15:42:09 -0000
@@ -92,8 +92,6 @@
#include <netinet6/in6_pcb.h>
#include <netinet6/nd6.h>
-#include "loop.h"
-extern struct ifnet loif[NLOOP];
#include "faith.h"
#ifdef IPSEC
Index: netinet6/in6_src.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_src.c,v
retrieving revision 1.18
diff -u -r1.18 in6_src.c
--- netinet6/in6_src.c 10 Dec 2003 11:46:33 -0000 1.18
+++ netinet6/in6_src.c 23 Jul 2004 15:42:09 -0000
@@ -97,9 +97,6 @@
#include <net/net_osdep.h>
-#include "loop.h"
-extern struct ifnet loif[NLOOP];
-
/*
* Return an IPv6 address, which is the most appropriate for a given
* destination and user specified options.
@@ -195,9 +192,8 @@
if (IN6_IS_ADDR_MULTICAST(dst)) {
struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
- if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
- ifp = &loif[0];
- }
+ if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst))
+ ifp = lo0ifp;
if (ifp) {
ia6 = in6_ifawithscope(ifp, dst);
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.75
diff -u -r1.75 ip6_input.c
--- netinet6/ip6_input.c 1 Jun 2004 03:13:22 -0000 1.75
+++ netinet6/ip6_input.c 23 Jul 2004 15:42:10 -0000
@@ -112,8 +112,6 @@
#include <netinet6/ip6protosw.h>
-/* we need it for NLOOP. */
-#include "loop.h"
#include "faith.h"
#include "gif.h"
#include "bpfilter.h"
@@ -131,7 +129,6 @@
struct in6_ifaddr *in6_ifaddr;
struct ifqueue ip6intrq;
-extern struct ifnet loif[NLOOP];
int ip6_forward_srcrt; /* XXX */
int ip6_sourcecheck; /* XXX */
int ip6_sourcecheck_interval; /* XXX */
@@ -248,7 +245,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[lo0ifp->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: /cvsroot/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.85
diff -u -r1.85 ip6_output.c
--- netinet6/ip6_output.c 14 Jul 2004 03:06:08 -0000 1.85
+++ netinet6/ip6_output.c 23 Jul 2004 15:42:12 -0000
@@ -98,8 +98,6 @@
#include <netkey/key.h>
#endif /* IPSEC */
-#include "loop.h"
-
#include <net/net_osdep.h>
#ifdef PFIL_HOOKS
@@ -124,8 +122,6 @@
static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
-extern struct ifnet loif[NLOOP];
-
/*
* IP6 output. The packet in mbuf chain m contains a skeletal IP6
* header (with pri, len, nxt, hlim, src, dst).
@@ -624,9 +620,8 @@
/* XXX correct ifp? */
in6_ifstat_inc(ifp, ifs6_out_discard);
goto bad;
- } else {
- ifp = &loif[0];
- }
+ } else
+ ifp = lo0ifp;
}
if (opt && opt->ip6po_hlim != -1)
@@ -1912,7 +1907,7 @@
* XXX: is it a good approach?
*/
if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
- ifp = &loif[0];
+ ifp = lo0ifp;
} else {
ro.ro_rt = NULL;
dst = (struct sockaddr_in6 *)&ro.ro_dst;
@@ -2309,7 +2304,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 lo0ifp -- easier than replicating that code here.
*/
void
ip6_mloopback(ifp, m, dst)
Index: netinet6/nd6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.c,v
retrieving revision 1.90
diff -u -r1.90 nd6.c
--- netinet6/nd6.c 19 May 2004 17:45:05 -0000 1.90
+++ netinet6/nd6.c 23 Jul 2004 15:42:13 -0000
@@ -69,9 +69,6 @@
#include <netinet6/ipsec.h>
#endif
-#include "loop.h"
-extern struct ifnet loif[NLOOP];
-
#include <net/net_osdep.h>
#define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */
@@ -1177,7 +1174,7 @@
SDL(gate)->sdl_alen = ifp->if_addrlen;
}
if (nd6_useloopback) {
- rt->rt_ifp = &loif[0]; /* XXX */
+ rt->rt_ifp = lo0ifp; /* XXX */
/*
* Make sure rt_ifa be equal to the ifaddr
* corresponding to the address.
Index: netiso/if_eon.c
===================================================================
RCS file: /cvsroot/src/sys/netiso/if_eon.c,v
retrieving revision 1.45
diff -u -r1.45 if_eon.c
--- netiso/if_eon.c 21 Apr 2004 18:40:41 -0000 1.45
+++ netiso/if_eon.c 23 Jul 2004 15:42:13 -0000
@@ -109,10 +109,6 @@
#include <machine/stdarg.h>
-#include "loop.h"
-
-extern struct ifnet loif[NLOOP];
-
extern struct timeval time;
#define EOK 0
@@ -294,7 +290,7 @@
case RTM_ADD:
case RTM_RESOLVE:
- rt->rt_rmx.rmx_mtu = loif[0].if_mtu; /* unless better below */
+ rt->rt_rmx.rmx_mtu = lo0ifp->if_mtu; /* unless better below */
R_Malloc(el, struct eon_llinfo *, sizeof(*el));
rt->rt_llinfo = (caddr_t) el;
if (el == 0)
--W/nzBZO5zC0uMSeA--