From a471bdc20d7f993fc126b765c8c3dacbc902fa68 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 8 Dec 1994 00:32:59 +0000 Subject: [PATCH] various fixes from netbsd port; added ppp_requeue and sc_relinq --- ultrix/if_ppp.c | 178 ++++++++++++++++++++++++++++------------------- ultrix/ppp_tty.c | 74 +++++++++++++++----- 2 files changed, 164 insertions(+), 88 deletions(-) diff --git a/ultrix/if_ppp.c b/ultrix/if_ppp.c index 7400315..981d131 100644 --- a/ultrix/if_ppp.c +++ b/ultrix/if_ppp.c @@ -72,7 +72,7 @@ * Robert Olsson and Paul Mackerras. */ -/* $Id: if_ppp.c,v 1.3 1994/11/28 01:38:25 paulus Exp $ */ +/* $Id: if_ppp.c,v 1.4 1994/12/08 00:32:59 paulus Exp $ */ /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ #include "ppp.h" @@ -127,6 +127,7 @@ int pppoutput __P((struct ifnet *ifp, struct mbuf *m0, int pppsioctl __P((struct ifnet *ifp, int cmd, caddr_t data)); void pppintr __P((void)); +static void ppp_requeue __P((struct ppp_softc *)); static void ppp_outpkt __P((struct ppp_softc *)); static int ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd)); static void ppp_ccp_closed __P((struct ppp_softc *)); @@ -214,17 +215,17 @@ pppalloc(pid) for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) if (sc->sc_xfer == pid) { sc->sc_xfer = 0; - break; + return sc; } - if (nppp >= NPPP) - for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) - if (sc->sc_devp == NULL) - break; + for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++) + if (sc->sc_devp == NULL) + break; if (nppp >= NPPP) return NULL; sc->sc_flags = 0; sc->sc_mru = PPP_MRU; + sc->sc_relinq = NULL; #ifdef VJC sl_compress_init(&sc->sc_comp); #endif @@ -234,13 +235,14 @@ pppalloc(pid) #endif /* PPP_COMPRESS */ for (i = 0; i < NUM_NP; ++i) sc->sc_npmode[i] = NPMODE_ERROR; - sc->sc_if.if_flags |= IFF_RUNNING; + sc->sc_npqueue = NULL; + sc->sc_npqtail = &sc->sc_npqueue; return sc; } /* - * Deallocate a ppp unit. + * Deallocate a ppp unit. Must be called at splnet or higher. */ void pppdealloc(sc) @@ -270,6 +272,10 @@ pppdealloc(sc) break; m_freem(m); } + while ((m = sc->sc_npqueue) != NULL) { + sc->sc_npqueue = m->m_nextpkt; + m_freem(m); + } if (sc->sc_togo != NULL) { m_freem(sc->sc_togo); sc->sc_togo = NULL; @@ -425,8 +431,10 @@ pppioctl(sc, cmd, data, flag) if (npi->mode != sc->sc_npmode[npx]) { s = splimp(); sc->sc_npmode[npx] = npi->mode; - if (npi->mode != NPMODE_QUEUE) + if (npi->mode != NPMODE_QUEUE) { + ppp_requeue(sc); (*sc->sc_start)(sc); + } splx(s); } } @@ -547,8 +555,10 @@ pppoutput(ifp, m0, dst) /* * Compute PPP header. + * We use the m_context field of the mbuf to indicate whether + * the packet should go on the fast queue. */ - ifq = &ifp->if_snd; + m0->m_context = 0; switch (dst->sa_family) { #ifdef INET case AF_INET: @@ -564,7 +574,7 @@ pppoutput(ifp, m0, dst) if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) { register int p = ntohl(((int *)ip)[ip->ip_hl]); if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16)) - ifq = &sc->sc_fastq; + m0->m_context = 1; } break; #endif @@ -633,20 +643,23 @@ pppoutput(ifp, m0, dst) * Put the packet on the appropriate queue. */ s = splimp(); /* splnet should be OK now */ - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - splx(s); - sc->sc_if.if_oerrors++; - error = ENOBUFS; - goto bad; - } - IF_ENQUEUE(ifq, m0); - - /* - * Tell the device to send it out. - */ - if (mode == NPMODE_PASS) + if (mode == NPMODE_QUEUE) { + /* XXX we should limit the number of packets on this queue */ + *sc->sc_npqtail = m0; + m0->m_nextpkt = NULL; + sc->sc_npqtail = &m0->m_nextpkt; + } else { + ifq = m0->m_context? &sc->sc_fastq: &ifp->if_snd; + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + splx(s); + sc->sc_if.if_oerrors++; + error = ENOBUFS; + goto bad; + } + IF_ENQUEUE(ifq, m0); (*sc->sc_start)(sc); + } splx(s); return (0); @@ -656,6 +669,57 @@ bad: return (error); } +/* + * After a change in the NPmode for some NP, move packets from the + * npqueue to the send queue or the fast queue as appropriate. + * Should be called at splimp (actually splnet would probably suffice). + */ +static void +ppp_requeue(sc) + struct ppp_softc *sc; +{ + struct mbuf *m, **mpp; + struct ifqueue *ifq; + enum NPmode mode; + + for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) { + switch (PPP_PROTOCOL(mtod(m, u_char *))) { + case PPP_IP: + mode = sc->sc_npmode[NP_IP]; + break; + default: + mode = NPMODE_PASS; + } + + switch (mode) { + case NPMODE_PASS: + /* + * This packet can now go on one of the queues to be sent. + */ + *mpp = m->m_nextpkt; + m->m_nextpkt = NULL; + ifq = (m->m_flags & M_HIGHPRI)? &sc->sc_fastq: &sc->sc_if.if_snd; + if (IF_QFULL(ifq)) { + IF_DROP(ifq); + sc->sc_if.if_oerrors++; + } else + IF_ENQUEUE(ifq, m); + break; + + case NPMODE_DROP: + case NPMODE_ERROR: + *mpp = m->m_nextpkt; + m_freem(m); + break; + + case NPMODE_QUEUE: + mpp = &m->m_nextpkt; + break; + } + } + sc->sc_npqtail = mpp; +} + /* * Get a packet to send. This procedure is intended to be called * at spltty()/splimp(), so it takes little time. If there isn't @@ -668,6 +732,7 @@ ppp_dequeue(sc) struct ppp_softc *sc; { struct mbuf *m; + int s = splimp(); m = sc->sc_togo; if (m) { @@ -676,6 +741,7 @@ ppp_dequeue(sc) */ sc->sc_togo = NULL; sc->sc_flags |= SC_TBUSY; + splx(s); return m; } /* @@ -683,6 +749,7 @@ ppp_dequeue(sc) */ sc->sc_flags &= ~SC_TBUSY; schednetisr(NETISR_PPP); + splx(s); return NULL; } @@ -696,6 +763,7 @@ pppintr() int i, s; struct mbuf *m; + s = splnet(); sc = ppp_softc; for (i = 0; i < NPPP; ++i, ++sc) { if (!(sc->sc_flags & SC_TBUSY) && sc->sc_togo == NULL @@ -708,6 +776,7 @@ pppintr() ppp_inproc(sc, m); } } + splx(s); } /* @@ -720,60 +789,21 @@ ppp_outpkt(sc) struct ppp_softc *sc; { int s; - struct mbuf *m, *mp, **mpp; + struct mbuf *m, *mp; u_char *cp; int address, control, protocol; - struct ifqueue *ifq; enum NPmode mode; /* - * Scan through the send queues looking for a packet - * which can be sent: first the fast queue, then the normal queue. + * Grab a packet to send: first try the fast queue, then the + * normal queue. */ - ifq = &sc->sc_fastq; - for (;;) { - mpp = &ifq->ifq_head; - mp = NULL; - while ((m = *mpp) != NULL) { - switch (PPP_PROTOCOL(mtod(m, u_char *))) { - case PPP_IP: - mode = sc->sc_npmode[NP_IP]; - break; - default: - mode = NPMODE_PASS; - } - if (mode == NPMODE_PASS) - break; - switch (mode) { - case NPMODE_DROP: - case NPMODE_ERROR: - *mpp = m->m_act; - --ifq->ifq_len; - m_freem(m); - break; - case NPMODE_QUEUE: - mpp = &m->m_act; - mp = m; - break; - } - } - if (m != NULL) - break; - - if (ifq == &sc->sc_if.if_snd) - break; - /* Finished the fast queue; do the normal queue. */ - ifq = &sc->sc_if.if_snd; - } - + IF_DEQUEUE(&sc->sc_fastq, m); + if (m == NULL) + IF_DEQUEUE(&sc->sc_if.if_snd, m); if (m == NULL) return; - if ((*mpp = m->m_act) == NULL) - ifq->ifq_tail = mp; - m->m_act = NULL; - --ifq->ifq_len; - /* * Extract the ppp header of the new packet. * The ppp header will be in one mbuf. @@ -948,7 +978,7 @@ ppp_ccp(sc, m, rcvd) if (sc->sc_rc_state != NULL && (*sc->sc_rcomp->decomp_init) (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN, - sc->sc_if.if_unit, sc->sc_mru, + sc->sc_if.if_unit, 0, sc->sc_mru, sc->sc_flags & SC_DEBUG)) { s = splimp(); sc->sc_flags |= SC_DECOMP_RUN; @@ -999,7 +1029,7 @@ ppp_ccp_closed(sc) * PPP packet input routine. * The caller has checked and removed the FCS and has inserted * the address/control bytes and the protocol high byte if they - * were omitted. Should be called at splimp/spltty. + * were omitted. */ void ppppktin(sc, m, lost) @@ -1007,9 +1037,12 @@ ppppktin(sc, m, lost) struct mbuf *m; int lost; { + int s = splimp(); + m->m_context = lost; IF_ENQUEUE(&sc->sc_rawq, m); schednetisr(NETISR_PPP); + splx(s); } /* @@ -1023,7 +1056,7 @@ ppp_inproc(sc, m) struct ppp_softc *sc; struct mbuf *m; { - struct ifqueue *inq, *lock; + struct ifqueue *inq; int s, ilen, xlen, proto, rv; u_char *cp, adrs, ctrl; struct mbuf *mp, *dmp, *pc; @@ -1207,6 +1240,7 @@ ppp_inproc(sc, m) bpf_mtap(sc->sc_bpf, m); #endif + rv = 0; switch (proto) { #ifdef INET case PPP_IP: diff --git a/ultrix/ppp_tty.c b/ultrix/ppp_tty.c index eacaf16..a1d8af7 100644 --- a/ultrix/ppp_tty.c +++ b/ultrix/ppp_tty.c @@ -1,5 +1,6 @@ /* - * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver. + * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous + * tty devices. * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. @@ -72,7 +73,7 @@ * Robert Olsson and Paul Mackerras. */ -/* $Id: ppp_tty.c,v 1.2 1994/11/28 01:38:59 paulus Exp $ */ +/* $Id: ppp_tty.c,v 1.3 1994/12/08 00:32:59 paulus Exp $ */ /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ #include "ppp.h" @@ -120,6 +121,7 @@ int pppstart __P((struct tty *tp)); static u_short pppfcs __P((u_short fcs, u_char *cp, int len)); static void pppasyncstart __P((struct ppp_softc *)); static void pppasyncctlp __P((struct ppp_softc *)); +static void pppasyncrelinq __P((struct ppp_softc *)); static void pppgetm __P((struct ppp_softc *sc)); static void pppdumpb __P((u_char *b, int l)); static void ppplogchar __P((struct ppp_softc *, int)); @@ -182,14 +184,12 @@ pppopen(dev, tp) if ((sc = pppalloc(p->p_pid)) == NULL) return ENXIO; - if (sc->sc_outm != NULL) { - m_freem(sc->sc_outm); - sc->sc_outm = NULL; - } - - pppgetm(sc); + if (sc->sc_relinq) + (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */ + s = splimp(); sc->sc_ilen = 0; + sc->sc_m = NULL; bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); sc->sc_asyncmap[0] = 0xffffffff; sc->sc_asyncmap[3] = 0x60000000; @@ -197,9 +197,14 @@ pppopen(dev, tp) sc->sc_devp = (void *) tp; sc->sc_start = pppasyncstart; sc->sc_ctlp = pppasyncctlp; + sc->sc_relinq = pppasyncrelinq; + sc->sc_outm = NULL; + pppgetm(sc); + sc->sc_if.if_flags |= IFF_RUNNING; tp->t_sc = (caddr_t) sc; ttyflush(tp, FREAD | FWRITE); + splx(s); return (0); } @@ -221,14 +226,11 @@ pppclose(tp, flag) ttywflush(tp); s = splimp(); /* paranoid; splnet probably ok */ tp->t_line = 0; - sc = (struct ppp_softc *)tp->t_sc; + sc = (struct ppp_softc *) tp->t_sc; if (sc != NULL) { tp->t_sc = NULL; if (tp == (struct tty *) sc->sc_devp) { - m_freem(sc->sc_outm); - sc->sc_outm = NULL; - m_freem(sc->sc_m); - sc->sc_m = NULL; + pppasyncrelinq(sc); pppdealloc(sc); } } @@ -236,6 +238,27 @@ pppclose(tp, flag) return 0; } +/* + * Relinquish the interface unit to another device. + */ +static void +pppasyncrelinq(sc) + struct ppp_softc *sc; +{ + int s; + + s = splimp(); + if (sc->sc_outm) { + m_freem(sc->sc_outm); + sc->sc_outm = NULL; + } + if (sc->sc_m) { + m_freem(sc->sc_m); + sc->sc_m = NULL; + } + splx(s); +} + /* * Line specific (tty) read routine. */ @@ -341,7 +364,7 @@ ppptioctl(tp, cmd, data, flag) int cmd, flag; { struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; - int error; + int error, s; if (sc == NULL || tp != (struct tty *) sc->sc_devp) return -1; @@ -371,10 +394,12 @@ ppptioctl(tp, cmd, data, flag) case PPPIOCSXASYNCMAP: if (!suser()) return EPERM; + 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 */ sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */ + splx(s); break; case PPPIOCGXASYNCMAP: @@ -451,8 +476,11 @@ pppasyncstart(sc) register struct ppp_softc *sc; { register struct tty *tp = (struct tty *) sc->sc_devp; + int s; + s = splimp(); pppstart(tp); + splx(s); } /* @@ -517,8 +545,11 @@ pppstart(tp) * Get another packet to be sent. */ m = ppp_dequeue(sc); - if (m == NULL) + if (m == NULL) { + if (tp->t_oproc != NULL) + (*tp->t_oproc)(tp); return; + } /* * The extra PPP_FLAG will start up a new packet, and thus @@ -684,12 +715,14 @@ pppinput(c, tp) register struct ppp_softc *sc; struct mbuf *m; int ilen; + extern int tk_nin; tk_nin++; sc = (struct ppp_softc *) tp->t_sc; if (sc == NULL || tp != (struct tty *) sc->sc_devp) return; + s = spltty(); sc->sc_bytesrcvd++; c &= 0xff; @@ -727,6 +760,7 @@ pppinput(c, tp) sc->sc_if.if_ierrors++; } else sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); + splx(s); return; } @@ -737,6 +771,7 @@ pppinput(c, tp) sc->sc_if.if_ierrors++; sc->sc_flags |= SC_PKTLOST; } + splx(s); return; } @@ -760,23 +795,28 @@ pppinput(c, tp) sc->sc_flags &= ~SC_PKTLOST; pppgetm(sc); + splx(s); return; } if (sc->sc_flags & SC_FLUSH) { if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); + splx(s); return; } - if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) + if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) { + splx(s); return; + } if (sc->sc_flags & SC_ESCAPED) { sc->sc_flags &= ~SC_ESCAPED; c ^= PPP_TRANS; } else if (c == PPP_ESCAPE) { sc->sc_flags |= SC_ESCAPED; + splx(s); return; } @@ -864,6 +904,7 @@ pppinput(c, tp) ++m->m_len; *sc->sc_mp++ = c; sc->sc_fcs = PPP_FCS(sc->sc_fcs, c); + splx(s); return; flush: @@ -873,6 +914,7 @@ pppinput(c, tp) if (sc->sc_flags & SC_LOG_FLUSH) ppplogchar(sc, c); } + splx(s); } #define MAX_DUMP_BYTES 128 -- 2.39.2