From 90d9802fe7378d14fa6349c68e9665372569d65a Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Mon, 29 Jan 2001 11:06:26 +0000 Subject: [PATCH] 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. --- sys/net/if_loop.c | 94 +++++++++++++++++++++++++++++++++++++++-------- sys/net/if_var.h | 2 +- 2 files changed, 79 insertions(+), 17 deletions(-) diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index a76466b65a2d..105b8dd1e95b 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 #include #include +#include #include #include #include +#include #include #include @@ -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; + int i; - 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)); - } + 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 1c932c2b5766..fc60f9cf787d 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;