diff -urN ../sys/Makefile ./Makefile
--- ../sys/Makefile	Mon Nov  8 09:16:40 1999
+++ ./Makefile	Fri Oct  5 14:59:17 2001
@@ -3,6 +3,7 @@
 SUBDIR=	adosfs arch compat dev filecorefs isofs miscfs msdosfs net \
 	netatalk netccitt netinet netinet6 netiso netkey netnatm netns \
 	nfs ntfs sys ufs uvm vm
+SUBDIR+=altq
 
 .if (${MACHINE_ARCH} != "mipseb" && ${MACHINE_ARCH} != "mipsel")
 
diff -urN ../sys/arch/alpha/alpha/conf.c ./arch/alpha/alpha/conf.c
--- ../sys/arch/alpha/alpha/conf.c	Tue May  1 19:42:41 2001
+++ ./arch/alpha/alpha/conf.c	Thu Oct  4 15:12:02 2001
@@ -333,6 +333,9 @@
 	cdev_disk_init(NCA,ca),		/* 59: Compaq array */
 	cdev_tty_init(NCY,cy),		/* 60: Cyclades Cyclom-Y serial */
 	cdev_tty_init(NCZ,cztty),	/* 61: Cyclades-Z serial */
+#ifdef ALTQ
+	cdev_notdef(),			/* 62: ALTQ */
+#endif
 };
 int	nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
 
diff -urN ../sys/arch/alpha/conf/ALTQ ./arch/alpha/conf/ALTQ
--- ../sys/arch/alpha/conf/ALTQ	Thu Jan  1 09:00:00 1970
+++ ./arch/alpha/conf/ALTQ	Thu Oct  4 15:12:02 2001
@@ -0,0 +1,22 @@
+include	"arch/alpha/conf/GENERIC"
+
+# a pseudo device needed for ALTQ
+pseudo-device	altq			# altq pseudo-device
+
+# ALTQ options - DOES NOT WORK
+options 	ALTQ		#alternate queueing
+options 	ALTQ_CBQ	#class based queueing
+options 	ALTQ_WFQ	#weighted fair queueing
+options 	ALTQ_FIFOQ	#fifo queueing
+options 	ALTQ_RED	#random early detection
+#options 	ALTQ_FLOWVALVE	#flowvalve for RED (needs RED)
+options 	ALTQ_RIO	#triple red for diffserv (needs RED)
+#options 	ALTQ_LOCALQ	#local use
+options 	ALTQ_HFSC	#hierarchical fair service curve
+#options 	ALTQ_ECN	#ecn extention to tcp (needs RED)
+#options 	ALTQ_IPSEC	#check ipsec in IPv4
+options 	ALTQ_CDNR	#diffserv traffic conditioner
+#options 	ALTQ_BLUE	#blue by wu-chang feng
+options 	ALTQ_PRIQ	#priority queue
+#options 	ALTQ_NOPCC	#don't use processor cycle counter
+#options 	ALTQ_DEBUG	#for debugging
diff -urN ../sys/arch/i386/conf/ALTQ ./arch/i386/conf/ALTQ
--- ../sys/arch/i386/conf/ALTQ	Thu Jan  1 09:00:00 1970
+++ ./arch/i386/conf/ALTQ	Thu Oct  4 15:12:03 2001
@@ -0,0 +1,22 @@
+include	"arch/i386/conf/GENERIC"
+
+# a pseudo device needed for ALTQ
+pseudo-device	altq			# altq pseudo-device
+
+# ALTQ options
+options 	ALTQ		#alternate queueing
+options 	ALTQ_CBQ	#class based queueing
+options 	ALTQ_WFQ	#weighted fair queueing
+options 	ALTQ_FIFOQ	#fifo queueing
+options 	ALTQ_RED	#random early detection
+#options 	ALTQ_FLOWVALVE	#flowvalve for RED (needs RED)
+options 	ALTQ_RIO	#triple red for diffserv (needs RED)
+#options 	ALTQ_LOCALQ	#local use
+options 	ALTQ_HFSC	#hierarchical fair service curve
+#options 	ALTQ_ECN	#ecn extention to tcp (needs RED)
+#options 	ALTQ_IPSEC	#check ipsec in IPv4
+options 	ALTQ_CDNR	#diffserv traffic conditioner
+#options 	ALTQ_BLUE	#blue by wu-chang feng
+options 	ALTQ_PRIQ	#priority queue
+#options 	ALTQ_NOPCC	#don't use processor cycle counter
+#options 	ALTQ_DEBUG	#for debugging
diff -urN ../sys/arch/i386/i386/conf.c ./arch/i386/i386/conf.c
--- ../sys/arch/i386/i386/conf.c	Tue May  1 19:41:30 2001
+++ ./arch/i386/i386/conf.c	Thu Oct  4 15:12:03 2001
@@ -390,6 +390,9 @@
 	cdev_notdef(),			/* 72 */
 	cdev_tty_init(NCZ,cztty),	/* 73: Cyclades-Z serial port */
 	cdev_ses_init(NSES,ses),	/* 74: SCSI SES/SAF-TE */
+#ifdef ALTQ
+	cdev_notdef(),			/* 75: ALTQ */
+#endif
 };
 int	nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
 
diff -urN ../sys/conf/files ./conf/files
--- ../sys/conf/files	Sat Mar 31 06:51:22 2001
+++ ./conf/files	Thu Oct  4 15:12:03 2001
@@ -75,6 +75,8 @@
 defopt	TCP_RECVSPACE
 defopt	TCP_SENDSPACE
 
+defopt	opt_altq.h	ALTQ_CBQ ALTQ_WFQ ALTQ_FIFOQ ALTQ_RED ALTQ_FLOWVALVE ALTQ_RIO ALTQ_LOCALQ ALTQ_HFSC ALTQ_CDNR ALTQ_BLUE ALTQ_PRIQ ALTQ_NOPCC ALTQ_DEBUG
+
 defopt	SB_MAX
 
 # UVM options
@@ -546,6 +548,7 @@
 defpseudo gif: ifnet
 defpseudo faith: ifnet
 defpseudo stf: ifnet
+defpseudo altq: ifnet
 
 defpseudo sequencer
 
@@ -554,6 +557,20 @@
 file adosfs/adutil.c			adosfs
 file adosfs/advfsops.c			adosfs
 file adosfs/advnops.c			adosfs
+file altq/altq_conf.c			altq
+file altq/altq_afmap.c			altq
+file altq/altq_blue.c			altq
+file altq/altq_cbq.c			altq
+file altq/altq_cdnr.c			altq
+file altq/altq_fifoq.c			altq
+file altq/altq_hfsc.c			altq
+file altq/altq_localq.c			altq
+file altq/altq_priq.c			altq
+file altq/altq_red.c			altq
+file altq/altq_rio.c			altq
+file altq/altq_rmclass.c		altq
+file altq/altq_subr.c			altq
+file altq/altq_wfq.c			altq
 file coda/coda_namecache.c		coda
 file coda/coda_psdev.c			vcoda			needs-count
 file coda/coda_subr.c			coda
diff -urN ../sys/dev/ic/awi.c ./dev/ic/awi.c
--- ../sys/dev/ic/awi.c	Mon May  7 00:04:35 2001
+++ ./dev/ic/awi.c	Thu Oct  4 15:12:03 2001
@@ -306,10 +306,11 @@
 #endif
 #ifdef __FreeBSD__
 	ifp->if_output = ether_output;
-	ifp->if_snd.ifq_maxlen = ifqmaxlen;
+	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
 	memcpy(sc->sc_ec.ac_enaddr, sc->sc_mib_addr.aMAC_Address,
 	    ETHER_ADDR_LEN);
 #endif
+	IFQ_SET_READY(&ifp->if_snd);
 
 	printf("%s: IEEE802.11 %s %dMbps (firmware %s)\n",
 	    sc->sc_dev.dv_xname,
@@ -883,12 +884,7 @@
 			break;
 		m_freem(m);
 	}
-	for (;;) {
-		IF_DEQUEUE(&ifp->if_snd, m);
-		if (m == NULL)
-			break;
-		m_freem(m);
-	}
+	IFQ_PURGE(&ifp->if_snd);
 	while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
 		TAILQ_REMOVE(&sc->sc_scan, bp, list);
 		free(bp, M_DEVBUF);
