aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2001-01-29 11:06:26 +0000
committerPeter Wemm <peter@FreeBSD.org>2001-01-29 11:06:26 +0000
commit90d9802fe7378d14fa6349c68e9665372569d65a (patch)
treec4620085f5b9b7f472b5a13c8b3c98818928eca8
parente50fa3d24715bcf2d59dab5d9c6a0105e087b5cf (diff)
downloadsrc-90d9802fe7378d14fa6349c68e9665372569d65a.tar.gz
src-90d9802fe7378d14fa6349c68e9665372569d65a.zip
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.
Notes
Notes: svn path=/head/; revision=71791
-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 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 <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 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;