-/* $Id: if_ppp.c,v 1.2 1996/04/04 03:21:05 paulus Exp $ */
+/* $Id: if_ppp.c,v 1.8 1998/03/25 04:04:37 paulus Exp $ */
/*
* if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
#include <sys/time.h>
#include <sys/malloc.h>
+#if NetBSD1_0 && defined(i386)
+#include <machine/psl.h>
+#endif
+
#include <net/if.h>
#include <net/if_types.h>
#include <net/netisr.h>
#include <net/route.h>
+#ifdef PPP_FILTER
#include <net/bpf.h>
+#endif
#if INET
#include <netinet/in.h>
#include <net/if_pppvar.h>
#include <machine/cpu.h>
+#if NetBSD1_0
+#define splsoftnet splnet
+#endif
+
#ifdef PPP_COMPRESS
#define PACKETPTR struct mbuf *
#include <net/ppp-comp.h>
#endif
+static int pppsioctl __P((struct ifnet *, u_long, caddr_t));
static void ppp_requeue __P((struct ppp_softc *));
-static void ppp_outpkt __P((struct ppp_softc *));
static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
static void ppp_ccp_closed __P((struct ppp_softc *));
static void ppp_inproc __P((struct ppp_softc *, struct mbuf *));
*/
extern struct compressor ppp_bsd_compress;
-extern struct compressor ppp_deflate;
+extern struct compressor ppp_deflate, ppp_deflate_draft;
struct compressor *ppp_compressors[8] = {
#if DO_BSD_COMPRESS
#endif
#if DO_DEFLATE
&ppp_deflate,
+ &ppp_deflate_draft,
#endif
NULL
};
#endif /* PPP_COMPRESS */
+
/*
* Called from boot code to establish ppp interfaces.
*/
bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
#endif
}
+
+#if NetBSD1_0 && defined(i386)
+ /*
+ * XXX kludge to fix the bug in the i386 interrupt handling code,
+ * where software interrupts could be taken while hardware
+ * interrupts were blocked.
+ */
+ if ((imask[IPL_TTY] & (1 << SIR_NET)) == 0) {
+ imask[IPL_TTY] |= (1 << SIR_NET);
+ intr_calculatemasks();
+ }
+#endif
}
/*
sc->sc_xc_state = NULL;
sc->sc_rc_state = NULL;
#endif /* PPP_COMPRESS */
+#ifdef PPP_FILTER
if (sc->sc_pass_filt.bf_insns != 0) {
FREE(sc->sc_pass_filt.bf_insns, M_DEVBUF);
sc->sc_pass_filt.bf_insns = 0;
sc->sc_active_filt.bf_insns = 0;
sc->sc_active_filt.bf_len = 0;
}
+#endif /* PPP_FILTER */
#ifdef VJC
if (sc->sc_comp != 0) {
FREE(sc->sc_comp, M_DEVBUF);
struct compressor **cp;
struct npioctl *npi;
time_t t;
+#ifdef PPP_FILTER
struct bpf_program *bp, *nbp;
struct bpf_insn *newcode, *oldcode;
int newcodelen;
+#endif /* PPP_FILTER */
#ifdef PPP_COMPRESS
u_char ccp_option[CCP_MAX_OPTION_LENGTH];
#endif
if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
ppp_ccp_closed(sc);
#endif
- splhigh();
+ splimp();
sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
splx(s);
break;
sc->sc_if.if_unit);
error = ENOBUFS;
}
- splhigh();
+ splimp();
sc->sc_flags &= ~SC_COMP_RUN;
splx(s);
} else {
sc->sc_if.if_unit);
error = ENOBUFS;
}
- splhigh();
+ splimp();
sc->sc_flags &= ~SC_DECOMP_RUN;
splx(s);
}
splx(s);
break;
+#ifdef PPP_FILTER
case PPPIOCSPASS:
case PPPIOCSACTIVE:
nbp = (struct bpf_program *) data;
if (oldcode != 0)
FREE(oldcode, M_DEVBUF);
break;
+#endif
default:
return (-1);
/*
* Process an ioctl request to the ppp network interface.
*/
-int
+static int
pppsioctl(ifp, cmd, data)
register struct ifnet *ifp;
u_long cmd;
struct ip *ip;
struct ifqueue *ifq;
enum NPmode mode;
- int active, len;
+ int len;
struct mbuf *m;
if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
pppdumpm(m0);
}
- /*
- * Apply the pass and active filters to the packet,
- * but only if it is a data packet.
- */
- active = 0;
if ((protocol & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * Apply the pass and active filters to the packet,
+ * but only if it is a data packet.
+ */
*mtod(m0, u_char *) = 1; /* indicates outbound */
if (sc->sc_pass_filt.bf_insns != 0
&& bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,
sc->sc_last_sent = time.tv_sec;
*mtod(m0, u_char *) = address;
+#else
+ /*
+ * Update the time we sent the most recent data packet.
+ */
+ sc->sc_last_sent = time.tv_sec;
+#endif /* PPP_FILTER */
}
#if NBPFILTER > 0
}
/*
- * Get a packet to send. This procedure is intended to be called at
- * spltty or splimp, so it takes little time. If there isn't a packet
- * waiting to go out, it schedules a software interrupt to prepare a
- * new packet; the device start routine gets called again when a
- * packet is ready.
+ * Transmitter has finished outputting some stuff;
+ * remember to call sc->sc_start later at splsoftnet.
*/
-struct mbuf *
-ppp_dequeue(sc)
+void
+ppp_restart(sc)
struct ppp_softc *sc;
{
- struct mbuf *m;
- int s = splhigh();
+ int s = splimp();
- m = sc->sc_togo;
- if (m) {
- /*
- * Had a packet waiting - send it.
- */
- sc->sc_togo = NULL;
- sc->sc_flags |= SC_TBUSY;
- splx(s);
- return m;
- }
- /*
- * Remember we wanted a packet and schedule a software interrupt.
- */
sc->sc_flags &= ~SC_TBUSY;
schednetisr(NETISR_PPP);
splx(s);
- return NULL;
}
/*
- * Software interrupt routine, called at splsoftnet.
- */
-void
-pppintr()
-{
- struct ppp_softc *sc;
- int i, s;
- struct mbuf *m;
-
- sc = ppp_softc;
- for (i = 0; i < NPPP; ++i, ++sc) {
- if (!(sc->sc_flags & SC_TBUSY) && sc->sc_togo == NULL
- && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head))
- ppp_outpkt(sc);
- for (;;) {
- s = splhigh();
- IF_DEQUEUE(&sc->sc_rawq, m);
- splx(s);
- if (m == NULL)
- break;
- ppp_inproc(sc, m);
- }
- }
-}
-
-/*
- * Grab another packet off a queue and apply VJ compression,
- * packet compression, address/control and/or protocol compression
- * if enabled. Should be called at splsoftnet.
+ * Get a packet to send. This procedure is intended to be called at
+ * splsoftnet, since it may involve time-consuming operations such as
+ * applying VJ compression, packet compression, address/control and/or
+ * protocol field compression to the packet.
*/
-static void
-ppp_outpkt(sc)
+struct mbuf *
+ppp_dequeue(sc)
struct ppp_softc *sc;
{
struct mbuf *m, *mp;
if (m == NULL)
IF_DEQUEUE(&sc->sc_if.if_snd, m);
if (m == NULL)
- return;
+ return NULL;
++sc->sc_stats.ppp_opackets;
for (mp = m; mp != NULL; mp = mp->m_next)
slen += mp->m_len;
clen = (*sc->sc_xcomp->compress)
- (sc->sc_xc_state, &mcomp, m, slen,
- (sc->sc_flags & SC_CCP_UP? sc->sc_if.if_mtu: 0));
+ (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);
if (mcomp != NULL) {
- m_freem(m);
- m = mcomp;
- cp = mtod(m, u_char *);
- protocol = cp[3];
+ if (sc->sc_flags & SC_CCP_UP) {
+ /* Send the compressed packet instead of the original. */
+ m_freem(m);
+ m = mcomp;
+ cp = mtod(m, u_char *);
+ protocol = cp[3];
+ } else {
+ /* Can't transmit compressed packets until CCP is up. */
+ m_freem(mcomp);
+ }
}
}
#endif /* PPP_COMPRESS */
--m->m_len;
}
- sc->sc_togo = m;
- (*sc->sc_start)(sc);
+ return m;
+}
+
+/*
+ * Software interrupt routine, called at splsoftnet.
+ */
+void
+pppintr()
+{
+ struct ppp_softc *sc;
+ int i, s, s2;
+ struct mbuf *m;
+
+ sc = ppp_softc;
+ s = splsoftnet();
+ for (i = 0; i < NPPP; ++i, ++sc) {
+ if (!(sc->sc_flags & SC_TBUSY)
+ && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) {
+ s2 = splimp();
+ sc->sc_flags |= SC_TBUSY;
+ splx(s2);
+ (*sc->sc_start)(sc);
+ }
+ for (;;) {
+ s2 = splimp();
+ IF_DEQUEUE(&sc->sc_rawq, m);
+ splx(s2);
+ if (m == NULL)
+ break;
+ ppp_inproc(sc, m);
+ }
+ }
+ splx(s);
}
#ifdef PPP_COMPRESS
case CCP_TERMACK:
/* CCP must be going down - disable compression */
if (sc->sc_flags & SC_CCP_UP) {
- s = splhigh();
+ s = splimp();
sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
splx(s);
}
&& (*sc->sc_xcomp->comp_init)
(sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
sc->sc_if.if_unit, 0, sc->sc_flags & SC_DEBUG)) {
- s = splhigh();
+ s = splimp();
sc->sc_flags |= SC_COMP_RUN;
splx(s);
}
(sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
sc->sc_if.if_unit, 0, sc->sc_mru,
sc->sc_flags & SC_DEBUG)) {
- s = splhigh();
+ s = splimp();
sc->sc_flags |= SC_DECOMP_RUN;
sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
splx(s);
} else {
if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
(*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
- s = splhigh();
+ s = splimp();
sc->sc_flags &= ~SC_DC_ERROR;
splx(s);
}
struct mbuf *m;
int lost;
{
- int s = splhigh();
+ int s = splimp();
if (lost)
m->m_flags |= M_ERRMARK;
if (m->m_flags & M_ERRMARK) {
m->m_flags &= ~M_ERRMARK;
- s = splhigh();
+ s = splimp();
sc->sc_flags |= SC_VJ_RESET;
splx(s);
}
*/
if (sc->sc_flags & SC_DEBUG)
printf("ppp%d: decompress failed %d\n", ifp->if_unit, rv);
- s = splhigh();
+ s = splimp();
sc->sc_flags |= SC_VJ_RESET;
if (rv == DECOMP_ERROR)
sc->sc_flags |= SC_DC_ERROR;
*/
if (sc->sc_comp)
sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
- s = splhigh();
+ s = splimp();
sc->sc_flags &= ~SC_VJ_RESET;
splx(s);
}
m->m_pkthdr.len = ilen;
m->m_pkthdr.rcvif = ifp;
- /*
- * See whether we want to pass this packet, and
- * if it counts as link activity.
- */
if ((proto & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * See whether we want to pass this packet, and
+ * if it counts as link activity.
+ */
adrs = *mtod(m, u_char *); /* save address field */
*mtod(m, u_char *) = 0; /* indicate inbound */
if (sc->sc_pass_filt.bf_insns != 0
sc->sc_last_recv = time.tv_sec;
*mtod(m, u_char *) = adrs;
+#else
+ /*
+ * Record the time that we received this packet.
+ */
+ sc->sc_last_recv = time.tv_sec;
+#endif /* PPP_FILTER */
}
#if NBPFILTER > 0
/*
* Put the packet on the appropriate input queue.
*/
- s = splhigh();
+ s = splimp();
if (IF_QFULL(inq)) {
IF_DROP(inq);
splx(s);