@@ -967,7 +963,7 @@
 		} else {
 			if (!(ifp->if_flags & IFF_RUNNING))
 				break;
-			IF_DEQUEUE(&ifp->if_snd, m0);
+			IFQ_POLL(&ifp->if_snd, m0);
 			if (m0 == NULL)
 				break;
 			len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
@@ -978,10 +974,10 @@
 				len += IEEE80211_WEP_IVLEN +
 				    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
 			if (awi_next_txd(sc, len, &frame, &ntxd)) {
-				IF_PREPEND(&ifp->if_snd, m0);
 				ifp->if_flags |= IFF_OACTIVE;
 				break;
 			}
+			IFQ_DEQUEUE(&ifp->if_snd, m0);
 			AWI_BPF_MTAP(sc, m0, AWI_BPF_NORM);
 			m0 = awi_fix_txhdr(sc, m0);
 			if (sc->sc_wep_algo != NULL && m0 != NULL)
diff -urN ../sys/dev/ic/dp8390.c ./dev/ic/dp8390.c
--- ../sys/dev/ic/dp8390.c	Mon Jan  1 05:14:43 2001
+++ ./dev/ic/dp8390.c	Thu Oct  4 15:12:03 2001
@@ -143,6 +143,7 @@
 		ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
 		ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
 	}
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * We can support 802.1Q VLAN-sized frames.
@@ -481,7 +482,7 @@
 		ifp->if_flags |= IFF_OACTIVE;
 		return;
 	}
-	IF_DEQUEUE(&ifp->if_snd, m0);
+	IFQ_DEQUEUE(&ifp->if_snd, m0);
 	if (m0 == 0)
 		return;
 
diff -urN ../sys/dev/ic/elink3.c ./dev/ic/elink3.c
--- ../sys/dev/ic/elink3.c	Tue May 30 02:37:12 2000
+++ ./dev/ic/elink3.c	Thu Oct  4 15:12:03 2001
@@ -432,6 +432,7 @@
 	ifp->if_watchdog = epwatchdog;
 	ifp->if_flags =
 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	if_attach(ifp);
 	ether_ifattach(ifp, enaddr);
@@ -1140,7 +1141,7 @@
 
 startagain:
 	/* Sneak a peek at the next packet */
-	m0 = ifp->if_snd.ifq_head;
+	IFQ_POLL(&ifp->if_snd, m0);
 	if (m0 == 0)
 		return;
 
@@ -1159,7 +1160,7 @@
 	if (len + pad > ETHER_MAX_LEN) {
 		/* packet is obviously too large: toss it */
 		++ifp->if_oerrors;
-		IF_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_DEQUEUE(&ifp->if_snd, m0);
 		m_freem(m0);
 		goto readcheck;
 	}
@@ -1177,7 +1178,7 @@
 		    SET_TX_AVAIL_THRESH | ELINK_THRESH_DISABLE);
 	}
 
-	IF_DEQUEUE(&ifp->if_snd, m0);
+	IFQ_DEQUEUE(&ifp->if_snd, m0);
 	if (m0 == 0)		/* not really needed */
 		return;
 
diff -urN ../sys/dev/ic/elinkxl.c ./dev/ic/elinkxl.c
--- ../sys/dev/ic/elinkxl.c	Wed May 16 06:34:06 2001
+++ ./dev/ic/elinkxl.c	Thu Oct  4 15:12:03 2001
@@ -434,6 +434,7 @@
 	ifp->if_watchdog = ex_watchdog;
 	ifp->if_flags =
 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * We can support 802.1Q VLAN-sized frames.
@@ -934,14 +935,16 @@
 	 * We're finished if there is nothing more to add to the list or if
 	 * we're all filled up with buffers to transmit.
 	 */
-	while (ifp->if_snd.ifq_head != NULL && sc->tx_free != NULL) {
+	while (!IFQ_IS_EMPTY(&ifp->if_snd) && sc->tx_free != NULL) {
 		struct mbuf *mb_head;
 		int segment, error;
 
 		/*
 		 * Grab a packet to transmit.
 		 */
-		IF_DEQUEUE(&ifp->if_snd, mb_head);
+		IFQ_DEQUEUE(&ifp->if_snd, mb_head);
+		if (mb_head == NULL)
+			break;
 
 		/*
 		 * Get pointer to next available tx desc.
@@ -1274,7 +1277,7 @@
 	}
 
 	/* no more interrupts */
-	if (ret && ifp->if_snd.ifq_head)
+	if (ret && !IFQ_IS_EMPTY(&ifp->if_snd))
 		ex_start(ifp);
 	return ret;
 }
diff -urN ../sys/dev/ic/hd64570.c ./dev/ic/hd64570.c
--- ../sys/dev/ic/hd64570.c	Mon Jan 10 02:32:58 2000
+++ ./dev/ic/hd64570.c	Thu Oct  4 15:12:03 2001
@@ -447,11 +447,12 @@
 	ifp->if_ioctl = sca_ioctl;
 	ifp->if_output = sca_output;
 	ifp->if_watchdog = sca_watchdog;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 	scp->linkq.ifq_maxlen = 5; /* if we exceed this we are hosed already */
 #ifdef SCA_USE_FASTQ
 	scp->fastq.ifq_maxlen = IFQ_MAXLEN;
 #endif
+	IFQ_SET_READY(&ifp->if_snd);
 	if_attach(ifp);
 
 #if NBPFILTER > 0
@@ -798,7 +799,11 @@
 #endif
 	struct hdlc_header *hdlc;
 	struct ifqueue *ifq;
-	int s, error;
+	int s, error, len;
+	short mflags;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	error = 0;
 	ifp->if_lastchange = time;
@@ -808,7 +813,14 @@
 		goto bad;
 	}
 
-	ifq = &ifp->if_snd;
+#ifdef ALTQ
+	/*
+	 * if the queueing discipline needs packet classification,
+	 * do it before prepending link headers.
+	 */
+	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+#endif
+	ifq = NULL;
 
 	/*
 	 * determine address family, and priority for this packet
@@ -818,7 +830,7 @@
 	case AF_INET:
 #ifdef SCA_USE_FASTQ
 		if ((mtod(m, struct ip *)->ip_tos & IPTOS_LOWDELAY)
-		    == IPTOS_LOWDELAY)
+		    == IPTOS_LOWDELAY && !ALTQ_IS_ENABLED(&ifp->if_snd))
 			ifq = &((sca_port_t *)ifp->if_softc)->fastq;
 #endif
 		/*
@@ -864,21 +876,33 @@
 	/*
 	 * queue the packet.  If interactive, use the fast queue.
 	 */
+	mflags = m->m_flags;
+	len = m->m_pkthdr.len;
 	s = splnet();
-	if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
+	if (ifq != NULL) {
+		if (IF_QFULL(ifq)) {
+			IF_DROP(ifq);
+			m_freem(m);
+			error = ENOBUFS;
+		} else
+			IF_ENQUEUE(ifq, m);
+	} else {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+#else
+		IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#endif
+	}
+
+	if (error != 0) {
+		splx(s);
 		ifp->if_oerrors++;
 		ifp->if_collisions++;
-		error = ENOBUFS;
-		splx(s);
-		goto bad;
+		return (error);
 	}
-	ifp->if_obytes += m->m_pkthdr.len;
-	IF_ENQUEUE(ifq, m);
-
+	ifp->if_obytes += len;
 	ifp->if_lastchange = time;
-
-	if (m->m_flags & M_MCAST)
+	if (mflags & M_MCAST)
 		ifp->if_omcasts++;
 
 	sca_start(ifp);
@@ -1021,7 +1045,7 @@
 		IF_DEQUEUE(&scp->fastq, mb_head);
 	if (mb_head == NULL)
 #endif
-		IF_DEQUEUE(&ifp->if_snd, mb_head);
+		IFQ_DEQUEUE(&ifp->if_snd, mb_head);
 	if (mb_head == NULL)
 		goto start_xmit;
 
diff -urN ../sys/dev/ic/i82557.c ./dev/ic/i82557.c
--- ../sys/dev/ic/i82557.c	Mon May  7 00:04:55 2001
+++ ./dev/ic/i82557.c	Thu Oct  4 15:12:03 2001
@@ -331,6 +331,7 @@
 	ifp->if_ioctl = fxp_ioctl;
 	ifp->if_start = fxp_start;
 	ifp->if_watchdog = fxp_watchdog;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * We can support 802.1Q VLAN-sized frames.
@@ -732,7 +733,7 @@
 		/*
 		 * Grab a packet off the queue.
 		 */
-		IF_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_POLL(&ifp->if_snd, m0);
 		if (m0 == NULL)
 			break;
 
@@ -757,7 +758,6 @@
 			if (m == NULL) {
 				printf("%s: unable to allocate Tx mbuf\n",
 				    sc->sc_dev.dv_xname);
-				IF_PREPEND(&ifp->if_snd, m0);
 				break;
 			}
 			if (m0->m_pkthdr.len > MHLEN) {
@@ -766,7 +766,6 @@
 					printf("%s: unable to allocate Tx "
 					    "cluster\n", sc->sc_dev.dv_xname);
 					m_freem(m);
-					IF_PREPEND(&ifp->if_snd, m0);
 					break;
 				}
 			}
@@ -779,10 +778,15 @@
 			if (error) {
 				printf("%s: unable to load Tx buffer, "
 				    "error = %d\n", sc->sc_dev.dv_xname, error);
-				IF_PREPEND(&ifp->if_snd, m0);
 				break;
 			}
 		}
+
+		/*
+		 * at this point, we are committed to transmit the packet.
+		 * (don't dequeue the packet to m0; it could hold a copy)
+		 */
+		IFQ_DEQUEUE(&ifp->if_snd, m);
 
 		/* Initialize the fraglist. */
 		for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
