From owner-freebsd-bugs Sun Apr 2 13:40:24 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 19EAD37B652 for ; Sun, 2 Apr 2000 13:40:02 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id NAA23638; Sun, 2 Apr 2000 13:40:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11]) by hub.freebsd.org (Postfix) with SMTP id 70FAB37B652 for ; Sun, 2 Apr 2000 13:35:55 -0700 (PDT) (envelope-from dwmalone@maths.tcd.ie) Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP id ; 2 Apr 2000 21:35:54 +0100 (BST) Message-Id: <200004022135.aa84513@walton.maths.tcd.ie> Date: Sun, 2 Apr 2000 21:35:54 +0100 (BST) From: dwmalone@maths.tcd.ie Reply-To: dwmalone@maths.tcd.ie To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: kern/17758: Make the sl driver dynamically expandable. Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 17758 >Category: kern >Synopsis: Make sl driver dynamicallly expandable. >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Apr 2 13:40:01 PDT 2000 >Closed-Date: >Last-Modified: >Originator: David Malone >Release: FreeBSD 5.0-CURRENT i386 >Organization: School of Mathematics, Trinity College, Dublin, Ireland. >Environment: 4.0 and 5.0 - patch probably applies to 3-STABLE too. >Description: Currently you need to give the numbes of slip units in the kernel config file. I include a patch which allocates units dynamically as they are required. The patch is based on the tun driver and the recent ability to delete interfaces which are no longer required. One or two points of the patch are slightly tricky, so I'll explain them here. These points relate to the fact that slip driver has an ioctl which allows you to select what slip unit number you want. First, if you specifically select a unit number, that unit is marked as static and will not be handed out dynamically (ie. when SLIPDISC is first selected for a tty). This used to be stored in the sl_softc using the SC_STATIC flag, however as the new code now deallocates sl_softc structs that are no longer in use it seemed a waste to store a whole softc struct to just remember that it shouldn't be handed out dynamically. For this reason I just store an array of unit numbers which are to be considered static. The array is explanded as necessary. Second, the unit selecting code had become really complicated. It swapped the contents of two softcs, and then swapped the contained if structs back again. It seems these acrobatics aimed to ensure that the linked list of interfaces didn't get screwed up. However interfaces can now be deleted, and I wanted to deallocate the struct softcs while they were no longer in use, so this code is now somewhat more straight forward. (I don't understand why the cblocks are reallocated after selecting a new unit number, it may now be unnecessary). The other changes just relate to the fact that the old driver got the softc from sl_softc[ifp->if_unit] instead of ifp->if_softc. Other than that I've tried to use the old code as much as possible. (The only code which is a bit less efficient would be the code which finds a free unit number. This could be improved by sorting the list of static unit numbers and the list of existing slip devices, but it doesn't seem worth the extra complexity). I've given this patch some testing configuring one/both of my serial ports as slip interfaces in various ways, and it seems to work fine. >How-To-Repeat: Try to use more slip devices than you have configured. >Fix: Index: if_sl.c =================================================================== RCS file: /cvs/FreeBSD-CVS/src/sys/net/if_sl.c,v retrieving revision 1.84 diff -u -r1.84 if_sl.c --- if_sl.c 2000/02/21 08:06:18 1.84 +++ if_sl.c 2000/03/31 22:16:57 @@ -105,6 +105,8 @@ #include +static MALLOC_DEFINE(M_SL, "sl", "SLIP Interface"); + static void slattach __P((void *)); PSEUDO_SET(slattach, if_sl); @@ -168,14 +170,17 @@ #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 @@ 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 @@ { struct proc *p = curproc; /* XXX */ register struct sl_softc *sc; - register int nsl; int s, error; error = suser(p); @@ -272,38 +331,44 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ * 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 @@ 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, Index: if_slvar.h =================================================================== RCS file: /cvs/FreeBSD-CVS/src/sys/net/if_slvar.h,v retrieving revision 1.16 diff -u -r1.16 if_slvar.h --- if_slvar.h 1999/08/28 00:48:21 1.16 +++ if_slvar.h 2000/03/30 00:06:28 @@ -67,13 +67,13 @@ struct callout_handle sc_ofhandle; struct callout_handle sc_kahandle; struct slcompress sc_comp; /* tcp compression data */ + LIST_ENTRY(sl_softc) sl_next; }; /* internal flags */ #define SC_ERROR 0x0001 /* had an input error */ #define SC_OUTWAIT 0x0002 /* waiting for output fill */ #define SC_KEEPALIVE 0x0004 /* input keepalive */ -#define SC_STATIC 0x0008 /* it is static unit */ /* visible flags */ #define SC_COMPRESS IFF_LINK0 /* compress TCP traffic */ >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message