summaryrefslogtreecommitdiffstats
path: root/sys/net/ppp_tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/ppp_tty.c')
-rw-r--r--sys/net/ppp_tty.c255
1 files changed, 143 insertions, 112 deletions
diff --git a/sys/net/ppp_tty.c b/sys/net/ppp_tty.c
index 422a360..c6f07ef 100644
--- a/sys/net/ppp_tty.c
+++ b/sys/net/ppp_tty.c
@@ -62,7 +62,7 @@
* Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
* Cleaned up a lot of the mbuf-related code to fix bugs that
* caused system crashes and packet corruption. Changed pppstart
- * so that it doesn't just give up with a collision if the whole
+ * so that it doesn't just give up with a "collision" if the whole
* packet doesn't fit in the output ring buffer.
*
* Added priority queueing for interactive IP packets, following
@@ -70,9 +70,7 @@
* Paul Mackerras (paulus@cs.anu.edu.au).
*/
-/* $Id: ppp_tty.c,v 1.20 1997/06/18 02:50:40 brian Exp $ */
-/* from Id: ppp_tty.c,v 1.3 1995/08/16 01:36:40 paulus Exp */
-/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
+/* $Id: ppp_tty.c,v 1.21 1997/06/22 02:19:52 brian Exp $ */
#include "ppp.h"
#if NPPP > 0
@@ -91,12 +89,13 @@
#include <sys/kernel.h>
#include <sys/conf.h>
+
#undef KERNEL /* so that vnode.h does not try to include vnode_if.h */
# include <sys/vnode.h>
#define KERNEL
-#ifdef i386 /* fiddle with the spl locking */
-# include <i386/isa/intr_machdep.h>
+#ifdef i386
+#include <i386/isa/intr_machdep.h>
#endif
#include <net/if.h>
@@ -109,6 +108,9 @@
#include <net/slcompress.h>
#endif
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
#include <net/ppp_defs.h>
#include <net/if_ppp.h>
#include <net/if_pppvar.h>
@@ -158,6 +160,7 @@ void pppasyncattach __P((void *));
/* This is a FreeBSD-2.X kernel. */
#define CCOUNT(q) ((q)->c_cc)
+#define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
#define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
/*
@@ -213,10 +216,10 @@ pppopen(dev, tp)
register struct ppp_softc *sc;
int error, s;
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
if (tp->t_line == PPPDISC) {
sc = (struct ppp_softc *) tp->t_sc;
@@ -283,7 +286,7 @@ pppclose(tp, flag)
register struct ppp_softc *sc;
int s;
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
ttyflush(tp, FREAD | FWRITE);
clist_free_cblocks(&tp->t_canq);
clist_free_cblocks(&tp->t_outq);
@@ -309,7 +312,7 @@ pppasyncrelinq(sc)
{
int s;
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
if (sc->sc_outm) {
m_freem(sc->sc_outm);
sc->sc_outm = NULL;
@@ -335,7 +338,7 @@ register struct ppp_softc *sc;
register struct tty *tp = (struct tty *) sc->sc_devp;
int s;
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
if (tp != NULL)
clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
sc->sc_if.if_mtu + PPP_HIWAT);
@@ -344,7 +347,7 @@ register struct ppp_softc *sc;
/*
* Line specific (tty) read routine.
- * called at no spl from the device driver in the response to user-level
+ * called at zero spl from the device driver in the response to user-level
* reads on the tty file descriptor (ie: pppd).
*/
static int
@@ -364,7 +367,7 @@ pppread(tp, uio, flag)
* Loop waiting for input, checking that nothing disasterous
* happens in the meantime.
*/
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
for (;;) {
if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
splx(s);
@@ -380,7 +383,7 @@ pppread(tp, uio, flag)
splx(s);
return (EWOULDBLOCK);
}
- error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
+ error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, "ttyin", 0);
if (error) {
splx(s);
return error;
@@ -395,7 +398,7 @@ pppread(tp, uio, flag)
splx(s);
for (m = m0; m && uio->uio_resid; m = m->m_next)
- if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
+ if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
break;
m_freem(m0);
return (error);
@@ -403,7 +406,7 @@ pppread(tp, uio, flag)
/*
* Line specific (tty) write routine.
- * called at no spl from the device driver in the response to user-level
+ * called at zero spl from the device driver in the response to user-level
* writes on the tty file descriptor (ie: pppd).
*/
static int
@@ -427,7 +430,7 @@ pppwrite(tp, uio, flag)
uio->uio_resid < PPP_HDRLEN)
return (EMSGSIZE);
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
MGET(m, M_WAIT, MT_DATA);
if ((*mp = m) == NULL) {
@@ -441,7 +444,7 @@ pppwrite(tp, uio, flag)
len = M_TRAILINGSPACE(m);
if (len > uio->uio_resid)
len = uio->uio_resid;
- if (error = uiomove(mtod(m, u_char *), len, uio)) {
+ if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
m_freem(m0);
splx(s);
return (error);
@@ -468,8 +471,9 @@ pppwrite(tp, uio, flag)
static int
ppptioctl(tp, cmd, data, flag, p)
struct tty *tp;
+ int cmd;
caddr_t data;
- int cmd, flag;
+ int flag;
struct proc *p;
{
struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
@@ -481,7 +485,7 @@ ppptioctl(tp, cmd, data, flag, p)
error = 0;
switch (cmd) {
case PPPIOCSASYNCMAP:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
break;
sc->sc_asyncmap[0] = *(u_int *)data;
break;
@@ -491,7 +495,7 @@ ppptioctl(tp, cmd, data, flag, p)
break;
case PPPIOCSRASYNCMAP:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
break;
sc->sc_rasyncmap = *(u_int *)data;
break;
@@ -501,9 +505,9 @@ ppptioctl(tp, cmd, data, flag, p)
break;
case PPPIOCSXASYNCMAP:
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
break;
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
@@ -577,70 +581,20 @@ pppfcs(fcs, cp, len)
}
/*
- * This gets called from pppoutput when a new packet is
- * put on a queue.
+ * This gets called at splsoftnet from if_ppp.c at various times
+ * when there is data ready to be sent.
*/
static void
pppasyncstart(sc)
register struct ppp_softc *sc;
{
register struct tty *tp = (struct tty *) sc->sc_devp;
- int s;
-
- s = spltty(); /* raise from splnet to spltty */
- pppstart(tp);
- splx(s);
-}
-
-/*
- * This gets called when a received packet is placed on
- * the inq. The pppd daemon is to be woken up to do a read().
- */
-static void
-pppasyncctlp(sc)
- struct ppp_softc *sc;
-{
- struct tty *tp;
- int s;
-
- /* Put a placeholder byte in canq for ttselect()/ttnread(). */
- s = spltty(); /* raise from splnet to spltty */
- tp = (struct tty *) sc->sc_devp;
- putc(0, &tp->t_canq);
- ttwakeup(tp);
- splx(s);
-}
-
-/*
- * Start output on async tty interface. Get another datagram
- * to send from the interface queue and start sending it.
- *
- * Called from tty system at splsofttty() or spltty().
- * Called from the upper half at softnet, raised to spltty via asyncstart.
- *
- * Harmless to be called while the upper netisr code is preempted, but we
- * do not want to be preempted by it again.
- */
-static int
-pppstart(tp)
- register struct tty *tp;
-{
- register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
register struct mbuf *m;
register int len;
register u_char *start, *stop, *cp;
- int n, s, ndone, done, idle;
+ int n, ndone, done, idle;
struct mbuf *m2;
-
- if ((tp->t_state & TS_CONNECTED) == 0
- || sc == NULL || tp != (struct tty *) sc->sc_devp
- || tp->t_line != PPPDISC) {
- if (tp->t_oproc != NULL)
- (*tp->t_oproc)(tp);
- return 0;
- }
-
- s = spltty(); /* in case.. do not want netisrs to preempt us */
+ int s;
idle = 0;
while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
@@ -665,12 +619,13 @@ pppstart(tp)
* the line may have been idle for some time.
*/
if (CCOUNT(&tp->t_outq) == 0) {
- ++sc->sc_bytessent;
+ ++sc->sc_stats.ppp_obytes;
(void) putc(PPP_FLAG, &tp->t_outq);
}
/* Calculate the FCS for the first mbuf's worth. */
sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
+ sc->sc_if.if_lastchange = time;
}
for (;;) {
@@ -691,24 +646,27 @@ pppstart(tp)
ndone = n - b_to_q(start, n, &tp->t_outq);
len -= ndone;
start += ndone;
- sc->sc_bytessent += ndone;
+ sc->sc_stats.ppp_obytes += ndone;
if (ndone < n)
break; /* packet doesn't fit */
}
/*
* If there are characters left in the mbuf,
- * the first one must be special..
+ * the first one must be special.
* Put it out in a different form.
*/
if (len) {
+ s = spltty();
if (putc(PPP_ESCAPE, &tp->t_outq))
break;
if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
(void) unputc(&tp->t_outq);
+ splx(s);
break;
}
- sc->sc_bytessent += 2;
+ splx(s);
+ sc->sc_stats.ppp_obytes += 2;
start++;
len--;
}
@@ -748,6 +706,7 @@ pppstart(tp)
* Try to output the FCS and flag. If the bytes
* don't all fit, back out.
*/
+ s = spltty();
for (q = endseq; q < p; ++q)
if (putc(*q, &tp->t_outq)) {
done = 0;
@@ -755,7 +714,9 @@ pppstart(tp)
unputc(&tp->t_outq);
break;
}
- sc->sc_bytessent += q - endseq;
+ splx(s);
+ if (done)
+ sc->sc_stats.ppp_obytes += q - endseq;
}
if (!done) {
@@ -770,28 +731,24 @@ pppstart(tp)
m = m2;
if (m == NULL) {
/* Finished a packet */
- sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes = sc->sc_bytessent;
break;
}
sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
}
/*
- * Here we have either finished a packet (m == NULL)
- * or filled up the output queue (m != NULL).
+ * If m == NULL, we have finished a packet.
+ * If m != NULL, we've either done as much work this time
+ * as we need to, or else we've filled up the output queue.
*/
sc->sc_outm = m;
if (m)
break;
}
- /*
- * Call output process whether or not there is any output.
- * We are being called in lieu of ttstart and must do what it would.
- */
- if (tp->t_oproc != NULL)
- (*tp->t_oproc)(tp);
+ /* Call pppstart to start output again if necessary. */
+ s = spltty();
+ pppstart(tp);
/*
* This timeout is needed for operation on a pseudo-tty,
@@ -802,7 +759,58 @@ pppstart(tp)
timeout(ppp_timeout, (void *) sc, 1);
sc->sc_flags |= SC_TIMEOUT;
}
+
+ splx(s);
+}
+
+/*
+ * This gets called when a received packet is placed on
+ * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
+ */
+static void
+pppasyncctlp(sc)
+ struct ppp_softc *sc;
+{
+ struct tty *tp;
+ int s;
+
+ /* Put a placeholder byte in canq for ttselect()/ttnread(). */
+ s = spltty();
+ tp = (struct tty *) sc->sc_devp;
+ putc(0, &tp->t_canq);
+ ttwakeup(tp);
splx(s);
+}
+
+/*
+ * Start output on async tty interface. If the transmit queue
+ * has drained sufficiently, arrange for pppasyncstart to be
+ * called later at splsoftnet.
+ * Called at spltty or higher.
+ */
+int
+pppstart(tp)
+ register struct tty *tp;
+{
+ register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
+
+ /*
+ * If there is stuff in the output queue, send it now.
+ * We are being called in lieu of ttstart and must do what it would.
+ */
+ if (tp->t_oproc != NULL)
+ (*tp->t_oproc)(tp);
+
+ /*
+ * If the transmit queue has drained and the tty has not hung up
+ * or been disconnected from the ppp unit, then tell if_ppp.c that
+ * we need more output.
+ */
+ if (CCOUNT(&tp->t_outq) < PPP_LOWAT
+ && !((tp->t_state & TS_CONNECTED) == 0)
+ && sc != NULL && tp == (struct tty *) sc->sc_devp) {
+ ppp_restart(sc);
+ }
return 0;
}
@@ -818,7 +826,7 @@ ppp_timeout(x)
struct tty *tp = (struct tty *) sc->sc_devp;
int s;
- s = spltty(); /* also netisr's, including NETISR_PPP */
+ s = spltty();
sc->sc_flags &= ~SC_TIMEOUT;
pppstart(tp);
splx(s);
@@ -833,9 +841,7 @@ pppgetm(sc)
{
struct mbuf *m, **mp;
int len;
- int s;
- s = spltty(); /* also netisr's, including NETISR_PPP */
mp = &sc->sc_m;
for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
if ((m = *mp) == NULL) {
@@ -848,7 +854,6 @@ pppgetm(sc)
len -= M_DATASIZE(m);
mp = &m->m_next;
}
- splx(s);
}
/*
@@ -877,9 +882,8 @@ pppinput(c, tp)
if (sc == NULL || tp != (struct tty *) sc->sc_devp)
return 0;
- s = spltty(); /* also netisr's, including NETISR_PPP */
++tk_nin;
- ++sc->sc_bytesrcvd;
+ ++sc->sc_stats.ppp_ibytes;
if ((tp->t_state & TS_CONNECTED) == 0) {
if (sc->sc_flags & SC_DEBUG)
@@ -897,6 +901,26 @@ pppinput(c, tp)
c &= TTY_CHARMASK;
+ /*
+ * Handle software flow control of output.
+ */
+ if (tp->t_iflag & IXON) {
+ if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
+ if ((tp->t_state & TS_TTSTOP) == 0) {
+ tp->t_state |= TS_TTSTOP;
+ (*cdevsw[major(tp->t_dev)]->d_stop)(tp, 0);
+ }
+ return 0;
+ }
+ if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
+ tp->t_state &= ~TS_TTSTOP;
+ if (tp->t_oproc != NULL)
+ (*tp->t_oproc)(tp);
+ return 0;
+ }
+ }
+
+ s = spltty();
if (c & 0x80)
sc->sc_flags |= SC_RCV_B7_1;
else
@@ -905,6 +929,7 @@ pppinput(c, tp)
sc->sc_flags |= SC_RCV_ODDP;
else
sc->sc_flags |= SC_RCV_EVNP;
+ splx(s);
if (sc->sc_flags & SC_LOG_RAWIN)
ppplogchar(sc, c);
@@ -912,7 +937,6 @@ pppinput(c, tp)
if (c == PPP_FLAG) {
ilen = sc->sc_ilen;
sc->sc_ilen = 0;
- sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
if (sc->sc_rawin_count > 0)
ppplogchar(sc, -1);
@@ -922,13 +946,15 @@ pppinput(c, tp)
* abort sequence "}~".
*/
if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
- || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
+ || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
+ s = spltty();
sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
if (sc->sc_flags & SC_DEBUG)
- printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
- sc->sc_fcs);
+ printf("ppp%d: bad fcs %x, pkt len %d\n",
+ sc->sc_if.if_unit, sc->sc_fcs, ilen);
sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
} else
sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
splx(s);
@@ -939,10 +965,12 @@ pppinput(c, tp)
if (ilen) {
if (sc->sc_flags & SC_DEBUG)
printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
+ s = spltty();
sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
sc->sc_flags |= SC_PKTLOST;
+ splx(s);
}
- splx(s);
return 0;
}
@@ -963,25 +991,26 @@ pppinput(c, tp)
sc->sc_mc->m_next = NULL;
ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
- sc->sc_flags &= ~SC_PKTLOST;
+ if (sc->sc_flags & SC_PKTLOST) {
+ s = spltty();
+ sc->sc_flags &= ~SC_PKTLOST;
+ splx(s);
+ }
pppgetm(sc);
- splx(s);
return 0;
}
if (sc->sc_flags & SC_FLUSH) {
if (sc->sc_flags & SC_LOG_FLUSH)
ppplogchar(sc, c);
- splx(s);
return 0;
}
- if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
- splx(s);
+ if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
return 0;
- }
+ s = spltty();
if (sc->sc_flags & SC_ESCAPED) {
sc->sc_flags &= ~SC_ESCAPED;
c ^= PPP_TRANS;
@@ -990,6 +1019,7 @@ pppinput(c, tp)
splx(s);
return 0;
}
+ splx(s);
/*
* Initialize buffer on first octet received.
@@ -1075,17 +1105,18 @@ pppinput(c, tp)
++m->m_len;
*sc->sc_mp++ = c;
sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
- splx(s);
return 0;
flush:
if (!(sc->sc_flags & SC_FLUSH)) {
+ s = spltty();
sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
sc->sc_flags |= SC_FLUSH;
+ splx(s);
if (sc->sc_flags & SC_LOG_FLUSH)
ppplogchar(sc, c);
}
- splx(s);
return 0;
}
@@ -1099,7 +1130,7 @@ ppplogchar(sc, c)
if (c >= 0)
sc->sc_rawin[sc->sc_rawin_count++] = c;
if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
- || c < 0 && sc->sc_rawin_count > 0) {
+ || (c < 0 && sc->sc_rawin_count > 0)) {
printf("ppp%d input: %*D", sc->sc_if.if_unit,
sc->sc_rawin_count, sc->sc_rawin, " ");
sc->sc_rawin_count = 0;
OpenPOWER on IntegriCloud