summaryrefslogtreecommitdiffstats
path: root/sys/net/if_sl.c
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2000-05-30 13:47:03 +0000
committergreen <green@FreeBSD.org>2000-05-30 13:47:03 +0000
commit2f41e1d09eea12df89f59e284063e8309f3dedc7 (patch)
tree8908cdf757b4547856c9089a2eb697fc0c585f0a /sys/net/if_sl.c
parent4fe853adac45791690d79450e26988cf8acc45f9 (diff)
downloadFreeBSD-src-2f41e1d09eea12df89f59e284063e8309f3dedc7.zip
FreeBSD-src-2f41e1d09eea12df89f59e284063e8309f3dedc7.tar.gz
Make sl(4) SLIP devices dynamically expansible. Yay! =)
PR: kern/17758 Submitted by: David Malone <dwmalone@maths.tcd.ie>
Diffstat (limited to 'sys/net/if_sl.c')
-rw-r--r--sys/net/if_sl.c284
1 files changed, 169 insertions, 115 deletions
diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c
index f2a8654..cc93d2f 100644
--- a/sys/net/if_sl.c
+++ b/sys/net/if_sl.c
@@ -105,6 +105,8 @@
#include <net/bpf.h>
+static MALLOC_DEFINE(M_SL, "sl", "SLIP Interface");
+
static void slattach __P((void *));
PSEUDO_SET(slattach, if_sl);
@@ -168,14 +170,17 @@ PSEUDO_SET(slattach, if_sl);
#define ABT_COUNT 3 /* count of escapes for abort */
#define ABT_WINDOW (ABT_COUNT*2+2) /* in seconds - time to count */
-static struct sl_softc sl_softc[NSL];
+LIST_HEAD(sl_list, sl_softc) sl_list;
#define FRAME_END 0xc0 /* Frame End */
#define FRAME_ESCAPE 0xdb /* Frame Esc */
#define TRANS_FRAME_END 0xdc /* transposed frame end */
#define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */
-static int slinit __P((struct sl_softc *));
+static int slisstatic __P((int));
+static void slmarkstatic __P((int));
+static struct sl_softc *slcreate __P((void));
+static void sldestroy __P((struct sl_softc *sc));
static struct mbuf *sl_btom __P((struct sl_softc *, int));
static timeout_t sl_keepalive;
static timeout_t sl_outfill;
@@ -201,55 +206,110 @@ static void
slattach(dummy)
void *dummy;
{
- register struct sl_softc *sc;
- register int i = 0;
-
linesw[SLIPDISC] = slipdisc;
- for (sc = sl_softc; i < NSL; sc++) {
- sc->sc_if.if_name = "sl";
- sc->sc_if.if_unit = i++;
- sc->sc_if.if_mtu = SLMTU;
- sc->sc_if.if_flags =
-#ifdef SLIP_IFF_OPTS
- SLIP_IFF_OPTS;
-#else
- IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST;
-#endif
- sc->sc_if.if_type = IFT_SLIP;
- sc->sc_if.if_ioctl = slioctl;
- sc->sc_if.if_output = sloutput;
- sc->sc_if.if_snd.ifq_maxlen = 50;
- sc->sc_fastq.ifq_maxlen = 32;
- sc->sc_if.if_linkmib = sc;
- sc->sc_if.if_linkmiblen = sizeof *sc;
- if_attach(&sc->sc_if);
- bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
- }
+ LIST_INIT(&sl_list);
}
-static int
-slinit(sc)
- register struct sl_softc *sc;
+static int *st_unit_list;
+static size_t st_unit_max = 0;
+
+static
+int slisstatic(unit)
+ int unit;
{
- register caddr_t p;
+ size_t i;
- if (sc->sc_ep == (u_char *) 0) {
- MCLALLOC(p, M_WAIT);
- if (p)
- sc->sc_ep = (u_char *)p + SLBUFSIZE;
- else {
- printf("sl%ld: can't allocate buffer\n",
- (long)(sc - sl_softc));
- return (0);
- }
+ for (i = 0; i < st_unit_max; i++)
+ if (st_unit_list[i] == unit)
+ return 1;
+ return 0;
+}
+
+static
+void slmarkstatic(unit)
+ int unit;
+{
+ int *t;
+
+ if (slisstatic(unit))
+ return;
+
+ MALLOC(t, int *, sizeof(int) * (st_unit_max+1), M_SL, M_NOWAIT);
+ if (t == NULL)
+ return;
+
+ if (st_unit_list) {
+ bcopy(st_unit_list, t, sizeof(int) * st_unit_max);
+ FREE(st_unit_list, M_SL);
+ }
+ st_unit_list = t;
+ st_unit_list[st_unit_max] = unit;
+ st_unit_max++;
+}
+
+static struct sl_softc *
+slcreate()
+{
+ struct sl_softc *sc, *nc;
+ int unit;
+ caddr_t p;
+
+ MALLOC(sc, struct sl_softc *, sizeof(*sc), M_SL, M_WAITOK);
+ bzero(sc, sizeof *sc);
+
+ MCLALLOC(p, M_WAIT);
+ if (p)
+ sc->sc_ep = (u_char *)p + SLBUFSIZE;
+ else {
+ printf("sl: can't allocate buffer\n");
+ FREE(sc, M_SL);
+ return (NULL);
}
+
sc->sc_buf = sc->sc_ep - SLRMAX;
sc->sc_mp = sc->sc_buf;
sl_compress_init(&sc->sc_comp, -1);
- return (1);
+
+ sc->sc_if.if_softc = sc;
+ sc->sc_if.if_name = "sl";
+ sc->sc_if.if_mtu = SLMTU;
+ sc->sc_if.if_flags =
+#ifdef SLIP_IFF_OPTS
+ SLIP_IFF_OPTS;
+#else
+ IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST;
+#endif
+ sc->sc_if.if_type = IFT_SLIP;
+ sc->sc_if.if_ioctl = slioctl;
+ sc->sc_if.if_output = sloutput;
+ sc->sc_if.if_snd.ifq_maxlen = 50;
+ sc->sc_fastq.ifq_maxlen = 32;
+ sc->sc_if.if_linkmib = sc;
+ sc->sc_if.if_linkmiblen = sizeof *sc;
+
+ /*
+ * Find a suitable unit number.
+ */
+ for (unit=0; ; unit++) {
+ if (slisstatic(unit))
+ continue;
+ LIST_FOREACH(nc, &sl_list, sl_next) {
+ if (nc->sc_if.if_unit == unit)
+ continue;
+ }
+ break;
+ }
+ sc->sc_if.if_unit = unit;
+ LIST_INSERT_HEAD(&sl_list, sc, sl_next);
+
+ if_attach(&sc->sc_if);
+ bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
+
+ return sc;
}
+
/*
* Line specific open routine.
* Attach the given tty to the first available sl unit.
@@ -262,7 +322,6 @@ slopen(dev, tp)
{
struct proc *p = curproc; /* XXX */
register struct sl_softc *sc;
- register int nsl;
int s, error;
error = suser(p);
@@ -272,38 +331,44 @@ slopen(dev, tp)
if (tp->t_line == SLIPDISC)
return (0);
- for (nsl = NSL, sc = sl_softc; --nsl >= 0; sc++)
- if (sc->sc_ttyp == NULL && !(sc->sc_flags & SC_STATIC)) {
- if (slinit(sc) == 0)
- return (ENOBUFS);
- tp->t_sc = (caddr_t)sc;
- sc->sc_ttyp = tp;
- sc->sc_if.if_baudrate = tp->t_ospeed;
- ttyflush(tp, FREAD | FWRITE);
+ if ((sc = slcreate()) == NULL)
+ return (ENOBUFS);
- tp->t_line = SLIPDISC;
- /*
- * We don't use t_canq or t_rawq, so reduce their
- * cblock resources to 0. Reserve enough cblocks
- * for t_outq to guarantee that we can fit a full
- * packet if the SLIP_HIWAT check allows slstart()
- * to loop. Use the same value for the cblock
- * limit since the reserved blocks should always
- * be enough. Reserving cblocks probably makes
- * the CLISTRESERVE check unnecessary and wasteful.
- */
- clist_alloc_cblocks(&tp->t_canq, 0, 0);
- clist_alloc_cblocks(&tp->t_outq,
- SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1,
- SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1);
- clist_alloc_cblocks(&tp->t_rawq, 0, 0);
+ tp->t_sc = (caddr_t)sc;
+ sc->sc_ttyp = tp;
+ sc->sc_if.if_baudrate = tp->t_ospeed;
+ ttyflush(tp, FREAD | FWRITE);
+ tp->t_line = SLIPDISC;
- s = splnet();
- if_up(&sc->sc_if);
- splx(s);
- return (0);
- }
- return (ENXIO);
+ /*
+ * We don't use t_canq or t_rawq, so reduce their
+ * cblock resources to 0. Reserve enough cblocks
+ * for t_outq to guarantee that we can fit a full
+ * packet if the SLIP_HIWAT check allows slstart()
+ * to loop. Use the same value for the cblock
+ * limit since the reserved blocks should always
+ * be enough. Reserving cblocks probably makes
+ * the CLISTRESERVE check unnecessary and wasteful.
+ */
+ clist_alloc_cblocks(&tp->t_canq, 0, 0);
+ clist_alloc_cblocks(&tp->t_outq,
+ SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1,
+ SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1);
+ clist_alloc_cblocks(&tp->t_rawq, 0, 0);
+
+ s = splnet();
+ if_up(&sc->sc_if);
+ splx(s);
+ return (0);
+}
+
+void
+sldestroy(struct sl_softc *sc) {
+ bpfdetach(&sc->sc_if);
+ if_detach(&sc->sc_if);
+ LIST_REMOVE(sc, sl_next);
+ MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE));
+ FREE(sc, M_SL);
}
/*
@@ -338,13 +403,9 @@ slclose(tp,flag)
untimeout(sl_keepalive, sc, sc->sc_kahandle);
}
if_down(&sc->sc_if);
- sc->sc_flags &= SC_STATIC;
sc->sc_ttyp = NULL;
tp->t_sc = NULL;
- MCLFREE((caddr_t)(sc->sc_ep - SLBUFSIZE));
- sc->sc_ep = 0;
- sc->sc_mp = 0;
- sc->sc_buf = 0;
+ sldestroy(sc);
}
splx(s);
return 0;
@@ -363,8 +424,8 @@ sltioctl(tp, cmd, data, flag, p)
int flag;
struct proc *p;
{
- struct sl_softc *sc = (struct sl_softc *)tp->t_sc, *nc, *tmpnc;
- int s, nsl;
+ struct sl_softc *sc = (struct sl_softc *)tp->t_sc, *nc;
+ int s, unit, wasup;
s = splimp();
switch (cmd) {
@@ -373,44 +434,36 @@ sltioctl(tp, cmd, data, flag, p)
break;
case SLIOCSUNIT:
- if (sc->sc_if.if_unit != *(u_int *)data) {
- for (nsl = NSL, nc = sl_softc; --nsl >= 0; nc++) {
- if ( nc->sc_if.if_unit == *(u_int *)data
- && nc->sc_ttyp == NULL
- ) {
- tmpnc = malloc(sizeof *tmpnc, M_TEMP,
- M_NOWAIT);
- if (tmpnc == NULL) {
+ unit = *(u_int *)data;
+ if (unit < 0) {
+ splx(s);
+ return (ENXIO);
+ }
+ if (sc->sc_if.if_unit != unit) {
+ LIST_FOREACH(nc, &sl_list, sl_next) {
+ if (nc->sc_if.if_unit == *(u_int *)data) {
splx(s);
- return (ENOMEM);
- }
- *tmpnc = *nc;
- *nc = *sc;
- nc->sc_if = tmpnc->sc_if;
- tmpnc->sc_if = sc->sc_if;
- *sc = *tmpnc;
- free(tmpnc, M_TEMP);
- if (sc->sc_if.if_flags & IFF_UP) {
- if_down(&sc->sc_if);
- if (!(nc->sc_if.if_flags & IFF_UP))
- if_up(&nc->sc_if);
- } else if (nc->sc_if.if_flags & IFF_UP)
- if_down(&nc->sc_if);
- sc->sc_flags &= ~SC_STATIC;
- sc->sc_flags |= (nc->sc_flags & SC_STATIC);
- tp->t_sc = sc = nc;
- clist_alloc_cblocks(&tp->t_outq,
- SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1,
- SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1);
- sl_compress_init(&sc->sc_comp, -1);
- goto slfound;
+ return (ENXIO);
}
}
- splx(s);
- return (ENXIO);
+
+ wasup = sc->sc_if.if_flags & IFF_UP;
+ bpfdetach(&sc->sc_if);
+ if_detach(&sc->sc_if);
+ LIST_REMOVE(sc, sl_next);
+ sc->sc_if.if_unit = unit;
+ LIST_INSERT_HEAD(&sl_list, sc, sl_next);
+ if_attach(&sc->sc_if);
+ bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
+ if (wasup)
+ if_up(&sc->sc_if);
+ else
+ if_down(&sc->sc_if);
+ clist_alloc_cblocks(&tp->t_outq,
+ SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1,
+ SLIP_HIWAT + 2 * sc->sc_if.if_mtu + 1);
}
- slfound:
- sc->sc_flags |= SC_STATIC;
+ slmarkstatic(unit);
break;
case SLIOCSKEEPAL:
@@ -470,7 +523,7 @@ sloutput(ifp, m, dst, rtp)
struct sockaddr *dst;
struct rtentry *rtp;
{
- register struct sl_softc *sc = &sl_softc[ifp->if_unit];
+ register struct sl_softc *sc = ifp->if_softc;
register struct ip *ip;
register struct ifqueue *ifq;
int s;
@@ -936,6 +989,7 @@ slioctl(ifp, cmd, data)
register struct ifaddr *ifa = (struct ifaddr *)data;
register struct ifreq *ifr = (struct ifreq *)data;
register int s, error = 0;
+ struct sl_softc *sc = ifp->if_softc;
s = splimp();
@@ -946,7 +1000,7 @@ slioctl(ifp, cmd, data)
* if.c will set the interface up even if we
* don't want it to.
*/
- if (sl_softc[ifp->if_unit].sc_ttyp == NULL) {
+ if (sc->sc_ttyp == NULL) {
ifp->if_flags &= ~IFF_UP;
}
break;
@@ -956,7 +1010,7 @@ slioctl(ifp, cmd, data)
* setting the address.
*/
if (ifa->ifa_addr->sa_family == AF_INET) {
- if (sl_softc[ifp->if_unit].sc_ttyp != NULL)
+ if (sc->sc_ttyp != NULL)
ifp->if_flags |= IFF_UP;
} else {
error = EAFNOSUPPORT;
@@ -982,7 +1036,7 @@ slioctl(ifp, cmd, data)
struct tty *tp;
ifp->if_mtu = ifr->ifr_mtu;
- tp = sl_softc[ifp->if_unit].sc_ttyp;
+ tp = sc->sc_ttyp;
if (tp != NULL)
clist_alloc_cblocks(&tp->t_outq,
SLIP_HIWAT + 2 * ifp->if_mtu + 1,
OpenPOWER on IntegriCloud