diff -urN ../sys/dev/ic/lemac.c ./dev/ic/lemac.c
--- ../sys/dev/ic/lemac.c	Sat May 13 01:45:42 2000
+++ ./dev/ic/lemac.c	Thu Oct  4 15:12:03 2001
@@ -639,14 +639,13 @@
     struct ifnet *ifp)
 {
     lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
-    struct ifqueue * const ifq = &ifp->if_snd;
 
     if ((ifp->if_flags & IFF_RUNNING) == 0)
 	return;
 
     LEMAC_INTR_DISABLE(sc);
 
-    while (ifq->ifq_head != NULL) {
+    while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 	struct mbuf *m;
 	struct mbuf *m0;
 	int tx_pg;
@@ -670,7 +669,9 @@
 	    break;
 	}
 
-	IF_DEQUEUE(ifq, m);
+	IFQ_DEQUEUE(&ifp->if_snd, m);
+	if (m == NULL)
+		break;
 
 	/*
 	 * The first four bytes of each transmit buffer are for
@@ -1041,6 +1042,7 @@
 	| IFF_NOTRAILERS
 #endif
 	| IFF_MULTICAST;
+    IFQ_SET_READY(&ifp->if_snd);
 
     if (sc->sc_flags & LEMAC_ALIVE) {
 	int media;
diff -urN ../sys/dev/ic/midway.c ./dev/ic/midway.c
--- ../sys/dev/ic/midway.c	Mon May  7 00:08:57 2001
+++ ./dev/ic/midway.c	Thu Oct  4 15:12:03 2001
@@ -251,7 +251,7 @@
 #define ENOTHER_RAW	0x04		/* 'raw' access  (aka boodi mode) */
 #define ENOTHER_SWSL	0x08		/* in software service list */
 
-int en_dma = EN_DMA;			/* use DMA (switch off for dbg) */
+static int en_dma = EN_DMA;		/* use DMA (switch off for dbg) */
 
 /*
  * autoconfig attachments
@@ -803,6 +803,7 @@
   ifp->if_ioctl = en_ioctl;
   ifp->if_output = atm_output;
   ifp->if_start = en_start;
+  IFQ_SET_READY(&ifp->if_snd);
 
   /*
    * init softc
@@ -1324,6 +1325,22 @@
 			error = en_pvctx(sc, (struct pvctxreq *)data);
 		break;
 
+	case SIOCGPVCFWD:
+	{
+		struct pvcfwdreq *req = (struct pvcfwdreq *)data;
+		error = pvc_set_fwd(req->pvc_ifname, req->pvc_ifname2, 2);
+		break;
+	}	
+
+	case SIOCSPVCFWD:
+	{
+		struct pvcfwdreq *req = (struct pvcfwdreq *)data;
+		if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) == 0)
+			error = pvc_set_fwd(req->pvc_ifname, req->pvc_ifname2,
+					    req->pvc_op);
+		break;
+	}
+
 #endif /* ATM_PVCEXT */
 
 	default: 
@@ -1676,7 +1693,6 @@
 #else
     struct en_softc *sc = (struct en_softc *) ifp->if_softc;
 #endif
-    struct ifqueue *ifq = &ifp->if_snd; /* if INPUT QUEUE */
     struct mbuf *m, *lastm, *prev;
     struct atm_pseudohdr *ap, *new_ap;
     int txchan, mlen, got, need, toadd, cellcnt, first;
@@ -1693,7 +1709,7 @@
 
     while (1) {
 
-      IF_DEQUEUE(ifq, m);
+      IFQ_DEQUEUE(&ifp->if_snd, m);
       if (m == NULL)
 	return;		/* EMPTY: >>> exit here <<< */
     
@@ -2932,6 +2948,28 @@
   sc->vtrash += MID_VTRASH(reg);
 #endif
 
+#ifdef ATM_PVCEXT
+  /*
+   * when the tx buffer is full, packets are left in the interface queue.
+   * (en dequeues all packets even when the tx buffer is full.)
+   * call en_start for each pvc interface using round-robin scheduling
+   * to avoid starvation.
+   */
+  if (kick) {
+    struct rrp *rrp_start;
+
+    if ((rrp_start = sc->txrrp) != NULL) {
+      while (1) {
+	en_start(sc->txrrp->ifp);
+	if (sc->txrrp->next == rrp_start)
+	  break;
+	else
+	  sc->txrrp = sc->txrrp->next;
+      }
+    }
+  }
+#endif
+
   EN_INTR_RET(1); /* for us */
 }
 
@@ -3707,6 +3745,7 @@
 	pvc_ifp->if_start = en_start;
 	pvc_ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST) |
 		(ifp->if_flags & (IFF_RUNNING|IFF_SIMPLEX|IFF_NOTRAILERS));
+	IFQ_SET_READY(&pvc_ifp->if_snd);
 
 	s = splimp();
 	LIST_INSERT_HEAD(&sc->sif_list, (struct pvcsif *)pvc_ifp, sif_links);
@@ -3958,7 +3997,7 @@
 	if (ifp == &sc->enif) {
 		/* physical interface: assume vci is specified */
 		struct atm_pseudohdr *pvc_aph;
-		
+
 		pvc_aph = &pvcreq->pvc_aph;
 		vci = ATM_PH_VCI(pvc_aph);
 		if ((slot = sc->rxvc2slot[vci]) == RX_NONE)
diff -urN ../sys/dev/ic/pdq_ifsubr.c ./dev/ic/pdq_ifsubr.c
--- ../sys/dev/ic/pdq_ifsubr.c	Tue Mar  7 09:33:13 2000
+++ ./dev/ic/pdq_ifsubr.c	Thu Oct  4 15:12:03 2001
@@ -162,7 +162,7 @@
     ifp->if_timer = 0;
     for (;;) {
 	struct mbuf *m;
-	IF_DEQUEUE(&ifp->if_snd, m);
+	IFQ_DEQUEUE(&ifp->if_snd, m);
 	if (m == NULL)
 	    return;
 	PDQ_OS_DATABUF_FREE(PDQ_OS_IFP_TO_SOFTC(ifp)->sc_pdq, m);
@@ -174,7 +174,6 @@
     struct ifnet *ifp)
 {
     pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp);
-    struct ifqueue *ifq = &ifp->if_snd;
     struct mbuf *m;
     int tx = 0;
 
@@ -189,7 +188,7 @@
 	return;
     }
     for (;; tx = 1) {
-	IF_DEQUEUE(ifq, m);
+	IFQ_POLL(&ifp->if_snd, m);
 	if (m == NULL)
 	    break;
 #if defined(PDQ_BUS_DMA) && !defined(PDQ_BUS_DMA_NOTX)
@@ -222,10 +221,11 @@
 
 	if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE)
 	    break;
+
+	IFQ_DEQUEUE(&ifp->if_snd, m);
     }
     if (m != NULL) {
 	ifp->if_flags |= IFF_OACTIVE;
-	IF_PREPEND(ifq, m);
     }
     if (tx)
 	PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
