diff options
author | peter <peter@FreeBSD.org> | 2001-01-29 11:06:26 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2001-01-29 11:06:26 +0000 |
commit | 20862096d0755befb9dccbb3c923851266bd3598 (patch) | |
tree | 58cd25d643c1a21f8b8a769e437c9bd0c47baef2 | |
parent | 20ada13c6020d34f110abb521568899f58d01830 (diff) | |
download | FreeBSD-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.c | 96 | ||||
-rw-r--r-- | sys/net/if_var.h | 2 |
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; |