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>
index | next in thread | raw e-mail
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
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199707041802.VAA01496>