@@ -281,7 +281,7 @@
 {
     pdq_softc_t *sc = pdq->pdq_os_ctx;
     sc->sc_if.if_flags &= ~IFF_OACTIVE;
-    if (sc->sc_if.if_snd.ifq_head != NULL) {
+    if (!IFQ_IS_EMPTY(&sc->sc_if.if_snd)) {
 	sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
 	pdq_ifstart(&sc->sc_if);
     } else {
@@ -558,6 +558,9 @@
     ifp->if_output = fddi_output;
 #endif
     ifp->if_start = pdq_ifstart;
+#ifdef notyet /* if_fddisubr.c hasn't been converted yet */
+    IFQ_SET_READY(&ifp->if_snd);
+#endif
 
 #if defined(IFM_FDDI)
     {
diff -urN ../sys/dev/ic/tropic.c ./dev/ic/tropic.c
--- ../sys/dev/ic/tropic.c	Thu Nov  2 08:24:45 2000
+++ ./dev/ic/tropic.c	Thu Oct  4 15:12:03 2001
@@ -57,13 +57,14 @@
 #include <net/netisr.h>
 #include <net/route.h>
 
+#include <net/if_token.h>
+
 #ifdef INET
 #include <netinet/in.h>
 #include <netinet/if_inarp.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #include <netinet/in_var.h>
-#include <net/if_token.h>
 #endif
 
 #ifdef NS
@@ -349,6 +350,9 @@
 		ifp->if_start = tr_oldstart;
 	ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
 	ifp->if_watchdog = tr_watchdog;
+#ifdef notyet /* if_tokensubr.c hasn't been converted yet */
+	IFQ_SET_READY(&ifp->if_snd);
+#endif
 
 	switch (MM_INB(sc, TR_MEDIAS_OFFSET)) {
 	case 0xF:
@@ -743,7 +747,7 @@
 		return;
 
 	/* if data in queue, copy mbuf chain to fast path buffers */
-	IF_DEQUEUE(&ifp->if_snd, m0);
+	IFQ_DEQUEUE(&ifp->if_snd, m0);
 
 	if (m0 == 0)
 		return;
@@ -813,9 +817,6 @@
 #endif
 }
 
-
-#define	IF_EMPTYQUEUE(queue) ((queue).ifq_head == 0)
-
 /*
  *  tr_intr - interrupt handler.  Find the cause of the interrupt and
  *  service it.
@@ -1055,7 +1056,7 @@
 					    sc->sc_dev.dv_xname);
 					ifp->if_flags &= ~IFF_RUNNING;
 					ifp->if_flags &= ~IFF_UP;
-					if_qflush(&ifp->if_snd);
+					IFQ_PURGE(&ifp->if_snd);
 					callout_reset(&sc->sc_reinit_callout,
 					    hz * 30, tr_reinit, sc);
 				}
@@ -1131,7 +1132,7 @@
  * XXX should this be done here ?
  */
 				/* if data on send queue */
-				if (!IF_EMPTYQUEUE(ifp->if_snd))
+				if (!IFQ_IS_EMPTY(&ifp->if_snd))
 					tr_oldstart(ifp);
 				break;
 
@@ -1365,7 +1366,7 @@
  * XXX what's command here ?  command = 0x0d (always ?)
  */
 		/* if data in queue, copy mbuf chain to DHB */
-		IF_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_DEQUEUE(&ifp->if_snd, m0);
 		if (m0 != 0) {
 #if NBPFILTER > 0
 			if (ifp->if_bpf)
@@ -1576,7 +1577,7 @@
 			}
 			arp_ifinit(ifp, ifa);
 			break;
-#endif INET
+#endif /*INET*/
 		default:
 			/* XXX if not running */
 			if ((ifp->if_flags & IFF_RUNNING) == 0) {
diff -urN ../sys/dev/isa/cs89x0.c ./dev/isa/cs89x0.c
--- ../sys/dev/isa/cs89x0.c	Wed Feb  9 03:40:51 2000
+++ ./dev/isa/cs89x0.c	Thu Oct  4 15:12:03 2001
@@ -367,6 +367,7 @@
 	ifp->if_watchdog = NULL;	/* no watchdog at this stage */
 	ifp->if_flags = IFF_SIMPLEX | IFF_NOTRAILERS |
 	    IFF_BROADCAST | IFF_MULTICAST;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/* Initialize ifmedia structures. */
 	ifmedia_init(&sc->sc_media, 0, cs_mediachange, cs_mediastatus);
@@ -1485,7 +1486,7 @@
 	sc->sc_txbusy = FALSE;
 
 	/* If there is more to transmit */
-	if (ifp->if_snd.ifq_head != NULL) {
+	if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 		/* Start the next transmission */
 		cs_start_output(ifp);
 	}
@@ -2019,14 +2020,12 @@
 	struct cs_softc *sc;
 	struct mbuf *pMbuf;
 	struct mbuf *pMbufChain;
-	struct ifqueue *pTxQueue;
 	u_int16_t BusStatus;
 	u_int16_t Length;
 	int txLoop = 0;
 	int dropout = 0;
 
 	sc = ifp->if_softc;
-	pTxQueue = &sc->sc_ethercom.ec_if.if_snd;
 
 	/* check that the interface is up and running */
 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) {
@@ -2043,9 +2042,11 @@
 	 * While there are packets to transmit and a transmit is not in
 	 * progress
 	 */
-	while ((pTxQueue->ifq_head != NULL) && !(sc->sc_txbusy) &&
+	while (!IFQ_IS_EMPTY(&ifp->if_snd) && !(sc->sc_txbusy) &&
 	    !(dropout)) {
-		IF_DEQUEUE(pTxQueue, pMbufChain);
+		IFQ_DEQUEUE(&ifp->if_snd, pMbufChain);
+		if (pMbufChain == NULL)
+			break;
 
 #if NBPFILTER > 0
 		/*
diff -urN ../sys/dev/pci/if_de.c ./dev/pci/if_de.c
--- ../sys/dev/pci/if_de.c	Thu Mar 23 16:01:37 2000
+++ ./dev/pci/if_de.c	Thu Oct  4 15:12:04 2001
@@ -4325,6 +4325,11 @@
 #else
     struct mbuf *m0;
 #endif
+#if 1 /* ALTQ */
+    struct ifnet *ifp = &sc->tulip_if;
+    struct mbuf *ombuf = m;
+    int compressed = 0;
+#endif
 
 #if defined(TULIP_DEBUG)
     if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
@@ -4475,6 +4480,26 @@
 		 * entries that we can use for one packet, so we have
 		 * recopy it into one mbuf and then try again.
 		 */
+#if 1 /* ALTQ */
+		struct mbuf *tmp;
+		/*
+		 * tulip_mbuf_compress() frees the original mbuf.
+		 * thus, we have to remove the mbuf from the queue
+		 * before calling it.
+		 * we don't have to worry about space shortage
+		 * after compressing the mbuf since the compressed
+		 * mbuf will take only two segs.
+		 */
+		if (compressed) {
+		    /* should not happen */
+		    printf("tulip_txput: compress called twice!\n");
+		    goto finish;
+		}
+		IFQ_DEQUEUE(&ifp->if_snd, tmp);
+		if (tmp != ombuf)
+		    panic("tulip_txput: different mbuf dequeued!");
+		compressed = 1;
+#endif
 		m = tulip_mbuf_compress(m);
 		if (m == NULL)
 		    goto finish;
@@ -4530,6 +4555,16 @@
      * The descriptors have been filled in.  Now get ready
      * to transmit.
      */
+#if 1 /* ALTQ */
+    if (!compressed && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) {
+	/* remove the mbuf from the queue */
+	struct mbuf *tmp;
+	IFQ_DEQUEUE(&ifp->if_snd, tmp);
+	if (tmp != ombuf)
+	    panic("tulip_txput: different mbuf dequeued!");
+    }
+#endif
+
     IF_ENQUEUE(&sc->tulip_txq, m);
     m = NULL;
 
@@ -4900,6 +4935,14 @@
     return error;
 }
 
+#if 1 /* ALTQ */
+/*
+ * the original dequeueing policy is dequeue-and-prepend if something
+ * goes wrong.  when altq is used, it is changed to peek-and-dequeue.
+ * the modification becomes a bit complicated since tulip_txput() might
+ * copy and modify the mbuf passed.
+ */
+#endif
 /*
  * These routines gets called at device spl (from ether_output).  This might
  * pose a problem for TULIP_USE_SOFTINTR if ether_output is called at
@@ -4918,15 +4961,23 @@
 	if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
 	    tulip_txput_setup(sc);
 
-	while (sc->tulip_if.if_snd.ifq_head != NULL) {
-	    struct mbuf *m;
-	    IF_DEQUEUE(&sc->tulip_if.if_snd, m);
-	    if ((m = tulip_txput(sc, m)) != NULL) {
-		IF_PREPEND(&sc->tulip_if.if_snd, m);
+	while (!IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
+	    struct mbuf *m, *m0;
+	    IFQ_POLL(&sc->tulip_if.if_snd, m);
+	    if (m == NULL)
+		break;
+	    if ((m0 = tulip_txput(sc, m)) != NULL) {
+		if (m0 != m)
+		    /* should not happen */
+		    printf("tulip_if_start: txput failed!\n");
 		break;
 	    }
 	}
-	if (sc->tulip_if.if_snd.ifq_head == NULL)
+#ifdef ALTQ
+	if (0) /* don't switch to the one packet mode */
+#else
+	if (IFQ_IS_EMPTY(&sc->tulip_if.if_snd))
+#endif
 	    sc->tulip_if.if_start = tulip_ifstart_one;
     }
 
@@ -4941,11 +4992,13 @@
     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
 
     if ((sc->tulip_if.if_flags & IFF_RUNNING)
-	    && sc->tulip_if.if_snd.ifq_head != NULL) {
-	struct mbuf *m;
-	IF_DEQUEUE(&sc->tulip_if.if_snd, m);
-	if ((m = tulip_txput(sc, m)) != NULL)
-	    IF_PREPEND(&sc->tulip_if.if_snd, m);
+	    && !IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
+	struct mbuf *m, *m0;
+	IFQ_POLL(&sc->tulip_if.if_snd, m);
+	if (m != NULL && (m0 = tulip_txput(sc, m)) != NULL)
+	    if (m0 != m)
+		/* should not happen */
+		printf("tulip_if_start_one: txput failed!\n");
     }
     TULIP_PERFEND(ifstart_one);
 }
@@ -5139,6 +5192,7 @@
 
     tulip_reset(sc);
 
+    IFQ_SET_READY(&ifp->if_snd);
 #if defined(__bsdi__) && _BSDI_VERSION >= 199510
     sc->tulip_pf = printf;
     TULIP_ETHER_IFATTACH(sc);
diff -urN ../sys/dev/pci/if_ti.c ./dev/pci/if_ti.c
--- ../sys/dev/pci/if_ti.c	Wed Mar 14 05:44:13 2001
+++ ./dev/pci/if_ti.c	Thu Oct  4 15:12:04 2001
@@ -1815,7 +1815,8 @@
 	ifp->if_ioctl = ti_ioctl;
 	ifp->if_start = ti_start;
 	ifp->if_watchdog = ti_watchdog;
-	ifp->if_snd.ifq_maxlen = TI_TX_RING_CNT - 1;
+	IFQ_SET_MAXLEN(&ifp->if_snd, TI_TX_RING_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * We can support 802.1Q VLAN-sized frames.
@@ -2105,7 +2106,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
 
-	if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
+	if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
 		ti_start(ifp);
 
 	return (1);
@@ -2239,13 +2240,14 @@
 	struct ti_softc		*sc;
 	struct mbuf		*m_head = NULL;
 	u_int32_t		prodidx = 0;
+	int			pkts = 0;
 
 	sc = ifp->if_softc;
 
 	prodidx = CSR_READ_4(sc, TI_MB_SENDPROD_IDX);
 
 	while(sc->ti_cdata.ti_tx_chain[prodidx] == NULL) {
-		IF_DEQUEUE(&ifp->if_snd, m_head);
+		IFQ_POLL(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
@@ -2255,11 +2257,14 @@
 		 * for the NIC to drain the ring.
 		 */
 		if (ti_encap(sc, m_head, &prodidx)) {
-			IF_PREPEND(&ifp->if_snd, m_head);
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
 
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
+		pkts++;
+
 		/*
 		 * If there's a BPF listener, bounce a copy of this frame
 		 * to him.
@@ -2269,6 +2274,8 @@
 			bpf_mtap(ifp->if_bpf, m_head);
 #endif
 	}
+	if (pkts == 0)
+		return;
 
 	/* Transmit */
 	CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, prodidx);
diff -urN ../sys/dev/pci/if_tl.c ./dev/pci/if_tl.c
--- ../sys/dev/pci/if_tl.c	Thu Mar 23 16:01:39 2000
+++ ./dev/pci/if_tl.c	Thu Oct  4 15:12:04 2001
@@ -446,6 +446,7 @@
 	ifp->if_start = tl_ifstart;
 	ifp->if_watchdog = tl_ifwatchdog;
 	ifp->if_timer = 0;
+	IFQ_SET_READY(&ifp->if_snd);
 	if_attach(ifp);
 	ether_ifattach(&(sc)->tl_if, (sc)->tl_enaddr);
 #if NBPFILTER > 0
@@ -1051,7 +1052,7 @@
 				TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_GO);
 			}
 			sc->tl_if.if_timer = 0;
-			if (sc->tl_if.if_snd.ifq_head != NULL)
+			if (!IFQ_IS_EMPTY(&sc->tl_if.if_snd))
 				tl_ifstart(&sc->tl_if);
 			return 1;
 		}
@@ -1061,7 +1062,7 @@
 		}
 #endif
 		sc->tl_if.if_timer = 0;
-		if (sc->tl_if.if_snd.ifq_head != NULL)
+		if (!IFQ_IS_EMPTY(&sc->tl_if.if_snd))
 			tl_ifstart(&sc->tl_if);
 		break;
 	case TL_INTR_Stat:
@@ -1258,7 +1259,7 @@
 		return;
 	}
 	/* Grab a paquet for output */
