Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Jul 1997 21:02:02 +0300 (EET DST)
From:      Ruslan Ermilov <ru@ucb.crimea.ua>
To:        freebsd-hackers@freebsd.org
Cc:        freebsd-bugs@freebsd.org
Subject:   SLIP DRIVER needs to be rewritten!!!
Message-ID:  <199707041802.VAA01496@relay.ucb.crimea.ua>

next in thread | raw e-mail | index | archive | help
Hi!

I'm using 2.2.1-RELEASE of FreeBSD now. I have a proposal of how to
solve the problem when SC_STATIC flag is used.

First, I'll try to explain the problem(s):

I've configured 4 slip units in kernel and need to attach two slip
interfaces. And I WANT to use STATIC FEATURE of the driver (using
-S switch of slattach).


Well, I run `slattach -s 38400 /dev/cuaa0 -S 1' and here is what I see:

1) netstat -in shows the sl0 and sl1 in the reversed order.
   This is because slopen() allocates first free element of slsoftc[],
   i.e. slsoftc[0], and then, when slattach proceeds the -S1 switch,
   sltioctl(SLIOCSUNIT) assigns to it "slip unit 1" and sets on it
   SC_STATIC flag.
2) `ifconfig -a' shows the sl0 and sl1 in the normal order.
3) what happens when I try to `ifconfig sl1 x.x.x.x y.y.y.y' is that
   ifconfig configures sl0 instead of sl1. (To be more exactly,
   `ifconfig -a' shows that sl0 (but not sl1) has been configured.
4) Moreover, when I then kill my slattach process and then start it
   again slopen() skips slsoftc[0] because it has SC_STATIC flag set.
   Note that SC_STATIC flag is not cleared in slclose() to avoid
   allocation of this unit to the "dynamic slip allocation requests"
   (i.e. when `slattach' started without -S switch, or when `sliplogin'
   is started).
   So, when I kill and start `slattach' 4 times (i.e. the number of
   slip units configured), slopen() returns ENXIO.
   If you don't believe me, try to run your kernel.GENERIC (it has
   been compiled with only 1 slip unit), then start `slattach' with
   -S switch, kill it, and then try to start `slattach' again.
   Oops... You'll believe me now ;-)

In my point of view, there is the WRONG LOGIC in the if_sl.c.
My patch uses the following ideas:

1) Do not `attach the given tty to the first available sl unit' when
   in the slopen().
2) Attach the SPECIFIED sl unit to the tty if the sltioctl(SLIOCSUNIT)
   has been invoked.
3) Or attach `first free, not SC_STATIC sl unit' when the
   sltioctl(SLIOCGUNIT) has been invoked.

The driver version which I've modified is:
$Id: if_sl.c,v 1.45.2.1 1997/03/11 19:40:37 bde Exp $

I.e. this is the current version of this driver in RELENG_2_2 branch.

My diff is:

[**********cut here**********]
--- if_sl.c.orig	Thu Jul  3 11:10:34 1997
+++ if_sl.c	Thu Jul  3 11:17:12 1997
@@ -186,6 +186,7 @@
 static struct mbuf *sl_btom __P((struct sl_softc *, int));
 static timeout_t sl_keepalive;
 static timeout_t sl_outfill;
+static int	slalloc __P((int, struct tty *));
 static int	slclose __P((struct tty *,int));
 static int	slinput __P((int, struct tty *));
 static int	slioctl __P((struct ifnet *, int, caddr_t));
@@ -265,8 +266,6 @@
 	register struct tty *tp;
 {
 	struct proc *p = curproc;		/* XXX */
-	register struct sl_softc *sc;
-	register int nsl;
 	int s, error;
 
 	error = suser(p->p_ucred, &p->p_acflag);
@@ -276,38 +275,62 @@
 	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);
-
-			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);
-
-			s = splnet();
-			if_up(&sc->sc_if);
-			splx(s);
-			return (0);
-		}
-	return (ENXIO);
+	ttyflush(tp, FREAD | FWRITE);
+
+	tp->t_line = SLIPDISC;
+	return (0);
+}
+
+static int
+slalloc(unit, tp)
+	int unit;
+	struct tty *tp;
+{
+	register struct sl_softc *sc;
+	int s, static_unit = 1;
+
+	if (unit == -1) {
+		static_unit = 0;
+		for (unit = 0; unit < NSL; unit++)
+			if (sl_softc[unit].sc_ttyp == NULL &&
+				!(sl_softc[unit].sc_flags & SC_STATIC) )
+				break;
+	}
+
+	if (unit < 0 || unit >= NSL || tp->t_sc != NULL)
+		return (ENXIO);
+
+	sc = &sl_softc[unit];
+	if (sc->sc_ttyp != NULL)
+		return (EBUSY);
+	if (slinit(sc) == 0)
+		return (ENOBUFS);
+	
+	tp->t_sc = (caddr_t)sc;
+	sc->sc_ttyp = tp;
+	sc->sc_if.if_baudrate = tp->t_ospeed;
+	if (static_unit != 0)
+		sc->sc_flags |= SC_STATIC;
+	/*
+	 * 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);
 }
 
 /*
@@ -368,34 +391,34 @@
 	struct proc *p;
 {
 	struct sl_softc *sc = (struct sl_softc *)tp->t_sc, *nc;
-	int s, nsl;
+	int s, nsl, ret;
+
+	if (sc == NULL && (cmd != SLIOCGUNIT && cmd != SLIOCSUNIT))
+		return (ENXIO);
 
 	s = splimp();
 	switch (cmd) {
 	case SLIOCGUNIT:
+		if (sc == NULL) {
+			ret = slalloc(-1, tp);
+			if (ret != 0) {
+				splx(s);
+				return (ret);
+			}
+			sc = (struct sl_softc *)tp->t_sc;
+		}
 		*(int *)data = sc->sc_if.if_unit;
 		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
-				   ) {
-					nc->sc_if.if_unit = sc->sc_if.if_unit;
-					nc->sc_flags &= ~SC_STATIC;
-					nc->sc_flags |= sc->sc_flags & SC_STATIC;
-					sc->sc_if.if_unit = *(u_int *)data;
-					goto slfound;
-				}
-			}
-			splx(s);
-			return (ENXIO);
-		}
-	slfound:
-		sc->sc_flags |= SC_STATIC;
+		if (sc == NULL)
+			ret = slalloc(*(int *)data, tp);
+		else
+			ret = EEXIST;
+		splx(s);
+		return (ret);
 		break;
-
+			
 	case SLIOCSKEEPAL:
 		sc->sc_keepalive = *(u_int *)data * hz;
 		if (sc->sc_keepalive) {

[**********cut here**********]


Thanks in advance,
---
Ruslan A. Ermilov	System Administrator
ru@ucb.crimea.ua	United Commercial Bank
+380-652-247 647	Simferopol, Crimea




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199707041802.VAA01496>