summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorbrooks <brooks@FreeBSD.org>2002-03-04 21:46:00 +0000
committerbrooks <brooks@FreeBSD.org>2002-03-04 21:46:00 +0000
commitbe085a899ec0eab8e938f7e658ae0e98833404da (patch)
tree9bda41e90494cd16c15cefbf9c35e5eb3d29abda /sys/net
parent50d3be4c82e6c70eac43734b67628e7a27fa3e24 (diff)
downloadFreeBSD-src-be085a899ec0eab8e938f7e658ae0e98833404da.zip
FreeBSD-src-be085a899ec0eab8e938f7e658ae0e98833404da.tar.gz
Add cloning support to the loopback interface.
Submitted by: mux
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_loop.c155
1 files changed, 99 insertions, 56 deletions
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 982ced0..b2b3c09 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -49,6 +49,8 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
@@ -88,12 +90,6 @@
#include <netatalk/at_var.h>
#endif
-int loioctl __P((struct ifnet *, u_long, caddr_t));
-static void lortrequest __P((int, struct rtentry *, struct rt_addrinfo *));
-
-int looutput __P((struct ifnet *ifp,
- struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
-
#ifdef TINY_LOMTU
#define LOMTU (1024+512)
#elif defined(LARGE_LOMTU)
@@ -102,26 +98,93 @@ int looutput __P((struct ifnet *ifp,
#define LOMTU 16384
#endif
-static int nloop = 1;
-
-struct ifnet *loif; /* Used externally */
-
-static MALLOC_DEFINE(M_LO, "lo", "Loopback Interface");
+#define LONAME "lo"
+#define LOMAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */
struct lo_softc {
struct ifnet sc_if; /* network-visible interface */
LIST_ENTRY(lo_softc) sc_next;
+ struct resource *r_unit;
};
+
+int loioctl(struct ifnet *, u_long, caddr_t);
+static void lortrequest(int, struct rtentry *, struct rt_addrinfo *);
+int looutput(struct ifnet *ifp, struct mbuf *m,
+ struct sockaddr *dst, struct rtentry *rt);
+int lo_clone_create(struct if_clone *, int *);
+int lo_clone_destroy(struct ifnet *);
+static void locreate(int, struct resource *);
+
+struct ifnet *loif = NULL; /* Used externally */
+
+static MALLOC_DEFINE(M_LO, LONAME, "Loopback Interface");
+
static LIST_HEAD(lo_list, lo_softc) lo_list;
+struct if_clone lo_cloner =
+ IF_CLONE_INITIALIZER(LONAME, lo_clone_create, lo_clone_destroy);
+
+static struct rman lounits[1];
+
+int
+lo_clone_create(ifc, unit)
+ struct if_clone *ifc;
+ int *unit;
+{
+ struct resource *r;
+
+ if (*unit > LOMAXUNIT)
+ return (ENXIO);
+
+ if (*unit < 0) {
+ r = rman_reserve_resource(lounits, 0, LOMAXUNIT, 1,
+ RF_ALLOCATED | RF_ACTIVE, NULL);
+ if (r == NULL)
+ return (ENOSPC);
+ *unit = rman_get_start(r);
+ } else {
+ r = rman_reserve_resource(lounits, *unit, *unit, 1,
+ RF_ALLOCATED | RF_ACTIVE, NULL);
+ if (r == NULL)
+ return (EEXIST);
+ }
+ locreate(*unit, r);
+ return (0);
+}
+
+int
+lo_clone_destroy(ifp)
+ struct ifnet *ifp;
+{
+ int err;
+ struct lo_softc *sc;
+
+ sc = ifp->if_softc;
+
+ /*
+ * Prevent lo0 from being destroyed.
+ */
+ if (loif == ifp)
+ return (EINVAL);
+
+ err = rman_release_resource(sc->r_unit);
+ KASSERT(err == 0, ("Unexpected error freeing resource"));
+
+ bpfdetach(ifp);
+ if_detach(ifp);
+ LIST_REMOVE(sc, sc_next);
+ FREE(sc, M_LO);
+ return (0);
+}
+
static void
-locreate(int unit)
+locreate(int unit, struct resource *r)
{
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_name = LONAME;
sc->sc_if.if_unit = unit;
sc->sc_if.if_mtu = LOMTU;
sc->sc_if.if_flags = IFF_LOOPBACK | IFF_MULTICAST;
@@ -129,6 +192,8 @@ locreate(int unit)
sc->sc_if.if_output = looutput;
sc->sc_if.if_type = IFT_LOOP;
sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
+ sc->sc_if.if_softc = sc;
+ sc->r_unit = r;
if_attach(&sc->sc_if);
bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
LIST_INSERT_HEAD(&lo_list, sc, sc_next);
@@ -136,55 +201,33 @@ locreate(int unit)
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", "");
-
static int
loop_modevent(module_t mod, int type, void *data)
{
- int i;
+ int err;
+ int unit;
switch (type) {
case MOD_LOAD:
- TUNABLE_INT_FETCH("net.nloop", &nloop);
- if (nloop < 1) /* sanity check */
- nloop = 1;
- for (i = 0; i < nloop; i++)
- locreate(i);
+ lounits->rm_type = RMAN_ARRAY;
+ lounits->rm_descr = "configurable if_loop units";
+ err = rman_init(lounits);
+ if (err != 0)
+ return (err);
+ err = rman_manage_region(lounits, 0, LOMAXUNIT);
+ if (err != 0) {
+ printf("%s: lounits: rman_manage_region: Failed %d\n",
+ LONAME, err);
+ rman_fini(lounits);
+ return (err);
+ }
+ LIST_INIT(&lo_list);
+ if_clone_attach(&lo_cloner);
+
+ /* Create lo0 */
+ unit = 0;
+ err = lo_clone_create(NULL, &unit);
+ KASSERT(err == 0, ("%s: can't create lo0", __func__));
break;
case MOD_UNLOAD:
printf("loop module unload - not possible for this module type\n");
OpenPOWER on IntegriCloud