-	IF_DEQUEUE(&ifp->if_snd, mb_head);
+	IFQ_DEQUEUE(&ifp->if_snd, mb_head);
 	if (mb_head == NULL) {
 #ifdef TLDEBUG_TX
 		printf("tl_ifstart: nothing to send\n");
@@ -1473,6 +1474,7 @@
 	void *v;
 {
 	tl_softc_t *sc = v;
+	int error;
 
 	tl_read_stats(sc);
 
@@ -1519,7 +1521,15 @@
 				m->m_len = m->m_pkthdr.len =
 				    sizeof(struct ether_header) + 3;
 				s = splnet();
+#if 1
+#ifdef ALTQ
+				IFQ_ENQUEUE(&sc->tl_if.if_snd, m, NULL, error);
+#else
+				IFQ_ENQUEUE(&sc->tl_if.if_snd, m, error);
+#endif
+#else
 				IF_PREPEND(&sc->tl_if.if_snd, m);
+#endif
 				tl_ifstart(&sc->tl_if);
 				splx(s);
 			}
diff -urN ../sys/dev/pci/if_vr.c ./dev/pci/if_vr.c
--- ../sys/dev/pci/if_vr.c	Wed Mar 14 05:44:29 2001
+++ ./dev/pci/if_vr.c	Thu Oct  4 15:12:04 2001
@@ -966,7 +966,7 @@
 		/*
 		 * Grab a packet off the queue.
 		 */
-		IF_DEQUEUE(&ifp->if_snd, m0);
+		IFQ_POLL(&ifp->if_snd, m0);
 		if (m0 == NULL)
 			break;
 
@@ -989,7 +989,6 @@
 			if (m == NULL) {
 				printf("%s: unable to allocate Tx mbuf\n",
 				    sc->vr_dev.dv_xname);
-				IF_PREPEND(&ifp->if_snd, m0);
 				break;
 			}
 			if (m0->m_pkthdr.len > MHLEN) {
@@ -998,24 +997,26 @@
 					printf("%s: unable to allocate Tx "
 					    "cluster\n", sc->vr_dev.dv_xname);
 					m_freem(m);
-					IF_PREPEND(&ifp->if_snd, m0);
 					break;
 				}
 			}
 			m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
 			m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
-			m_freem(m0);
 			m0 = m;
 			error = bus_dmamap_load_mbuf(sc->vr_dmat,
 			    ds->ds_dmamap, m0, BUS_DMA_NOWAIT);
 			if (error) {
 				printf("%s: unable to load Tx buffer, "
 				    "error = %d\n", sc->vr_dev.dv_xname, error);
-				IF_PREPEND(&ifp->if_snd, m0);
+				/* ick!  discard the new mbuf */
+				m_freem(m);
 				break;
 			}
 		}
 
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m);
+
 		/* Sync the DMA map. */
 		bus_dmamap_sync(sc->vr_dmat, ds->ds_dmamap, 0,
 		    ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
@@ -1710,6 +1711,7 @@
 	ifp->if_start = vr_start;
 	ifp->if_watchdog = vr_watchdog;
 	bcopy(sc->vr_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Initialize MII/media info.
diff -urN ../sys/dev/pcmcia/if_wi.c ./dev/pcmcia/if_wi.c
--- ../sys/dev/pcmcia/if_wi.c	Sun May 27 01:10:03 2001
+++ ./dev/pcmcia/if_wi.c	Thu Oct  4 15:12:04 2001
@@ -375,6 +375,7 @@
 	ifp->if_ioctl = wi_ioctl;
 	ifp->if_watchdog = wi_watchdog;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	(void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
 	    sizeof(WI_DEFAULT_NODENAME) - 1);
@@ -718,7 +719,7 @@
 	/* Re-enable interrupts. */
 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
 
-	if (ifp->if_snd.ifq_head != NULL)
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
 		wi_start(ifp);
 
 	return 1;
@@ -1598,7 +1599,7 @@
 	if (ifp->if_flags & IFF_OACTIVE)
 		return;
 
-	IF_DEQUEUE(&ifp->if_snd, m0);
+	IFQ_DEQUEUE(&ifp->if_snd, m0);
 	if (m0 == NULL)
 		return;
 
diff -urN ../sys/net/if.c ./net/if.c
--- ../sys/net/if.c	Mon Jan  1 02:57:40 2001
+++ ./net/if.c	Thu Oct  4 15:12:04 2001
@@ -337,6 +337,14 @@
 
 	ifp->if_link_state = LINK_STATE_UNKNOWN;
 
+#ifdef ALTQ
+	ifp->if_snd.altq_type = 0;
+	ifp->if_snd.altq_disc = NULL;
+	ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
+	ifp->if_snd.altq_tbr  = NULL;
+	ifp->if_snd.altq_ifp  = ifp;
+#endif
+
 	/* Announce the interface. */
 	rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
 }
@@ -400,6 +408,12 @@
 	 * Do an if_down() to give protocols a chance to do something.
 	 */
 	if_down(ifp);
+#ifdef ALTQ
+	if (ALTQ_IS_ENABLED(&ifp->if_snd))
+		altq_disable(&ifp->if_snd);
+	if (ALTQ_IS_ATTACHED(&ifp->if_snd))
+		altq_detach(&ifp->if_snd);
+#endif
 
 	/*
 	 * Rip all the addresses off the interface.  This should make
@@ -897,7 +911,7 @@
 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
 	     ifa = TAILQ_NEXT(ifa, ifa_list))
 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
-	if_qflush(&ifp->if_snd);
+	IFQ_PURGE(&ifp->if_snd);
 	rt_ifmsg(ifp);
 }
 
diff -urN ../sys/net/if.h ./net/if.h
--- ../sys/net/if.h	Mon Jan  1 02:57:43 2001
+++ ./net/if.h	Thu Oct  4 15:12:04 2001
@@ -77,6 +77,9 @@
 #if !defined(_XOPEN_SOURCE)
 
 #include <sys/queue.h>
+#if 1 /* ALTQ */
+#include <altq/if_altq.h>
+#endif
 
 /*
  * Structures defining a network interface, providing a packet
@@ -210,6 +213,17 @@
 
 /*
  * Structure defining a queue for a network interface.
+ */
+struct	ifqueue {
+	struct	mbuf *ifq_head;
+	struct	mbuf *ifq_tail;
+	int	ifq_len;
+	int	ifq_maxlen;
+	int	ifq_drops;
+};
+
+/*
+ * Structure defining a network interface.
  *
  * (Would like to call this struct ``if'', but C isn't PL/1.)
  */
@@ -246,13 +260,11 @@
 		__P((struct ifnet *));
 	void	(*if_drain)		/* routine to release resources */
 		__P((struct ifnet *));
-	struct	ifqueue {
-		struct	mbuf *ifq_head;
-		struct	mbuf *ifq_tail;
-		int	ifq_len;
-		int	ifq_maxlen;
-		int	ifq_drops;
-	} if_snd;			/* output queue */
+#if 1 /* ALTQ */
+	struct	ifaltq if_snd;		/* output queue (includes altq) */
+#else
+	struct	ifqueue if_snd;		/* output queue */
+#endif
 	struct	sockaddr_dl *if_sadl;	/* pointer to our sockaddr_dl */
 	u_int8_t *if_broadcastaddr;	/* linklevel broadcast bytestring */
 	struct ifprefix *if_prefixlist; /* linked list of prefixes per if */
@@ -340,6 +352,17 @@
 		(ifq)->ifq_len--; \
 	} \
 }
