summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenjiro Cho <kjc@cvs.openbsd.org>2001-06-27 06:07:48 +0000
committerKenjiro Cho <kjc@cvs.openbsd.org>2001-06-27 06:07:48 +0000
commit617b9204d0b61c24f1c430d0d271187effbd4db7 (patch)
treef0298d5992870f173131e355b24266b1167650ca
parent68127d8aa8be05026092d74eb27663a9fe287c85 (diff)
introduce the ALTQ queue macros into sys/net files.
the new model removes direct references to the fields in ifp->if_snd, and defines the following macros to manipulate ifp->if_snd. IFQ_ENQUEUE(ifq, m, pktattr, err) IFQ_DEQUEUE(ifq, m) IFQ_POLL(ifq, m) IFQ_PURGE(ifq) IFQ_IS_EMPTY(ifq) the new model also enforces some rules regarding how to use these macros. details are descrined in http://www.csl.sony.co.jp/~kjc/software/altq-new-design.txt
-rw-r--r--sys/net/bridgestp.c19
-rw-r--r--sys/net/if_atmsubr.c31
-rw-r--r--sys/net/if_bridge.c93
-rw-r--r--sys/net/if_ethersubr.c115
-rw-r--r--sys/net/if_fddisubr.c29
-rw-r--r--sys/net/if_loop.c122
-rw-r--r--sys/net/if_ppp.c62
-rw-r--r--sys/net/if_sl.c25
-rw-r--r--sys/net/if_spppsubr.c50
-rw-r--r--sys/net/if_strip.c35
-rw-r--r--sys/net/if_tokensubr.c29
-rw-r--r--sys/net/if_tun.c78
-rw-r--r--sys/net/if_vlan.c44
-rw-r--r--sys/netinet/if_ether.h5
14 files changed, 571 insertions, 166 deletions
diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c
index f84e8f5016b..49d697068c1 100644
--- a/sys/net/bridgestp.c
+++ b/sys/net/bridgestp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bridgestp.c,v 1.6 2001/05/30 02:12:23 deraadt Exp $ */
+/* $OpenBSD: bridgestp.c,v 1.7 2001/06/27 06:07:37 kjc Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright (jason@thought.net)
@@ -224,7 +224,7 @@ bstp_send_config_bpdu(bif, cu)
struct mbuf *m;
struct ether_header eh;
struct bstp_cbpdu bpdu;
- int s;
+ int s, error;
s = splimp();
ifp = bif->ifp;
@@ -234,6 +234,9 @@ bstp_send_config_bpdu(bif, cu)
splx(s);
return;
}
+#ifdef ALTQ
+ if (!ALTQ_IS_ENABLED(&ifp->if_snd))
+#endif
if (IF_QFULL(&ifp->if_snd)) {
splx(s);
return;
@@ -287,8 +290,8 @@ bstp_send_config_bpdu(bif, cu)
bcopy(&eh, m->m_data, sizeof(eh));
bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu));
- IF_ENQUEUE(&ifp->if_snd, m);
- if ((ifp->if_flags & IFF_OACTIVE) == 0)
+ IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+ if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
}
@@ -386,7 +389,7 @@ bstp_transmit_tcn(sc)
struct arpcom *arp = (struct arpcom *)ifp;
struct ether_header *eh;
struct mbuf *m;
- int s;
+ int s, error;
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL)
@@ -410,10 +413,8 @@ bstp_transmit_tcn(sc)
s = splimp();
if ((ifp->if_flags & IFF_RUNNING) == 0)
goto out;
- if (IF_QFULL(&ifp->if_snd))
- goto out;
- IF_ENQUEUE(&ifp->if_snd, m);
- if ((ifp->if_flags & IFF_OACTIVE) == 0)
+ IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+ if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
m = NULL;
diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c
index c9437d5d1aa..10c13bbbb73 100644
--- a/sys/net/if_atmsubr.c
+++ b/sys/net/if_atmsubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_atmsubr.c,v 1.15 2001/06/15 03:38:33 itojun Exp $ */
+/* $OpenBSD: if_atmsubr.c,v 1.16 2001/06/27 06:07:38 kjc Exp $ */
/*
*
@@ -107,17 +107,25 @@ atm_output(ifp, m0, dst, rt0)
struct rtentry *rt0;
{
u_int16_t etype = 0; /* if using LLC/SNAP */
- int s, error = 0, sz;
+ int s, error = 0, sz, len;
struct atm_pseudohdr atmdst, *ad;
register struct mbuf *m = m0;
register struct rtentry *rt;
struct atmllc *atmllc;
u_int32_t atm_flags;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
/*
+ * if the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m,
+ (dst != NULL ? dst->sa_family : AF_UNSPEC), &pktattr);
+
+ /*
* check route
*/
if ((rt = rt0) != NULL) {
@@ -160,14 +168,6 @@ atm_output(ifp, m0, dst, rt0)
etype = ETHERTYPE_IP;
else
etype = ETHERTYPE_IPV6;
-# ifdef ATM_PVCEXT
- if (ifp->if_flags & IFF_POINTOPOINT) {
- /* pvc subinterface */
- struct pvcsif *pvcsif = (struct pvcsif *)ifp;
- atmdst = pvcsif->sif_aph;
- break;
- }
-# endif
if (!atmresolve(rt, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
@@ -235,15 +235,14 @@ atm_output(ifp, m0, dst, rt0)
* Queue message on interface, and start output if interface
* not yet active.
*/
-
+ len = m->m_pkthdr.len;
s = splimp();
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
+ IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+ if (error) {
splx(s);
- senderr(ENOBUFS);
+ return (error);
}
- ifp->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&ifp->if_snd, m);
+ ifp->if_obytes += len;
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 5690b6c5e76..cd3776b5b67 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.67 2001/06/26 18:17:53 deraadt Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.68 2001/06/27 06:07:39 kjc Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -742,7 +742,9 @@ bridge_output(ifp, m, sa, rt)
struct ifnet *dst_if;
struct ether_addr *src, *dst;
struct bridge_softc *sc;
- int s;
+ int s, error, len;
+ short mflags;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
#ifdef IPSEC
struct m_tag *mtag;
#endif /* IPSEC */
@@ -806,6 +808,9 @@ bridge_output(ifp, m, sa, rt)
dst_if = p->ifp;
if ((dst_if->if_flags & IFF_RUNNING) == 0)
continue;
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&dst_if->if_snd) == 0)
+#endif
if (IF_QFULL(&dst_if->if_snd)) {
IF_DROP(&dst_if->if_snd);
sc->sc_if.if_oerrors++;
@@ -821,13 +826,22 @@ bridge_output(ifp, m, sa, rt)
continue;
}
}
-
+ len = mc->m_pkthdr.len;
+ mflags = mc->m_flags;
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&dst_if->if_snd))
+ altq_etherclassify(&dst_if->if_snd, mc, &pktattr);
+#endif
+ IFQ_ENQUEUE(&dst_if->if_snd, mc, &pktattr, error);
+ if (error) {
+ sc->sc_if.if_oerrors++;
+ continue;
+ }
sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes += mc->m_pkthdr.len;
- dst_if->if_obytes += mc->m_pkthdr.len;
- IF_ENQUEUE(&dst_if->if_snd, mc);
- if (mc->m_flags & M_MCAST)
- ifp->if_omcasts++;
+ sc->sc_if.if_obytes += len;
+ dst_if->if_obytes += len;
+ if (mflags & M_MCAST)
+ dst_if->if_omcasts++;
if ((dst_if->if_flags & IFF_OACTIVE) == 0)
(*dst_if->if_start)(dst_if);
}
@@ -843,18 +857,22 @@ sendunicast:
splx(s);
return (0);
}
- if (IF_QFULL(&dst_if->if_snd)) {
- IF_DROP(&dst_if->if_snd);
+ len = m->m_pkthdr.len;
+ mflags = m->m_flags;
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&dst_if->if_snd))
+ altq_etherclassify(&dst_if->if_snd, m, &pktattr);
+#endif
+ IFQ_ENQUEUE(&dst_if->if_snd, m, &pktattr, error);
+ if (error) {
sc->sc_if.if_oerrors++;
- m_freem(m);
splx(s);
return (0);
}
sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes += m->m_pkthdr.len;
- dst_if->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&dst_if->if_snd, m);
- if (m->m_flags & M_MCAST)
+ sc->sc_if.if_obytes += len;
+ dst_if->if_obytes += len;
+ if (mflags & M_MCAST)
dst_if->if_omcasts++;
if ((dst_if->if_flags & IFF_OACTIVE) == 0)
(*dst_if->if_start)(dst_if);
@@ -902,11 +920,13 @@ bridgeintr_frame(sc, m)
struct bridge_softc *sc;
struct mbuf *m;
{
- int s;
+ int s, error, len;
struct ifnet *src_if, *dst_if;
struct bridge_iflist *ifl;
struct ether_addr *dst, *src;
struct ether_header eh;
+ short mflags;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
m_freem(m);
@@ -1067,19 +1087,23 @@ bridgeintr_frame(sc, m)
m_freem(m);
return;
}
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&dst_if->if_snd))
+ altq_etherclassify(&dst_if->if_snd, m, &pktattr);
+#endif
+ len = m->m_pkthdr.len;
+ mflags = m->m_flags;
s = splimp();
- if (IF_QFULL(&dst_if->if_snd)) {
- IF_DROP(&dst_if->if_snd);
+ IFQ_ENQUEUE(&dst_if->if_snd, m, &pktattr, error);
+ if (error) {
sc->sc_if.if_oerrors++;
- m_freem(m);
splx(s);
return;
}
sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes += m->m_pkthdr.len;
- dst_if->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&dst_if->if_snd, m);
- if (m->m_flags & M_MCAST)
+ sc->sc_if.if_obytes += len;
+ dst_if->if_obytes += len;
+ if (mflags & M_MCAST)
dst_if->if_omcasts++;
if ((dst_if->if_flags & IFF_OACTIVE) == 0)
(*dst_if->if_start)(dst_if);
@@ -1245,7 +1269,9 @@ bridge_broadcast(sc, ifp, eh, m)
struct bridge_iflist *p;
struct mbuf *mc;
struct ifnet *dst_if;
- int used = 0;
+ int error, len, used = 0;
+ short mflags;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
LIST_FOREACH(p, &sc->sc_iflist, next) {
/*
@@ -1268,6 +1294,9 @@ bridge_broadcast(sc, ifp, eh, m)
if ((dst_if->if_flags & IFF_RUNNING) == 0)
continue;
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&dst_if->if_snd) == 0)
+#endif
if (IF_QFULL(&dst_if->if_snd)) {
IF_DROP(&dst_if->if_snd);
sc->sc_if.if_oerrors++;
@@ -1294,11 +1323,19 @@ bridge_broadcast(sc, ifp, eh, m)
}
}
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&dst_if->if_snd))
+ altq_etherclassify(&dst_if->if_snd, mc, &pktattr);
+#endif
+ IFQ_ENQUEUE(&dst_if->if_snd, mc, &pktattr, error);
+ if (error) {
+ sc->sc_if.if_oerrors++;
+ continue;
+ }
sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes += mc->m_pkthdr.len;
- dst_if->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&dst_if->if_snd, mc);
- if (mc->m_flags & M_MCAST)
+ sc->sc_if.if_obytes += len;
+ dst_if->if_obytes += len;
+ if (mflags & M_MCAST)
dst_if->if_omcasts++;
if ((dst_if->if_flags & IFF_OACTIVE) == 0)
(*dst_if->if_start)(dst_if);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 325a7720cb7..622c73107b9 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.51 2001/06/24 22:34:04 fgsch Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.52 2001/06/27 06:07:40 kjc Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -246,13 +246,15 @@ ether_output(ifp, m0, dst, rt0)
struct rtentry *rt0;
{
u_int16_t etype;
- int s, error = 0, hdrcmplt = 0;
+ int s, len, error = 0, hdrcmplt = 0;
u_char edst[6], esrc[6];
register struct mbuf *m = m0;
register struct rtentry *rt;
struct mbuf *mcopy = (struct mbuf *)0;
register struct ether_header *eh;
struct arpcom *ac = (struct arpcom *)ifp;
+ short mflags;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
@@ -278,6 +280,13 @@ ether_output(ifp, m0, dst, rt0)
time.tv_sec < rt->rt_rmx.rmx_expire)
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
+
+ /*
+ * if the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+
switch (dst->sa_family) {
#ifdef INET
@@ -560,19 +569,21 @@ ether_output(ifp, m0, dst, rt0)
}
#endif
+ mflags = m->m_flags;
+ len = m->m_pkthdr.len;
s = splimp();
/*
* Queue message on interface, and start output if interface
* not yet active.
*/
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
+ IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+ if (error) {
+ /* mbuf is already freed */
splx(s);
- senderr(ENOBUFS);
+ return (error);
}
- ifp->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&ifp->if_snd, m);
- if (m->m_flags & M_MCAST)
+ ifp->if_obytes += len + sizeof (struct ether_header);
+ if (mflags & M_MCAST)
ifp->if_omcasts++;
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
@@ -585,6 +596,94 @@ bad:
return (error);
}
+#ifdef ALTQ
+/*
+ * This routine is a slight hack to allow a packet to be classified
+ * if the Ethernet headers are present. It will go away when ALTQ's
+ * classification engine understands link headers.
+ */
+void
+altq_etherclassify(struct ifaltq *ifq, struct mbuf *m,
+ struct altq_pktattr *pktattr)
+{
+ struct ether_header *eh;
+ u_int16_t ether_type;
+ int hlen, af, hdrsize;
+ caddr_t hdr;
+
+ hlen = ETHER_HDR_LEN;
+ eh = mtod(m, struct ether_header *);
+
+ ether_type = htons(eh->ether_type);
+
+ if (ether_type < ETHERMTU) {
+ /* LLC/SNAP */
+ struct llc *llc = (struct llc *)(eh + 1);
+ hlen += 8;
+
+ if (m->m_len < hlen ||
+ llc->llc_dsap != LLC_SNAP_LSAP ||
+ llc->llc_ssap != LLC_SNAP_LSAP ||
+ llc->llc_control != LLC_UI) {
+ /* Not SNAP. */
+ goto bad;
+ }
+
+ ether_type = htons(llc->llc_un.type_snap.ether_type);
+ }
+
+ switch (ether_type) {
+ case ETHERTYPE_IP:
+ af = AF_INET;
+ hdrsize = 20; /* sizeof(struct ip) */
+ break;
+
+ case ETHERTYPE_IPV6:
+ af = AF_INET6;
+ hdrsize = 40; /* sizeof(struct ip6_hdr) */
+ break;
+
+ default:
+ af = AF_UNSPEC;
+ hdrsize = 0;
+ break;
+ }
+
+ if (m->m_len < (hlen + hdrsize)) {
+ /*
+ * Ethernet and protocol header not in a single
+ * mbuf. We can't cope with this situation right
+ * now (but it shouldn't ever happen, really, anyhow).
+ * XXX Should use m_pulldown().
+ */
+ printf("altq_etherclassify: headers span multiple mbufs: "
+ "%d < %d\n", m->m_len, (hlen + hdrsize));
+ goto bad;
+ }
+
+ m->m_data += hlen;
+ m->m_len -= hlen;
+
+ hdr = mtod(m, caddr_t);
+
+ if (ALTQ_NEEDS_CLASSIFY(ifq))
+ pktattr->pattr_class =
+ (*ifq->altq_classify)(ifq->altq_clfier, m, af);
+ pktattr->pattr_af = af;
+ pktattr->pattr_hdr = hdr;
+
+ m->m_data -= hlen;
+ m->m_len += hlen;
+
+ return;
+
+ bad:
+ pktattr->pattr_class = NULL;
+ pktattr->pattr_hdr = NULL;
+ pktattr->pattr_af = AF_UNSPEC;
+}
+#endif /* ALTQ */
+
/*
* Temporary function to migrate while
* removing ether_header * from ether_input().
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index e4e9464ad79..3ae884a351c 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_fddisubr.c,v 1.24 2001/06/15 03:38:33 itojun Exp $ */
+/* $OpenBSD: if_fddisubr.c,v 1.25 2001/06/27 06:07:40 kjc Exp $ */
/* $NetBSD: if_fddisubr.c,v 1.5 1996/05/07 23:20:21 christos Exp $ */
/*
@@ -150,13 +150,15 @@ fddi_output(ifp, m0, dst, rt0)
struct rtentry *rt0;
{
u_int16_t type;
- int s, error = 0, hdrcmplt = 0;
+ int s, len, error = 0, hdrcmplt = 0;
u_char edst[6], esrc[6];
register struct mbuf *m = m0;
register struct rtentry *rt;
struct mbuf *mcopy = (struct mbuf *)0;
register struct fddi_header *fh;
struct arpcom *ac = (struct arpcom *)ifp;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
+ short mflags;
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
@@ -182,6 +184,13 @@ fddi_output(ifp, m0, dst, rt0)
time.tv_sec < rt->rt_rmx.rmx_expire)
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
+
+ /*
+ * If the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+
switch (dst->sa_family) {
#ifdef INET
@@ -432,23 +441,25 @@ fddi_output(ifp, m0, dst, rt0)
else
bcopy((caddr_t)ac->ac_enaddr, (caddr_t)fh->fddi_shost,
sizeof(fh->fddi_shost));
+ mflags = m->m_flags;
+ len = m->m_pkthdr.len;
s = splimp();
/*
* Queue message on interface, and start output if interface
* not yet active.
*/
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
+ IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+ if (error) {
+ /* mbuf is already freed */
splx(s);
- senderr(ENOBUFS);
+ return (error);
}
- ifp->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&ifp->if_snd, m);
+ ifp->if_obytes += len;
+ if (mflags & M_MCAST)
+ ifp->if_omcasts++;
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
- if (m->m_flags & M_MCAST)
- ifp->if_omcasts++;
return (error);
bad:
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 3d784315000..9c6d22d4014 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_loop.c,v 1.18 2001/06/15 03:38:34 itojun Exp $ */
+/* $OpenBSD: if_loop.c,v 1.19 2001/06/27 06:07:42 kjc Exp $ */
/* $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 thorpej Exp $ */
/*
@@ -145,6 +145,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#define LOMTU (32768 + MHLEN + MLEN)
#endif
+#ifdef ALTQ
+static void lo_altqstart __P((struct ifnet *));
+#endif
+
void
loopattach(n)
int n;
@@ -168,6 +172,10 @@ loopattach(n)
ifp->if_type = IFT_LOOP;
ifp->if_hdrlen = sizeof(u_int32_t);
ifp->if_addrlen = 0;
+ IFQ_SET_READY(&ifp->if_snd);
+#ifdef ALTQ
+ ifp->if_start = lo_altqstart;
+#endif
if_attachhead(ifp);
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
@@ -221,6 +229,37 @@ looutput(ifp, m, dst, rt)
ifp->if_opackets++;
ifp->if_obytes += m->m_pkthdr.len;
+#ifdef ALTQ
+ /*
+ * altq for loop is just for debugging.
+ * only used when called for loop interface (not for
+ * a simplex interface).
+ */
+ if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd))
+ && ifp->if_start == lo_altqstart) {
+ struct altq_pktattr pktattr;
+ int32_t *afp;
+ int error;
+
+ /*
+ * if the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+
+ M_PREPEND(m, sizeof(int32_t), M_DONTWAIT);
+ if (m == 0)
+ return(ENOBUFS);
+ afp = mtod(m, int32_t *);
+ *afp = (int32_t)dst->sa_family;
+
+ s = splimp();
+ IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+ (*ifp->if_start)(ifp);
+ splx(s);
+ return (error);
+ }
+#endif /* ALTQ */
switch (dst->sa_family) {
#ifdef INET
@@ -280,6 +319,87 @@ looutput(ifp, m, dst, rt)
return (0);
}
+#ifdef ALTQ
+static void
+lo_altqstart(ifp)
+ struct ifnet *ifp;
+{
+ struct ifqueue *ifq;
+ struct mbuf *m;
+ int32_t af, *afp;
+ int s, isr;
+
+ while (1) {
+ s = splimp();
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ splx(s);
+ if (m == NULL)
+ return;
+
+ afp = mtod(m, int32_t *);
+ af = *afp;
+ m_adj(m, sizeof(int32_t));
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ m->m_flags |= M_LOOP;
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ break;
+#endif
+#ifdef IPX
+ case AF_IPX:
+ ifq = &ipxintrq;
+ isr = NETISR_IPX;
+ break;
+#endif
+#ifdef NS
+ case AF_NS:
+ ifq = &nsintrq;
+ isr = NETISR_NS;
+ break;
+#endif
+#ifdef ISO
+ case AF_ISO:
+ ifq = &clnlintrq;
+ isr = NETISR_ISO;
+ break;
+#endif
+#ifdef NETATALK
+ case AF_APPLETALK:
+ ifq = &atintrq2;
+ isr = NETISR_ATALK;
+ break;
+#endif NETATALK
+ default:
+ printf("lo_altqstart: can't handle af%d\n", af);
+ m_freem(m);
+ return;
+ }
+
+ s = splimp();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ splx(s);
+ return;
+ }
+ IF_ENQUEUE(ifq, m);
+ schednetisr(isr);
+ ifp->if_ipackets++;
+ ifp->if_ibytes += m->m_pkthdr.len;
+ splx(s);
+ }
+}
+#endif /* ALTQ */
+
/* ARGSUSED */
void
lortrequest(cmd, rt, info)
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c
index 96fbe46d218..b057ba38669 100644
--- a/sys/net/if_ppp.c
+++ b/sys/net/if_ppp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ppp.c,v 1.22 2001/06/27 03:49:53 angelos Exp $ */
+/* $OpenBSD: if_ppp.c,v 1.23 2001/06/27 06:07:42 kjc Exp $ */
/* $NetBSD: if_ppp.c,v 1.39 1997/05/17 21:11:59 christos Exp $ */
/*
@@ -199,10 +199,11 @@ pppattach()
sc->sc_if.if_hdrlen = PPP_HDRLEN;
sc->sc_if.if_ioctl = pppsioctl;
sc->sc_if.if_output = pppoutput;
- sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&sc->sc_if.if_snd);
if_attach(&sc->sc_if);
#if NBPFILTER > 0
bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
@@ -636,6 +637,7 @@ pppoutput(ifp, m0, dst, rtp)
enum NPmode mode;
int len;
struct mbuf *m;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
@@ -643,6 +645,8 @@ pppoutput(ifp, m0, dst, rtp)
goto bad;
}
+ IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
+
/*
* Compute PPP header.
*/
@@ -759,16 +763,29 @@ pppoutput(ifp, m0, dst, rtp)
m0->m_nextpkt = NULL;
sc->sc_npqtail = &m0->m_nextpkt;
} else {
- ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq: &ifp->if_snd;
- if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
- IF_DROP(ifq);
+ if ((m0->m_flags & M_HIGHPRI)
+#ifdef ALTQ
+ && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
+#endif
+ ) {
+ ifq = &sc->sc_fastq;
+ if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
+ IF_DROP(ifq);
+ m_freem(m0);
+ error = ENOBUFS;
+ }
+ else {
+ IF_ENQUEUE(ifq, m0);
+ error = 0;
+ }
+ } else
+ IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error);
+ if (error) {
splx(s);
sc->sc_if.if_oerrors++;
sc->sc_stats.ppp_oerrors++;
- error = ENOBUFS;
- goto bad;
+ return (error);
}
- IF_ENQUEUE(ifq, m0);
(*sc->sc_start)(sc);
}
ifp->if_opackets++;
@@ -794,6 +811,7 @@ ppp_requeue(sc)
struct mbuf *m, **mpp;
struct ifqueue *ifq;
enum NPmode mode;
+ int error;
for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
switch (PPP_PROTOCOL(mtod(m, u_char *))) {
@@ -811,13 +829,27 @@ ppp_requeue(sc)
*/
*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);
+ if ((m->m_flags & M_HIGHPRI)
+#ifdef ALTQ
+ && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
+#endif
+ ) {
+ ifq = &sc->sc_fastq;
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ error = ENOBUFS;
+ }
+ else {
+ IF_ENQUEUE(ifq, m);
+ error = 0;
+ }
+ } else
+ IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error);
+ if (error) {
sc->sc_if.if_oerrors++;
sc->sc_stats.ppp_oerrors++;
- } else
- IF_ENQUEUE(ifq, m);
+ }
break;
case NPMODE_DROP:
@@ -869,7 +901,7 @@ ppp_dequeue(sc)
*/
IF_DEQUEUE(&sc->sc_fastq, m);
if (m == NULL)
- IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
if (m == NULL)
return NULL;
@@ -995,7 +1027,7 @@ pppintr()
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)) {
+ && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head)) {
s2 = splimp();
sc->sc_flags |= SC_TBUSY;
splx(s2);
diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c
index 38a24740995..7b7898ac805 100644
--- a/sys/net/if_sl.c
+++ b/sys/net/if_sl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sl.c,v 1.13 2001/06/15 03:38:34 itojun Exp $ */
+/* $OpenBSD: if_sl.c,v 1.14 2001/06/27 06:07:43 kjc Exp $ */
/* $NetBSD: if_sl.c,v 1.39.4.1 1996/06/02 16:26:31 thorpej Exp $ */
/*
@@ -214,8 +214,9 @@ slattach(n)
sc->sc_if.if_type = IFT_SLIP;
sc->sc_if.if_ioctl = slioctl;
sc->sc_if.if_output = sloutput;
- sc->sc_if.if_snd.ifq_maxlen = 50;
+ IFQ_SET_MAXLEN(&sc->sc_if.if_snd, 50);
sc->sc_fastq.ifq_maxlen = 32;
+ IFQ_SET_READY(&sc->sc_if.if_snd);
if_attach(&sc->sc_if);
#if NBPFILTER > 0
bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
@@ -383,8 +384,10 @@ sloutput(ifp, m, dst, rtp)
{
register struct sl_softc *sc = ifp->if_softc;
register struct ip *ip;
- register struct ifqueue *ifq;
- int s;
+ int s, error;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
+
+ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
/*
* `Cannot happen' (see slioctl). Someday we will extend
@@ -407,14 +410,11 @@ sloutput(ifp, m, dst, rtp)
m_freem(m);
return (EHOSTUNREACH);
}
- ifq = &sc->sc_if.if_snd;
ip = mtod(m, struct ip *);
if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
m_freem(m);
return (ENETRESET); /* XXX ? */
}
- if (ip->ip_tos & IPTOS_LOWDELAY)
- ifq = &sc->sc_fastq;
s = splimp();
if (sc->sc_oqlen && sc->sc_ttyp->t_outq.c_cc == sc->sc_oqlen) {
struct timeval tv;
@@ -426,14 +426,13 @@ sloutput(ifp, m, dst, rtp)
slstart(sc->sc_ttyp);
}
}
- if (IF_QFULL(ifq)) {
- IF_DROP(ifq);
- m_freem(m);
+ IFQ_ENQUEUE(&sc->sc_if.if_snd, m, &pktattr, error);
+ if (error) {
splx(s);
sc->sc_if.if_oerrors++;
- return (ENOBUFS);
+ return (error);
}
- IF_ENQUEUE(ifq, m);
+
sc->sc_lastpacket = time;
if ((sc->sc_oqlen = sc->sc_ttyp->t_outq.c_cc) == 0)
slstart(sc->sc_ttyp);
@@ -500,7 +499,7 @@ slstart(tp)
if (m)
sc->sc_if.if_omcasts++; /* XXX */
else
- IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
splx(s);
if (m == NULL)
return;
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 7a7f30dc6fe..55c69259192 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_spppsubr.c,v 1.8 2001/03/25 02:56:18 csapuntz Exp $ */
+/* $OpenBSD: if_spppsubr.c,v 1.9 2001/06/27 06:07:43 kjc Exp $ */
/*
* Synchronous PPP/Cisco link level subroutines.
* Keepalive protocol implemented in both Cisco and PPP modes.
@@ -639,8 +639,9 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
{
struct sppp *sp = (struct sppp*) ifp;
struct ppp_header *h;
- struct ifqueue *ifq;
- int s, rv = 0;
+ struct ifqueue *ifq = NULL;
+ int s, len, rv = 0;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
s = splimp();
@@ -662,7 +663,12 @@ sppp_output(struct ifnet *ifp, struct mbuf *m,
s = splimp();
}
- ifq = &ifp->if_snd;
+ /*
+ * if the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+
#ifdef INET
/*
* Put low delay, telnet, rlogin and ftp control packets
@@ -782,14 +788,28 @@ nosupport:
* Queue message on interface, and start output if interface
* not yet active.
*/
- if (IF_QFULL (ifq)) {
- IF_DROP (&ifp->if_snd);
- m_freem (m);
+ len = m->m_pkthdr.len;
+ if (ifq != NULL
+#ifdef ALTQ
+ && ALTQ_IS_ENABLED(&ifp->if_snd) == 0
+#endif
+ ) {
+ if (IF_QFULL (ifq)) {
+ IF_DROP (&ifp->if_snd);
+ m_freem (m);
+ if (rv == 0)
+ rv = ENOBUFS;
+ }
+ IF_ENQUEUE (ifq, m);
+ }
+ else
+ IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, rv);
+ if (rv != 0) {
++ifp->if_oerrors;
splx (s);
- return (rv? rv: ENOBUFS);
+ return (rv);
}
- IF_ENQUEUE (ifq, m);
+
if (! (ifp->if_flags & IFF_OACTIVE))
(*ifp->if_start) (ifp);
@@ -798,7 +818,7 @@ nosupport:
* The packet length includes header, FCS and 1 flag,
* according to RFC 1333.
*/
- ifp->if_obytes += m->m_pkthdr.len + 3;
+ ifp->if_obytes += len + 3;
splx (s);
return (0);
}
@@ -823,7 +843,7 @@ sppp_attach(struct ifnet *ifp)
sp->pp_if.if_type = IFT_PPP;
sp->pp_if.if_output = sppp_output;
- sp->pp_if.if_snd.ifq_maxlen = 50;
+ IFQ_SET_MAXLEN(&sp->pp_if.if_snd, 50);
sp->pp_fastq.ifq_maxlen = 50;
sp->pp_cpq.ifq_maxlen = 50;
sp->pp_loopcnt = 0;
@@ -870,7 +890,7 @@ sppp_flush(struct ifnet *ifp)
{
struct sppp *sp = (struct sppp*) ifp;
- sppp_qflush (&sp->pp_if.if_snd);
+ IFQ_PURGE(&sp->pp_if.if_snd);
sppp_qflush (&sp->pp_fastq);
sppp_qflush (&sp->pp_cpq);
}
@@ -886,7 +906,7 @@ sppp_isempty(struct ifnet *ifp)
s = splimp();
empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&
- !sp->pp_if.if_snd.ifq_head;
+ IFQ_IS_EMPTY(&sp->pp_if.if_snd);
splx(s);
return (empty);
}
@@ -913,7 +933,7 @@ sppp_dequeue(struct ifnet *ifp)
(sppp_ncp_check(sp) || (sp->pp_flags & PP_CISCO) != 0)) {
IF_DEQUEUE(&sp->pp_fastq, m);
if (m == NULL)
- IF_DEQUEUE (&sp->pp_if.if_snd, m);
+ IFQ_DEQUEUE (&sp->pp_if.if_snd, m);
}
splx(s);
return m;
@@ -936,7 +956,7 @@ sppp_pick(struct ifnet *ifp)
(sp->pp_phase == PHASE_NETWORK ||
(sp->pp_flags & PP_CISCO) != 0))
if ((m = sp->pp_fastq.ifq_head) == NULL)
- m = sp->pp_if.if_snd.ifq_head;
+ IFQ_POLL(&sp->pp_if.if_snd, m);
splx (s);
return (m);
}
diff --git a/sys/net/if_strip.c b/sys/net/if_strip.c
index ccf994ce912..6b3d1c8a484 100644
--- a/sys/net/if_strip.c
+++ b/sys/net/if_strip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_strip.c,v 1.14 2001/06/15 03:38:34 itojun Exp $ */
+/* $OpenBSD: if_strip.c,v 1.15 2001/06/27 06:07:44 kjc Exp $ */
/* $NetBSD: if_strip.c,v 1.2.4.3 1996/08/03 00:58:32 jtc Exp $ */
/* from: NetBSD: if_sl.c,v 1.38 1996/02/13 22:00:23 christos Exp $ */
@@ -362,11 +362,12 @@ stripattach(n)
sc->sc_if.if_type = IFT_SLIP;
sc->sc_if.if_ioctl = stripioctl;
sc->sc_if.if_output = stripoutput;
- sc->sc_if.if_snd.ifq_maxlen = 50;
+ IFQ_SET_MAXLEN(&sc->sc_if.if_snd, 50);
sc->sc_fastq.ifq_maxlen = 32;
sc->sc_if.if_watchdog = strip_watchdog;
sc->sc_if.if_timer = STRIP_WATCHDOG_INTERVAL;
+ IFQ_SET_READY(&sc->sc_if.if_snd);
if_attach(&sc->sc_if);
#if NBPFILTER > 0
bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
@@ -715,7 +716,7 @@ stripoutput(ifp, m, dst, rt)
register u_char *dldst; /* link-level next-hop */
int s;
u_char dl_addrbuf[STARMODE_ADDR_LEN+1];
-
+ ALTQ_DECL(struct altq_pktattr pktattr;)
/*
* Verify tty line is up and alive.
@@ -779,13 +780,17 @@ stripoutput(ifp, m, dst, rt)
return (EAFNOSUPPORT);
}
- ifq = &sc->sc_if.if_snd;
+ ifq = NULL;
ip = mtod(m, struct ip *);
if (sc->sc_if.if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
m_freem(m);
return (ENETRESET); /* XXX ? */
}
- if (ip->ip_tos & IPTOS_LOWDELAY)
+ if ((ip->ip_tos & IPTOS_LOWDELAY)
+#ifdef ALTQ
+ && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
+#endif
+ )
ifq = &sc->sc_fastq;
/*
@@ -843,14 +848,22 @@ stripoutput(ifp, m, dst, rt)
stripstart(sc->sc_ttyp);
}
}
- if (IF_QFULL(ifq)) {
- IF_DROP(ifq);
- m_freem(m);
+ if (ifq != NULL) {
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ error = ENOBUFS;
+ } else {
+ IF_ENQUEUE(ifq, m);
+ error = 0;
+ }
+ } else
+ IFQ_ENQUEUE(&sc->sc_if.if_snd, m, &pktattr, error);
+ if (error) {
splx(s);
sc->sc_if.if_oerrors++;
- return (ENOBUFS);
+ return (error);
}
- IF_ENQUEUE(ifq, m);
sc->sc_lastpacket = time;
if ((sc->sc_oqlen = sc->sc_ttyp->t_outq.c_cc) == 0) {
stripstart(sc->sc_ttyp);
@@ -940,7 +953,7 @@ stripstart(tp)
if (m)
sc->sc_if.if_omcasts++; /* XXX */
else
- IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
splx(s);
if (m == NULL) {
return;
diff --git a/sys/net/if_tokensubr.c b/sys/net/if_tokensubr.c
index d0b85026f85..8b745ca24e6 100644
--- a/sys/net/if_tokensubr.c
+++ b/sys/net/if_tokensubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tokensubr.c,v 1.3 2001/06/15 03:38:34 itojun Exp $ */
+/* $OpenBSD: if_tokensubr.c,v 1.4 2001/06/27 06:07:45 kjc Exp $ */
/* $NetBSD: if_tokensubr.c,v 1.7 1999/05/30 00:39:07 bad Exp $ */
/*
@@ -140,7 +140,7 @@ token_output(ifp, m0, dst, rt0)
struct rtentry *rt0;
{
u_int16_t etype;
- int s, error = 0;
+ int s, len, error = 0;
u_char edst[ISO88025_ADDR_LEN];
register struct mbuf *m = m0;
register struct rtentry *rt;
@@ -152,6 +152,8 @@ token_output(ifp, m0, dst, rt0)
struct token_rif *rif = (struct token_rif *)0;
struct token_rif bcastrif;
size_t riflen = 0;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
+ short mflags;
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
@@ -177,6 +179,13 @@ token_output(ifp, m0, dst, rt0)
time.tv_sec < rt->rt_rmx.rmx_expire)
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
+
+ /*
+ * If the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+
switch (dst->sa_family) {
#ifdef INET
@@ -439,23 +448,25 @@ token_output(ifp, m0, dst, rt0)
send:
#endif /* 0 */
+ mflags = m->m_flags;
+ len = m->m_pkthdr.len;
s = splimp();
/*
* Queue message on interface, and start output if interface
* not yet active.
*/
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
+ IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+ if (error) {
+ /* mbuf is already freed */
splx(s);
- senderr(ENOBUFS);
+ return (error);
}
- ifp->if_obytes += m->m_pkthdr.len;
- IF_ENQUEUE(&ifp->if_snd, m);
+ ifp->if_obytes += len;
+ if (mflags & M_MCAST)
+ ifp->if_omcasts++;
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
- if (m->m_flags & M_MCAST)
- ifp->if_omcasts++;
return (error);
bad:
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index e9b7ff47528..e93689d2b8b 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tun.c,v 1.35 2001/06/15 03:38:34 itojun Exp $ */
+/* $OpenBSD: if_tun.c,v 1.36 2001/06/27 06:07:46 kjc Exp $ */
/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
/*
@@ -112,6 +112,9 @@ int tunselect __P((dev_t, int, struct proc *));
static int tuninit __P((struct tun_softc *));
+#ifdef ALTQ
+static void tunstart __P((struct ifnet *));
+#endif
void
tunattach(n)
@@ -132,9 +135,13 @@ tunattach(n)
ifp->if_mtu = TUNMTU;
ifp->if_ioctl = tun_ioctl;
ifp->if_output = tun_output;
+#ifdef ALTQ
+ ifp->if_start = tunstart;
+#endif
ifp->if_flags = IFF_POINTOPOINT;
ifp->if_type = IFT_PROPVIRTUAL;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ IFQ_SET_READY(&ifp->if_snd);
ifp->if_hdrlen = sizeof(u_int32_t);
ifp->if_collisions = 0;
ifp->if_ierrors = 0;
@@ -194,7 +201,6 @@ tunclose(dev, flag, mode, p)
register int unit, s;
struct tun_softc *tp;
struct ifnet *ifp;
- struct mbuf *m;
if ((unit = minor(dev)) >= ntun)
return (ENXIO);
@@ -206,13 +212,9 @@ tunclose(dev, flag, mode, p)
/*
* junk all pending output
*/
- do {
- s = splimp();
- IF_DEQUEUE(&ifp->if_snd, m);
- splx(s);
- if (m)
- m_freem(m);
- } while (m);
+ s = splimp();
+ IFQ_PURGE(&ifp->if_snd);
+ splx(s);
if ((ifp->if_flags & IFF_UP) && !(tp->tun_flags & TUN_STAYUP)) {
s = splimp();
@@ -330,8 +332,9 @@ tun_output(ifp, m0, dst, rt)
struct rtentry *rt;
{
struct tun_softc *tp = ifp->if_softc;
- int s;
+ int s, len, error;
u_int32_t *af;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
TUNDEBUG(("%s: tun_output\n", ifp->if_xname));
@@ -342,6 +345,12 @@ tun_output(ifp, m0, dst, rt)
return EHOSTDOWN;
}
+ /*
+ * if the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
+
M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
af = mtod(m0, u_int32_t *);
*af = htonl(dst->sa_family);
@@ -351,19 +360,17 @@ tun_output(ifp, m0, dst, rt)
bpf_mtap(ifp->if_bpf, m0);
#endif
+ len = m0->m_pkthdr.len + sizeof(*af);
s = splimp();
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
- m_freem(m0);
+ IFQ_ENQUEUE(&ifp->if_snd, m0, &pktattr, error);
+ if (error) {
splx(s);
ifp->if_collisions++;
- return (ENOBUFS);
+ return (error);
}
- IF_ENQUEUE(&ifp->if_snd, m0);
-
- ifp->if_opackets++;
- ifp->if_obytes += m0->m_pkthdr.len + sizeof(*af);
splx(s);
+ ifp->if_opackets++;
+ ifp->if_obytes += len;
if (tp->tun_flags & TUN_RWAIT) {
tp->tun_flags &= ~TUN_RWAIT;
@@ -510,7 +517,7 @@ tunread(dev, uio, ioflag)
splx(s);
return (error);
}
- IF_DEQUEUE(&ifp->if_snd, m0);
+ IFQ_DEQUEUE(&ifp->if_snd, m0);
if (m0 == 0) {
if (tp->tun_flags & TUN_NBIO && ioflag & IO_NDELAY) {
splx(s);
@@ -716,3 +723,34 @@ tunselect(dev, rw, p)
TUNDEBUG(("%s: tunselect waiting\n", ifp->if_xname));
return 0;
}
+
+#ifdef ALTQ
+/*
+ * Start packet transmission on the interface.
+ * when the interface queue is rate-limited by ALTQ or TBR,
+ * if_start is needed to drain packets from the queue in order
+ * to notify readers when outgoing packets become ready.
+ */
+static void
+tunstart(ifp)
+ struct ifnet *ifp;
+{
+ struct tun_softc *tp = ifp->if_softc;
+ struct mbuf *m;
+
+ if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
+ return;
+
+ IFQ_POLL(&ifp->if_snd, m);
+ if (m != NULL) {
+ if (tp->tun_flags & TUN_RWAIT) {
+ tp->tun_flags &= ~TUN_RWAIT;
+ wakeup((caddr_t)tp);
+ }
+ if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
+ csignal(tp->tun_pgid, SIGIO,
+ tp->tun_siguid, tp->tun_sigeuid);
+ selwakeup(&tp->tun_rsel);
+ }
+}
+#endif
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index fcb27c76b22..5f7546803fa 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vlan.c,v 1.23 2001/06/27 03:49:53 angelos Exp $ */
+/* $OpenBSD: if_vlan.c,v 1.24 2001/06/27 06:07:46 kjc Exp $ */
/*
* Copyright 1998 Massachusetts Institute of Technology
*
@@ -165,7 +165,8 @@ vlanattach(void *dummy)
ifp->if_start = vlan_start;
ifp->if_ioctl = vlan_ioctl;
ifp->if_output = ether_output;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ IFQ_SET_READY(&ifp->if_snd);
if_attach(ifp);
ether_ifattach(ifp);
@@ -182,13 +183,15 @@ vlan_start(struct ifnet *ifp)
struct ifnet *p;
struct ether_vlan_header *evl;
struct mbuf *m, *m0;
+ int error;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
ifv = ifp->if_softc;
p = ifv->ifv_p;
ifp->if_flags |= IFF_OACTIVE;
for (;;) {
- IF_DEQUEUE(&ifp->if_snd, m);
+ IFQ_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
@@ -201,6 +204,26 @@ vlan_start(struct ifnet *ifp)
continue;
}
+#ifdef ALTQ
+ /*
+ * If ALTQ is enabled on the parent interface, do
+ * classification; the queueing discipline might
+ * not require classification, but might require
+ * the address family/header pointer in the pktattr.
+ */
+ if (ALTQ_IS_ENABLED(&p->if_snd)) {
+ switch (p->if_type) {
+ case IFT_ETHER:
+ altq_etherclassify(&p->if_snd, m, &pktattr);
+ break;
+#ifdef DIAGNOSTIC
+ default:
+ panic("vlan_start: impossible (altq)");
+#endif
+ }
+ }
+#endif /* ALTQ */
+
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
@@ -271,17 +294,16 @@ vlan_start(struct ifnet *ifp)
* Send it, precisely as ether_output() would have.
* We are already running at splimp.
*/
- if (IF_QFULL(&p->if_snd)) {
- IF_DROP(&p->if_snd);
- /* XXX stats */
- ifp->if_oerrors++;
- m_freem(m);
- continue;
- }
p->if_obytes += m->m_pkthdr.len;
if (m->m_flags & M_MCAST)
p->if_omcasts++;
- IF_ENQUEUE(&p->if_snd, m);
+ IFQ_ENQUEUE(&p->if_snd, m, &pktattr, error);
+ if (error) {
+ /* mbuf is already freed */
+ ifp->if_oerrors++;
+ continue;
+ }
+
ifp->if_opackets++;
if ((p->if_flags & IFF_OACTIVE) == 0)
p->if_start(p);
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 7abd64b245a..308effcfd9a 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.h,v 1.16 2001/06/23 21:32:26 fgsch Exp $ */
+/* $OpenBSD: if_ether.h,v 1.17 2001/06/27 06:07:47 kjc Exp $ */
/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */
/*
@@ -285,6 +285,9 @@ void revarprequest __P((struct ifnet *));
int revarpwhoarewe __P((struct ifnet *, struct in_addr *, struct in_addr *));
int revarpwhoami __P((struct in_addr *, struct ifnet *));
int db_show_arptab __P((void));
+#ifdef ALTQ
+void altq_etherclassify(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
+#endif /* ALTQ */
#else