summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2001-01-29 11:06:26 +0000
committerpeter <peter@FreeBSD.org>2001-01-29 11:06:26 +0000
commit20862096d0755befb9dccbb3c923851266bd3598 (patch)
tree58cd25d643c1a21f8b8a769e437c9bd0c47baef2
parent20ada13c6020d34f110abb521568899f58d01830 (diff)
downloadFreeBSD-src-20862096d0755befb9dccbb3c923851266bd3598.zip
FreeBSD-src-20862096d0755befb9dccbb3c923851266bd3598.tar.gz
Make the number of loopback interfaces dynamically tunable. Why one
would *want* to is a different story, but it used to be able to be done statically. Get rid of #include "loop.h" and struct ifnet loif[NLOOP]; This could be used as an example of how to do this in other drivers, for example: ccd.
-rw-r--r--sys/net/if_loop.c96
-rw-r--r--sys/net/if_var.h2
2 files changed, 80 insertions, 18 deletions
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index a76466b..105b8dd 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -37,7 +37,6 @@
/*
* Loopback interface driver for protocol testing and timing.
*/
-#include "loop.h"
#include "opt_atalk.h"
#include "opt_inet.h"
@@ -47,9 +46,11 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_types.h>
@@ -102,28 +103,89 @@ int looutput __P((struct ifnet *ifp,
#define LOMTU 16384
#endif
-struct ifnet loif[NLOOP];
+static int nloop;
+
+struct ifnet *loif; /* Used externally */
+
+static MALLOC_DEFINE(M_LO, "lo", "Loopback Interface");
+
+struct lo_softc {
+ struct ifnet sc_if; /* network-visible interface */
+ LIST_ENTRY(lo_softc) sc_next;
+};
+static LIST_HEAD(lo_list, lo_softc) lo_list;
+
+static void
+locreate(int unit)
+{
+ struct lo_softc *sc;
+
+ MALLOC(sc, struct lo_softc *, sizeof(*sc), M_LO, M_WAITOK | M_ZERO);
+
+ sc->sc_if.if_name = "lo";
+ 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;
+ 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;
+}
+
+static void
+lodestroy(struct lo_softc *sc)
+{
+ bpfdetach(&sc->sc_if);
+ if_detach(&sc->sc_if);
+ LIST_REMOVE(sc, sc_next);
+ FREE(sc, M_LO);
+}
+
+
+static int
+sysctl_net_nloop(SYSCTL_HANDLER_ARGS)
+{
+ int newnloop;
+ int error;
+
+ newnloop = nloop;
+
+ error = sysctl_handle_opaque(oidp, &newnloop, sizeof newnloop, req);
+ if (error || !req->newptr)
+ return (error);
+
+ if (newnloop < 1)
+ return (EINVAL);
+ while (newnloop > nloop) {
+ locreate(nloop);
+ nloop++;
+ }
+ while (newnloop < nloop) {
+ lodestroy(LIST_FIRST(&lo_list));
+ nloop--;
+ }
+ return (0);
+}
+SYSCTL_PROC(_net, OID_AUTO, nloop, CTLTYPE_INT | CTLFLAG_RW,
+ 0, 0, sysctl_net_nloop, "I", "");
/* ARGSUSED */
static void
loopattach(dummy)
void *dummy;
{
- register struct ifnet *ifp;
- register int i = 0;
-
- 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 i;
+
+ TUNABLE_INT_FETCH("net.nloop", 1, nloop);
+ if (nloop < 1) /* sanity check */
+ nloop = 1;
+ for (i = 0; i < nloop; i++)
+ locreate(i);
}
int
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 1c932c2..fc60f9c 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -372,7 +372,7 @@ struct ifmultiaddr {
extern struct ifnethead ifnet;
extern struct ifnet **ifindex2ifnet;
extern int ifqmaxlen;
-extern struct ifnet loif[];
+extern struct ifnet *loif; /* first loopback interface */
extern int if_index;
extern struct ifaddr **ifnet_addrs;
OpenPOWER on IntegriCloud