+#define	IF_POLL(ifq, m)		((m) = (ifq)->ifq_head)
+#define	IF_PURGE(ifq)							\
+while (1) {								\
+	struct mbuf *m0;						\
+	IF_DEQUEUE((ifq), m0);						\
+	if (m0 == NULL)							\
+		break;							\
+	else								\
+		m_freem(m0);						\
+}
+#define	IF_IS_EMPTY(ifq)	((ifq)->ifq_len == 0)
 
 #define	IFQ_MAXLEN	50
 #define	IFNET_SLOWHZ	1		/* granularity is 1 second */
@@ -571,6 +594,107 @@
 } while (0)
 #endif /* DIAGNOSTIC */
 #endif /* IFAREF_DEBUG */
+
+#ifdef ALTQ
+
+#define	IFQ_ENQUEUE(ifq, m, pattr, err)					\
+do {									\
+	if (ALTQ_IS_ENABLED((ifq)))					\
+		ALTQ_ENQUEUE((ifq), (m), (pattr), (err));		\
+	else {								\
+		if (IF_QFULL((ifq))) {					\
+			m_freem((m));					\
+			(err) = ENOBUFS;				\
+		} else {						\
+			IF_ENQUEUE((ifq), (m));				\
+			(err) = 0;					\
+		}							\
+	}								\
+	if ((err))							\
+		(ifq)->ifq_drops++;					\
+} while (0)
+
+#define	IFQ_DEQUEUE(ifq, m)						\
+do {									\
+	if (TBR_IS_ENABLED((ifq)))					\
+		(m) = tbr_dequeue((ifq), ALTDQ_REMOVE);			\
+	else if (ALTQ_IS_ENABLED((ifq)))				\
+		ALTQ_DEQUEUE((ifq), (m));				\
+	else								\
+		IF_DEQUEUE((ifq), (m));					\
+} while (0)
+
+#define	IFQ_POLL(ifq, m)						\
+do {									\
+	if (TBR_IS_ENABLED((ifq)))					\
+		(m) = tbr_dequeue((ifq), ALTDQ_POLL);			\
+	else if (ALTQ_IS_ENABLED((ifq)))				\
+		ALTQ_POLL((ifq), (m));					\
+	else								\
+		IF_POLL((ifq), (m));					\
+} while (0)
+
+#define	IFQ_PURGE(ifq)							\
+do {									\
+	if (ALTQ_IS_ENABLED((ifq)))					\
+		ALTQ_PURGE((ifq));					\
+	else								\
+		IF_PURGE((ifq));					\
+} while (0)
+
+#define	IFQ_SET_READY(ifq)						\
+	do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
+
+#define	IFQ_CLASSIFY(ifq, m, af, pa)					\
+do {									\
+	if (ALTQ_IS_ENABLED((ifq))) {					\
+		if (ALTQ_NEEDS_CLASSIFY((ifq)))				\
+			(pa)->pattr_class = (*(ifq)->altq_classify)	\
+				((ifq)->altq_clfier, (m), (af));	\
+		(pa)->pattr_af = (af);					\
+		(pa)->pattr_hdr = mtod((m), caddr_t);			\
+	}								\
+} while (0)
+
+#else /* !ALTQ */
+
+#define	IFQ_ENQUEUE(ifq, m, err)					\
+do {									\
+	if (IF_QFULL((ifq))) {						\
+		m_freem((m));						\
+		(err) = ENOBUFS;					\
+	} else {							\
+		IF_ENQUEUE((ifq), (m));					\
+		(err) = 0;						\
+	}								\
+	if ((err))							\
+		(ifq)->ifq_drops++;					\
+} while (0)
+
+#define	IFQ_DEQUEUE(ifq, m)	IF_DEQUEUE((ifq), (m))
+
+#define	IFQ_POLL(ifq, m)	IF_POLL((ifq), (m))
+
+#define	IFQ_PURGE(ifq)							\
+while (1) {								\
+	struct mbuf *m0;						\
+	IF_DEQUEUE((ifq), m0);						\
+	if (m0 == NULL)							\
+		break;							\
+	else								\
+		m_freem(m0);						\
+}
+
+#define	IFQ_SET_READY(ifq)		((void)0)
+#define	IFQ_CLASSIFY(ifq, m, af, pa)	((void)0)
+
+#endif /* !ALTQ */
+
+#define	IFQ_IS_EMPTY(ifq)		((ifq)->ifq_len == 0)
+#define	IFQ_INC_LEN(ifq)		((ifq)->ifq_len++)
+#define	IFQ_DEC_LEN(ifq)		(--(ifq)->ifq_len)
+#define	IFQ_INC_DROPS(ifq)		((ifq)->ifq_drops++)
+#define	IFQ_SET_MAXLEN(ifq, len)	((ifq)->ifq_maxlen = (len))
 
 struct ifnet_head ifnet;
 extern struct ifnet **ifindex2ifnet;
diff -urN ../sys/net/if_atm.h ./net/if_atm.h
--- ../sys/net/if_atm.h	Sat Nov 20 05:41:19 1999
+++ ./net/if_atm.h	Thu Oct  4 15:12:04 2001
@@ -111,7 +111,17 @@
     int pvc_pcr;			/* peak cell rate (shaper value) */
 };
 
+/* structure to control PVC bridging */
+struct pvcfwdreq {
+    /* first entry must be compatible with struct ifreq */
+    char pvc_ifname[IFNAMSIZ];		/* if name, e.g. "en0" */
+    char pvc_ifname2[IFNAMSIZ];		/* if name to be bridged to/from */
+    int	 pvc_op;			/* 1:add 0:delete */
+};
+
 /* use ifioctl for now */
+#define SIOCSPVCFWD	_IOW('i', 93, struct pvcfwdreq)
+#define SIOCGPVCFWD	_IOWR('i', 94, struct pvcfwdreq)
 #define SIOCSPVCTX	_IOWR('i', 95, struct pvctxreq)
 #define SIOCGPVCTX	_IOWR('i', 96, struct pvctxreq)
 #define SIOCSPVCSIF	_IOWR('i', 97, struct ifreq)
@@ -161,9 +171,11 @@
 	struct ifnet sif_if;		/* ifnet structure per pvc */
 	struct atm_pseudohdr sif_aph;	/* flags + vpi:vci */
 	int	sif_vci;		/* vci no */
+	struct ifnet *sif_fwdifp;	/* bridging ifp */
 	LIST_ENTRY(pvcsif) sif_links;
 };
 struct ifnet *pvcsif_alloc __P((void));
+int pvc_set_fwd __P((char *, char *, int));
 #endif
 #endif /* ATM_PVCEXT */
 #endif /* _NET_IF_ATM_H_ */
diff -urN ../sys/net/if_atmsubr.c ./net/if_atmsubr.c
--- ../sys/net/if_atmsubr.c	Thu Mar 30 18:45:35 2000
+++ ./net/if_atmsubr.c	Thu Oct  4 15:12:04 2001
@@ -35,7 +35,6 @@
 /*
  * if_atmsubr.c
  */
-
 #include "opt_inet.h"
 #include "opt_gateway.h"
 #include "opt_natm.h"
@@ -96,18 +95,29 @@
 	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;
 	struct mbuf *m = m0;
 	struct rtentry *rt;
 	struct atmllc *atmllc;
 	struct atmllc *llc_hdr = NULL;
 	u_int32_t atm_flags;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 		senderr(ENETDOWN);
 	ifp->if_lastchange = time;
 
+#ifdef ALTQ
+	/*
+	 * 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);
+#endif
 	/*
 	 * check route
 	 */
@@ -175,6 +185,8 @@
 			 * assuming dst contains 12 bytes (atm pseudo
 			 * header (4) + LLC/SNAP (8))
 			 */
+			if (dst->sa_len + 2 < sizeof(atmdst) + sizeof(*llc_hdr))
+				senderr(EINVAL);
 			bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
 			llc_hdr = (struct atmllc *)(dst->sa_data + sizeof(atmdst));
 			break;
@@ -182,10 +194,10 @@
 		default:
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 			printf("%s: can't handle af%d\n", ifp->if_xname, 
-			    dst->sa_family);
+			       dst->sa_family);
 #elif defined(__FreeBSD__) || defined(__bsdi__)
 			printf("%s%d: can't handle af%d\n", ifp->if_name, 
-			    ifp->if_unit, dst->sa_family);
+			       ifp->if_unit, dst->sa_family);
 #endif
 			senderr(EAFNOSUPPORT);
 		}
@@ -213,15 +225,18 @@
 	 * 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);
+#ifdef ALTQ
+	IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+#else
+	IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#endif
+	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);
@@ -293,6 +308,33 @@
 	    m_adj(m, sizeof(*alc));
 	  }
 
+#ifdef ATM_PVCEXT
+	/* atm bridging support */
+	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LINK2)) ==
+		(IFF_POINTOPOINT|IFF_LINK2)) {
+		struct pvcsif *pvcsif = (struct pvcsif *)ifp;
+
+		if (pvcsif->sif_fwdifp != NULL) {
+			struct sockaddr dst;
+
+			/* set address family to dummy dst addr */
+			switch (etype) {
+			case ETHERTYPE_IP:
+				dst.sa_family = AF_INET;
+				break;
+			case ETHERTYPE_IPV6:
+				dst.sa_family = AF_INET6;
+				break;
+			default:
+				m_freem(m);
+				return;
+			}
+			atm_output(pvcsif->sif_fwdifp, m, &dst, NULL);
+			return;
+		}
+	}
+#endif /* ATM_PVCEXT */
+
 	  switch (etype) {
 #ifdef INET
 	  case ETHERTYPE_IP:
@@ -396,5 +438,60 @@
 	pvcsif->sif_if.if_unit = pvc_number++;
 #endif
 	return (&pvcsif->sif_if);
+}
+
+/*
+ * pvc bridging support:
+ * add or delete brigding between 2 pvc interfaces.
+ */
+int
+pvc_set_fwd(if_name, if_name2, op)
+	char *if_name, *if_name2;
+	int op;		/* 0:delete 1:add 2:get */
+{
+	struct ifnet *ifp, *ifp2;
+	struct pvcsif *pvcsif, *pvcsif2;
+
+	if (strncmp(if_name, "pvc", 3) != 0
+	    || (ifp = ifunit(if_name)) == NULL)
+		return (EINVAL);
+	pvcsif = (struct pvcsif *)ifp;
+
+	if (op == 2) {
+		/* get bridging info */
+		if ((ifp2 = pvcsif->sif_fwdifp) == NULL)
+			*if_name2 = '\0';
+		else
+#ifdef __NetBSD__
+			sprintf(if_name2, "%s", ifp2->if_xname);
+#else
+			sprintf(if_name2, "%s%d",
+				ifp2->if_name, ifp2->if_unit);
+#endif
+		return (0);
+	}
+
+	if (strncmp(if_name2, "pvc", 3) != 0
+	    || (ifp2 = ifunit(if_name2)) == NULL)
+		return (EINVAL);
+	pvcsif2 = (struct pvcsif *)ifp2;
+
+	if (op) {
+		/* set up bridging */
+		pvcsif->sif_fwdifp = ifp2;
+		pvcsif2->sif_fwdifp = ifp;
+		ifp->if_flags |= IFF_LINK2;	/* use IFF_LINK2 to show */
+		ifp2->if_flags |= IFF_LINK2;	/* bridging is enabled   */
+	}
+	else {
+		/* delete bridging */
+		if (pvcsif->sif_fwdifp != ifp2 || pvcsif2->sif_fwdifp != ifp)
+			return (EINVAL);
+		pvcsif->sif_fwdifp = NULL;
+		pvcsif2->sif_fwdifp = NULL;
+		ifp->if_flags &= ~IFF_LINK2;
+		ifp2->if_flags &= ~IFF_LINK2;
+	}
+	return (0);
 }
 #endif /* ATM_PVCEXT */
diff -urN ../sys/net/if_ethersubr.c ./net/if_ethersubr.c
--- ../sys/net/if_ethersubr.c	Fri Jun  8 02:00:32 2001
+++ ./net/if_ethersubr.c	Thu Oct  4 15:12:04 2001
@@ -169,18 +169,22 @@
 	struct rtentry *rt0)
 {
 	u_int16_t etype = 0;
-	int s, error = 0, hdrcmplt = 0;
+	int s, len, error = 0, hdrcmplt = 0;
  	u_char esrc[6], edst[6];
 	struct mbuf *m = m0;
 	struct rtentry *rt;
 	struct mbuf *mcopy = (struct mbuf *)0;
 	struct ether_header *eh;
+	short mflags;
 #ifdef INET
 	struct arphdr *ah;
 #endif /* INET */
 #ifdef NETATALK
 	struct at_ifaddr *aa;
 #endif /* NETATALK */
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 		senderr(ENETDOWN);
@@ -217,6 +221,13 @@
 			    time.tv_sec < rt->rt_rmx.rmx_expire)
 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
 	}
+#ifdef ALTQ
+	/*
+	 * if the queueing discipline needs packet classification,
+	 * do it before prepending link headers.
+	 */
+	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+#endif
 	switch (dst->sa_family) {
 
 #ifdef INET
@@ -269,8 +280,7 @@
 			return(0);	/* if not yet resolves */
 #else
 		if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){
-			/* this must be impossible, so we bark */
-			printf("nd6_storelladdr failed\n");
+			/* something bad happened */
 			return(0);
 		}
 #endif /* OLDIP6OUTPUT */
@@ -464,20 +474,26 @@
 	else
 	 	bcopy(LLADDR(ifp->if_sadl), (caddr_t)eh->ether_shost,
 		    sizeof(eh->ether_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);
+#ifdef ALTQ
+	IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+#else
+	IFQ_ENQUEUE(&ifp->if_snd, m, error);
+#endif
+	if (error) {
+		/* mbuf is already freed */
 		splx(s);
-		senderr(ENOBUFS);
+		return (error);
 	}
-	ifp->if_obytes += m->m_pkthdr.len;
-	if (m->m_flags & M_MCAST)
+	ifp->if_obytes += len;
+	if (mflags & M_MCAST)
 		ifp->if_omcasts++;
-	IF_ENQUEUE(&ifp->if_snd, m);
 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
 		(*ifp->if_start)(ifp);
 	splx(s);
diff -urN ../sys/net/if_loop.c ./net/if_loop.c
--- ../sys/net/if_loop.c	Thu Mar 30 18:45:36 2000
+++ ./net/if_loop.c	Thu Oct  4 15:12:04 2001
@@ -139,6 +139,10 @@
 
 struct	ifnet loif[NLOOP];
 
+#ifdef ALTQ
+static void lo_altqstart __P((struct ifnet *));
+#endif
+
 void
 loopattach(n)
 	int n;
@@ -157,6 +161,10 @@
 		ifp->if_type = IFT_LOOP;
 		ifp->if_hdrlen = 0;
 		ifp->if_addrlen = 0;
+		IFQ_SET_READY(&ifp->if_snd);
+#ifdef ALTQ
+		ifp->if_start = lo_altqstart;
+#endif
 		if_attach(ifp);
 #if NBPFILTER > 0
 		bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
@@ -258,6 +266,37 @@
 
 	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
@@ -317,6 +356,87 @@
 	splx(s);
 	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
diff -urN ../sys/net/if_ppp.c ./net/if_ppp.c
--- ../sys/net/if_ppp.c	Fri Aug 17 01:52:39 2001
+++ ./net/if_ppp.c	Thu Oct  4 15:12:04 2001
@@ -78,7 +78,9 @@
 #include "ppp.h"
 #if NPPP > 0
 
+#ifdef INET
 #define VJC
+#endif
 #define PPP_COMPRESS
 
 #include "opt_inet.h"
@@ -103,10 +105,10 @@
 #include <net/bpf.h>
 #endif
 
-#ifdef INET
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
+#ifdef INET
 #include <netinet/ip.h>
 #else
 #ifdef _KERNEL
@@ -210,10 +212,11 @@
 	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_NULL, 0);
@@ -719,11 +722,16 @@
     int protocol, address, control;
     u_char *cp;
     int s, error;
+#ifdef INET
     struct ip *ip;
+#endif
     struct ifqueue *ifq;
     enum NPmode mode;
     int len;
     struct mbuf *m;
+#ifdef ALTQ
+    struct altq_pktattr pktattr;
+#endif
 
     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
 	|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
@@ -731,6 +739,9 @@
 	goto bad;
     }
 
+#ifdef ALTQ
+    IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
+#endif
     /*
      * Compute PPP header.
      */
@@ -870,16 +881,34 @@
 	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)
+#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 {
+#ifdef ALTQ
+	    IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error);
+#else
+	    IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, error);
+#endif
+	}
+	if (error) {
 	    splx(s);
 	    sc->sc_if.if_oerrors++;
 	    sc->sc_stats.ppp_oerrors++;
-	    error = ENOBUFS;
-	    goto bad;
+	    return (error);
 	}
-	IF_ENQUEUE(ifq, m0);
 	ppp_restart(sc);
     }
     ifp->if_lastchange = time;
@@ -906,6 +935,7 @@
     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 *))) {
@@ -926,13 +956,32 @@
 	     */
 	    *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)
+#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 {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error);
+#else
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, error);
+#endif
+	    }
+	    if (error) {
 		sc->sc_if.if_oerrors++;
 		sc->sc_stats.ppp_oerrors++;
-	    } else
-		IF_ENQUEUE(ifq, m);
+	    }
 	    break;
 
 	case NPMODE_DROP:
@@ -986,7 +1035,7 @@
     s = splimp();    
     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);
     splx(s);
     
     if (m == NULL)
@@ -1113,7 +1162,7 @@
     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) || sc->sc_fastq.ifq_head
 		|| sc->sc_outm)) {
 	    s2 = splimp();
 	    sc->sc_flags |= SC_TBUSY;
@@ -1284,11 +1333,14 @@
 {
     struct ifnet *ifp = &sc->sc_if;
     struct ifqueue *inq;
-    int s, ilen, xlen, proto, rv;
+    int s, ilen, proto, rv;
     u_char *cp, adrs, ctrl;
     struct mbuf *mp, *dmp = NULL;
+#ifdef VJC
+    int xlen;
     u_char *iphdr;
     u_int hlen;
+#endif
 
     sc->sc_stats.ppp_ipackets++;
 
diff -urN ../sys/net/if_sl.c ./net/if_sl.c
--- ../sys/net/if_sl.c	Thu Mar 30 18:45:36 2000
+++ ./net/if_sl.c	Thu Oct  4 15:12:04 2001
@@ -211,8 +211,9 @@
 		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);
@@ -382,8 +383,14 @@
 	struct sl_softc *sc = ifp->if_softc;
 	struct ip *ip;
 	struct ifqueue *ifq;
-	int s;
+	int s, error;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
+#ifdef ALTQ
+	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+#endif
 	/*
 	 * `Cannot happen' (see slioctl).  Someday we will extend
 	 * the line protocol to support other address families.
@@ -406,14 +413,11 @@
 		printf("%s: no carrier and not local\n", sc->sc_if.if_xname);
 		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;
@@ -425,14 +429,33 @@
 			slstart(sc->sc_ttyp);
 		}
 	}
-	if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
-		m_freem(m);
+	if ((ip->ip_tos & IPTOS_LOWDELAY)
+#ifdef ALTQ
+	    && !ALTQ_IS_ENABLED(&sc->sc_if.if_snd)
+#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 {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, &pktattr, error);
+#else
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, error);
+#endif
+	}
+	if (error) {
 		splx(s);
 		sc->sc_if.if_oerrors++;
-		return (ENOBUFS);
+		return (error);
 	}
-	IF_ENQUEUE(ifq, m);
+	
 	sc->sc_if.if_lastchange = time;
 	if ((sc->sc_oqlen = sc->sc_ttyp->t_outq.c_cc) == 0)
 		slstart(sc->sc_ttyp);
@@ -514,7 +537,7 @@
 		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) {
 #if NBPFILTER > 0
diff -urN ../sys/net/if_spppsubr.c ./net/if_spppsubr.c
--- ../sys/net/if_spppsubr.c	Mon Jul 30 04:51:36 2001
+++ ./net/if_spppsubr.c	Thu Oct  4 15:12:04 2001
@@ -60,20 +60,18 @@
 
 #include <machine/stdarg.h>
 
-#ifdef INET
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
+#ifdef INET
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
+#endif
 #if defined (__FreeBSD__) || defined (__OpenBSD__)
 #include <netinet/if_ether.h>
 #else
 #include <net/ethertypes.h>
 #endif
-#else
-#error Huh? sppp without INET?
-#endif
 
 #ifdef IPX
 #include <netipx/ipx.h>
@@ -270,6 +268,7 @@
 #define	SPP_ARGS(ifp)	(ifp)->if_xname
 #endif
 
+#ifdef INET
 /*
  * The following disgusting hack gets around the problem that IP TOS
  * can't be set yet.  We want to put "interactive" traffic on a high
@@ -283,6 +282,7 @@
 	0,	21,	0,	23,
 };
 #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
+#endif
 
 /* almost every function needs these */
 #define STDDCL							\
@@ -685,8 +685,11 @@
 {
 	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;
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	s = splimp();
 
@@ -708,8 +711,13 @@
 		s = splimp();
 	}
 
-	ifq = &ifp->if_snd;
-
+#ifdef ALTQ
+	/*
+	 * if the queueing discipline needs packet classification,
+	 * do it before prepending link headers.
+	 */
+	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
+#endif
 #ifdef INET
 	if (dst->sa_family == AF_INET)
 	{
@@ -856,14 +864,33 @@
 	 * 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)
+#endif
+		) {
+		if (IF_QFULL (ifq)) {
+			IF_DROP (&ifp->if_snd);
+			m_freem (m);
+			if (rv == 0)
+				rv = ENOBUFS;
+		}
+		IF_ENQUEUE (ifq, m);
+	}
+	else {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, rv);
+#else
+		IFQ_ENQUEUE(&ifp->if_snd, m, rv);
+#endif
+	}
+	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);
 
@@ -872,7 +899,7 @@
 	 * 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);
 }
@@ -974,7 +1001,7 @@
 {
 	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);
 }
@@ -990,7 +1017,7 @@
 
 	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);
 }
@@ -1017,7 +1044,7 @@
 	    (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;
@@ -1040,7 +1067,7 @@
 	    (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 -urN ../sys/net/if_strip.c ./net/if_strip.c
--- ../sys/net/if_strip.c	Thu Mar 30 18:45:37 2000
+++ ./net/if_strip.c	Thu Oct  4 15:12:04 2001
@@ -359,10 +359,11 @@
 		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;
+		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);
@@ -727,9 +728,11 @@
 	struct ifqueue *ifq;
 	struct st_header *shp;
 	const u_char *dldst;		/* link-level next-hop */
-	int s;
+	int s, error;
 	u_char dl_addrbuf[STARMODE_ADDR_LEN+1];
-
+#ifdef ALTQ
+	struct altq_pktattr pktattr;
+#endif
 
 	/*
 	 * Verify tty line is up and alive.
@@ -792,13 +795,17 @@
 		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)
+#endif
+		)
 		ifq = &sc->sc_fastq;
 
 	/*
@@ -856,14 +863,27 @@
 			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 {
+#ifdef ALTQ
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, &pktattr, error);
+#else
+		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, error);
+#endif
+	}
+	if (error) {
 		splx(s);
 		sc->sc_if.if_oerrors++;
-		return (ENOBUFS);
+		return (error);
 	}
-	IF_ENQUEUE(ifq, m);
 	sc->sc_if.if_lastchange = time;
 	if ((sc->sc_oqlen = sc->sc_ttyp->t_outq.c_cc) == 0) {
 		stripstart(sc->sc_ttyp);
@@ -953,7 +973,7 @@
 		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 -urN ../sys/netinet/ip_input.c ./netinet/ip_input.c
--- ../sys/netinet/ip_input.c	Wed Apr 25 07:21:20 2001
+++ ./netinet/ip_input.c	Thu Oct  4 15:12:04 2001
@@ -416,6 +416,11 @@
 		goto bad;
 	}
 
+#ifdef ALTQ
+	if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0)
+		/* packet is dropped by traffic conditioner */
+		return;
+#endif
 	/*
 	 * Convert fields to host representation.
 	 */
diff -urN ../sys/netinet6/ip6_input.c ./netinet6/ip6_input.c
--- ../sys/netinet6/ip6_input.c	Fri Apr  6 10:37:35 2001
+++ ./netinet6/ip6_input.c	Thu Oct  4 15:47:27 2001
@@ -350,6 +350,12 @@
 	}
 #endif
 
+#ifdef ALTQ
+	if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
+		/* packet is dropped by traffic conditioner */
+		return;
+	}
+#endif
 	/*
 	 * Scope check
 	 */
