Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Mar 1999 14:26:18 +0100
From:      Andreas Klemm <andreas@klemm.gtn.com>
To:        julian@whistle.com
Cc:        freebsd-net@FreeBSD.ORG
Subject:   ALTQ 1.1.3, support for FreeBSD 3.1-STABLE, started the work
Message-ID:  <19990307142618.A4807@titan.klemm.gtn.com>

next in thread | raw e-mail | index | archive | help

--lrZ03NoBR/3+SXJZ
Content-Type: text/plain; charset=us-ascii

Hi Julian (and the others on the list),

I started to port your ALTQ 1.1.3 patches for FreeBSD 3.0
to FreeBSD-3.1.

Patching the sys dir went very smoothly after bumping patch's Fuzz
factor up to 100. A smaller value might be ok as well, but I didn't
want to waste time by playing around with different parameters.

With a Fuzz of 100 only 2 rejects occurred:

./net/if_ethersubr.c.rej --- applied manually... For this a Fuzz of
				~300 would have been needed
./pci/if_en_pci.c.rej    --- most or all of the changes went already
				into the driver, when browsing through it.
				So I simply ignored it.

Well, so far so good (I hope ;-). But the ALTQ kernel doesn't compile
well and I'm lacking of experience how to handle with the remaining
errors.

Managing the first problem was trivial. if_spppsubr.c has a define
of it's own for TIMEOUT and UNTIMEOUT, which is already defined by
an altq file. Solution is a wrapper like this:

--- if_spppsubr.c.orig  Sun Dec 27 22:30:44 1998
+++ if_spppsubr.c       Sun Mar  7 13:55:59 1999
@@ -100,9 +104,11 @@
 #include <net/if_sppp.h>

 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#if !defined (ALTQ)
 # define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle)
 # define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2)
 # define IOCTL_CMD_T   u_long
+#endif

...but the remaining compilation errors scare me a bit.
Could you or somebody else please have a look into this ?!

root{434} /sys/compile/TITANALTQ make
cc -c -O -pipe -Wreturn-type -Wcomment -Wredundant-decls -Wimplicit  -Wnested-ex
terns -Wstrict-prototypes -Wmissing-prototypes  -Wpointer-arith -Winline -Wunini
tialized -Wformat -Wunused  -fformat-extensions -ansi -g -nostdinc -I- -I. -I../
.. -I../../../include  -DKERNEL -DVM_STACK -include opt_global.h -elf  ../../net
/if_spppsubr.c
../../net/if_spppsubr.c:629: parameter `pr_hdr' has just a forward declaration
../../net/if_spppsubr.c:627: parameter `m' has just a forward declaration
../../net/if_spppsubr.c:627: parameter `ifp' has just a forward declaration
../../net/if_spppsubr.c:632: conflicting types for `sppp_output'
../../net/if_spppsubr.c:299: previous declaration of `sppp_output'
../../net/if_spppsubr.c: In function `sppp_output':
../../net/if_spppsubr.c:635: warning: `ifq' might be used uninitialized in this
function
../../net/if_spppsubr.c: In function `sppp_attach':
../../net/if_spppsubr.c:856: warning: assignment from incompatible pointer type
../../net/if_spppsubr.c: At top level:
../../net/if_spppsubr.c:999: parse error before `IOCTL_CMD_T'
../../net/if_spppsubr.c: In function `sppp_ioctl':
../../net/if_spppsubr.c:1000: number of arguments doesn't match prototype
../../net/if_sppp.h:168: prototype declaration
../../net/if_spppsubr.c:1001: `data' undeclared (first use this function)
../../net/if_spppsubr.c:1001: (Each undeclared identifier is reported only once
../../net/if_spppsubr.c:1001: for each function it appears in.)
../../net/if_spppsubr.c:1002: `ifp' undeclared (first use this function)
../../net/if_spppsubr.c:1007: `cmd' undeclared (first use this function)
*** Error code 1

Fine would be to get a working set of patches, to get FreeBSD 3.1
support for ALTQ 1.1.3.

In the attachement is my new set of diffs...

	Andreas ///

P.S.:	I just read about yout netgraph work, so I don't know if you
	have time for this (so Cc'd to freebsd-net).

BTW, just curious, did you or somebody else play with WFQ ?
The authors say in the docu, WFQ isn't well maintained and 
is missing hashing ... Do you thing using ALTQ brings advantages
like Cisco's implementation does ? All I want is, to get better
telnet / ssh performance over a 64 KBit ISDN line if UUCP/ftp
sessions saturate the link.

-- 
Andreas Klemm                                http://www.FreeBSD.ORG/~andreas
     What gives you 90% more speed, for example, in kernel compilation ?
          http://www.FreeBSD.ORG/~fsmp/SMP/akgraph-a/graph1.html
             "NT = Not Today" (Maggie Biggs)      ``powered by FreeBSD SMP''

--lrZ03NoBR/3+SXJZ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="FreeBSD-3.1-990306.diff"

--- ./conf/files.orig	Sun Jan 24 06:11:31 1999
+++ ./conf/files	Sun Mar  7 12:58:10 1999
@@ -387,6 +387,7 @@
 net/bpf_filter.c	optional bpfilter
 net/bridge.c		optional bridge
 net/bsd_comp.c		optional ppp_bsdcomp
+net/altq_conf.c		optional altq
 #net/hostcache.c		standard
 net/if.c		standard
 net/if_atmsubr.c	optional atm
@@ -498,6 +499,15 @@
 netatm/uni/unisig_subr.c	optional atm_uni atm_core
 netatm/uni/unisig_util.c	optional atm_uni atm_core
 netatm/uni/unisig_vc_state.c	optional atm_uni atm_core
+netinet/altq_afmap.c	optional altq
+netinet/altq_cbq.c	optional altq
+netinet/altq_fifoq.c	optional altq
+netinet/altq_localq.c	optional altq
+netinet/altq_red.c	optional altq
+netinet/altq_rio.c	optional altq
+netinet/altq_rmclass.c	optional altq
+netinet/altq_subr.c	optional altq
+netinet/altq_wfq.c	optional altq
 netinet/fil.c		optional ipfilter inet
 netinet/if_atm.c	optional atm
 netinet/if_ether.c	optional ether
--- ./conf/options.orig	Mon Feb  8 20:05:55 1999
+++ ./conf/options	Sun Mar  7 12:58:10 1999
@@ -182,6 +182,22 @@
 MAXDSIZ			opt_rlimit.h
 
 # Net stuff.
+# altq stuff
+ALTQ			opt_global.h
+ALTQ_ECN		opt_global.h
+CBQ			opt_altq.h
+WFQ			opt_altq.h
+AFMAP			opt_altq.h
+FIFOQ			opt_altq.h
+RED			opt_altq.h
+FLOWVALVE		opt_altq.h
+CBQ_RED			opt_altq.h
+RIO			opt_altq.h
+CBQ_RIO			opt_altq.h
+ALTQ_ACCOUNT		opt_altq.h
+ALTQ_IPSEC		opt_altq.h
+LOCALQ			opt_altq.h
+ 
 BOOTP			opt_bootp.h
 BOOTP_COMPAT		opt_bootp.h
 BOOTP_NFSROOT		opt_bootp.h
--- ./dev/en/midway.c.orig	Fri Dec  4 23:54:45 1998
+++ ./dev/en/midway.c	Sun Mar  7 12:58:10 1999
@@ -164,6 +164,10 @@
 #include <netnatm/natm.h>
 #endif
 
+#if defined(ALTQ) && defined(AFMAP)
+#include <netinet/altq_afmap.h>
+#endif
+
 #if !defined(sparc) && !defined(__FreeBSD__)
 #include <machine/bus.h>
 #endif
@@ -323,6 +327,12 @@
 static int en_txspeed2pcr __P((int));
 #endif
 
+#if defined(ALTQ) && defined(AFMAP)
+static int en_flowmap_add __P((struct en_softc *, struct atm_flowmap *));
+static int en_flowmap_delete __P((struct en_softc *, int, int));
+static int en_flowmap_get __P((struct en_softc *, struct atm_flowmap *));
+#endif
+
 /*
  * macros/inline
  */
@@ -757,6 +767,9 @@
   ifp->if_ioctl = en_ioctl;
   ifp->if_output = atm_output;
   ifp->if_start = en_start;
+#ifdef ALTQ
+  ifp->if_altqflags |= ALTQF_READY;
+#endif  /* ALTQ */
 
   /*
    * init softc
@@ -854,6 +867,9 @@
 #if NBPFILTER > 0 
   BPFATTACH(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
 #endif
+#if defined(ALTQ) && defined(AFMAP)
+  afm_alloc(ifp);
+#endif
 }
 
 
@@ -1288,6 +1304,43 @@
 
 #endif /* ATM_PVCEXT */
 
+#if defined(ALTQ) && defined(AFMAP)
+	case AFM_ADDFMAP:
+		do {
+			struct afm *afm = afm_top(ifp);
+			error = en_flowmap_add(sc, (struct atm_flowmap *)data);
+			if (afm == NULL && error == 0)
+				ifp->if_altqflags |= ALTQF_DRIVER1;
+		} while (0);
+		break;
+		
+	case AFM_DELFMAP:
+		do {
+			struct atm_flowmap *fmap = (struct atm_flowmap *)data;
+			error = en_flowmap_delete(sc, fmap->af_vpi, fmap->af_vci);
+		    
+			if (afm_top(ifp) == NULL)
+				ifp->if_altqflags &= ~ALTQF_DRIVER1;
+
+		} while (0);
+		break;
+		
+	case AFM_CLEANFMAP:
+		do {
+			struct afm *afm;
+			while ((afm = afm_top(ifp)) != NULL)
+				en_flowmap_delete(sc, afm->afm_vpi, afm->afm_vci);
+		
+			ifp->if_altqflags &= ~ALTQF_DRIVER1;
+		} while (0);
+		break;
+
+	case AFM_GETFMAP:
+		error = en_flowmap_get(sc, (struct atm_flowmap *)data);
+		break;
+
+#endif /* ALTQ && AFMAP */
+
 	default: 
 	    error = EINVAL;
 	    break;
@@ -1464,6 +1517,14 @@
       m_freem(m);
     }
 
+#ifdef ALTQ
+    do {
+	    struct ifnet *ifp = &sc->enif;
+
+	    if (ALTQ_IS_ON(ifp))
+		    (void)(*ifp->if_altqdequeue)(ifp, ALTDQ_FLUSH);
+    } while (0);
+#endif /* ALTQ */
     sc->txslot[lcv].mbsize = 0;
   }
 
@@ -1629,6 +1690,33 @@
 
     while (1) {
 
+#ifdef ALTQ
+      if (ALTQ_IS_ON(ifp)) {
+	  struct mbuf *tmp;
+	  /*
+	   * when altq is used, don't dequeue the packet until we
+	   * know we have enough buffer space.  this makes packet
+	   * dropping is done in altq_enqueue.
+	   * also make the internal buffer smaller (20KB instead of 64KB)
+	   * to keep packets remaining in altq.
+	   */
+	  m = (*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK);
+	  if (m != NULL) {
+	      ap = mtod(m, struct atm_pseudohdr *);
+	      atm_vci = ATM_PH_VCI(ap);
+	      txchan = sc->txvc2slot[atm_vci];
+	      if (sc->txslot[txchan].mbsize > 20*1024) {
+	          EN_COUNT(sc->txmbovr); /* this isn't a right stat counter */
+		  return;
+	      }
+
+	      tmp = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	      if (tmp != m)
+		  panic("en_start: different mbuf dequeued!");
+	  }
+      }
+      else
+#endif
       IF_DEQUEUE(ifq, m);
       if (m == NULL)
 	return;		/* EMPTY: >>> exit here <<< */
@@ -1765,6 +1853,35 @@
       txchan = sc->txvc2slot[atm_vci];
 
       if (sc->txslot[txchan].mbsize > EN_TXHIWAT) {
+#ifdef ALTQ_ACCOUNT
+	/*
+	 * special process for altq drop accounting.
+	 * re-extract flow and do drop-accounting here.
+	 */
+	struct pr_hdr pr_hdr;
+	int size;
+
+	pr_hdr.ph_family = AF_INET;  /* XXX */
+	if (ifp->if_altqflags & ALTQF_ACCOUNTING) {
+	    size = sizeof(struct atm_pseudohdr);
+	    if (atm_flags & ATM_PH_LLCSNAP)
+		size += 8; /* sizeof snap == 8 */
+	    if (atm_flags & EN_OBHDR)
+		size += MID_TBD_SIZE;
+	    if (m->m_len >= size + 20)
+		/* ip header in the first mbuf */
+		pr_hdr.ph_hdr = mtod(m, caddr_t) + size;
+	    else if (m->m_len == size && m->m_next->m_len >= 20)
+		/* ip header is in the second mbuf */
+		pr_hdr.ph_hdr = mtod(m->m_next, caddr_t);
+	    else
+		/* give up otherwise */
+	        pr_hdr.ph_hdr = NULL;
+	}
+	else
+	    pr_hdr.ph_hdr = NULL;
+	ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCDROP);
+#endif
 	EN_COUNT(sc->txmbovr);
 	m_freem(m);
 #ifdef EN_DEBUG
@@ -2847,6 +2964,12 @@
   sc->vtrash += MID_VTRASH(reg);
 #endif
 
+#ifdef ALTQ
+  /* when altq is used, better try to dequeue the next packet. */
+  if (ALTQ_IS_ON(&sc->enif) && kick)
+    en_start(&sc->enif);
+#endif
+
   EN_INTR_RET(1); /* for us */
 }
 
@@ -3708,5 +3831,98 @@
 }
 
 #endif /* ATM_PVCEXT */
+
+#if defined(ALTQ) && defined(AFMAP)
+
+static int en_flowmap_add(sc, fmap)
+	struct en_softc *sc;
+	struct atm_flowmap *fmap;
+{
+	struct afm *afm;
+	struct atm_pseudoioctl api;
+	int error = 0;
+
+	afm = afm_lookup(&sc->enif, fmap->af_vpi, fmap->af_vci);
+	if (afm)
+		/* already in use */
+		return (EEXIST);
+
+	if ((error = afm_add(&sc->enif, fmap)))
+		return error;
+
+	/* enable rx */
+	ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5 | ATM_PH_LLCSNAP;
+	ATM_PH_VPI(&api.aph) = fmap->af_vpi;
+	ATM_PH_SETVCI(&api.aph, fmap->af_vci);
+	api.rxhand = NULL;
+#ifdef ATM_PVCEXT
+	if (fmap->af_ifname[0] == 'p' && fmap->af_ifname[1] == 'v' &&
+	    fmap->af_ifname[2] == 'c') {
+		struct ifnet *shadow;
+
+		if ((shadow = ifunit(fmap->af_ifname)) == NULL)
+			return (EINVAL);
+		ATM_PH_FLAGS(&api.aph) |= ATM_PH_PVCSIF;
+		api.rxhand = shadow;
+	}
+#endif
+	error = en_rxctl(sc, &api, 1);
+	if (error)
+		return error;
+	error = en_txctl(sc, fmap->af_vci, 0, fmap->af_pcr);
+	return error;
+}
+
+static int en_flowmap_delete(sc, vpi, vci)
+	struct en_softc *sc;
+	int vpi, vci;
+{
+	struct afm *afm;
+	struct atm_pseudoioctl api;
+	int error = 0;
+
+	afm = afm_lookup(&sc->enif, vpi, vci);
+	if (afm == NULL)
+		return (ENOENT);
+    
+	afm_remove(afm);
+
+	/* disable rx */
+	ATM_PH_FLAGS(&api.aph) = 0;
+	ATM_PH_VPI(&api.aph) = vpi;
+	ATM_PH_SETVCI(&api.aph, vci);
+	api.rxhand = NULL;
+	error = en_rxctl(sc, &api, 0);
+
+	return error;
+}
+
+static int en_flowmap_get(sc, fmap)
+	struct en_softc *sc;
+	struct atm_flowmap *fmap;
+{
+	struct afm *afm;
+	int error = 0;
+
+	afm = afm_lookup(&sc->enif, fmap->af_vpi, fmap->af_vci);
+	if (afm == NULL)
+		return (ENOENT);
+
+	bcopy(&afm->afm_flowinfo, &fmap->af_flowinfo, sizeof(struct flowinfo));
+
+	/* get pcr value */
+	if (sc->txspeed[fmap->af_vci] != 0)
+		fmap->af_pcr = en_txspeed2pcr(sc->txspeed[fmap->af_vci]);
+	else
+		fmap->af_pcr = 0;
+
+	/* get stats */
+	fmap->afs_packets = afm->afms_packets;
+	fmap->afs_bytes = afm->afms_bytes;
+
+	return error;
+}
+
+#endif /* ALTQ && AFMAP */
 
 #endif /* NEN > 0 || !defined(__FreeBSD__) */
--- ./dev/vx/if_vx.c.orig	Tue Jan 12 03:09:31 1999
+++ ./dev/vx/if_vx.c	Sun Mar  7 12:58:10 1999
@@ -212,6 +212,9 @@
     ifp->if_init = vxinit;
     ifp->if_watchdog = vxwatchdog;
     ifp->if_softc = sc;
+#ifdef ALTQ
+    ifp->if_altqflags |= ALTQF_READY;
+#endif
 
     if_attach(ifp);
     ether_ifattach(ifp);
@@ -453,6 +456,11 @@
 
 startagain:
     /* Sneak a peek at the next packet */
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp))
+	m0 = (*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK);
+    else
+#endif
     m0 = ifp->if_snd.ifq_head;
     if (m0 == 0) {
 	return;
@@ -472,6 +480,14 @@
     if (len + pad > ETHER_MAX_LEN) {
 	/* packet is obviously too large: toss it */
 	++ifp->if_oerrors;
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	    struct mbuf *tmp = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	    if (tmp != m0)
+		panic("vxstart: different mbuf dequeued!");
+	}
+	else
+#endif
 	IF_DEQUEUE(&ifp->if_snd, m0);
 	m_freem(m0);
 	goto readcheck;
@@ -487,6 +503,14 @@
 	}
     }
     outw(BASE + VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2));
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp)) {
+	struct mbuf *tmp = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	if (tmp != m0)
+	    panic("vxstart: different mbuf dequeued!");
+    }
+    else
+#endif
     IF_DEQUEUE(&ifp->if_snd, m0);
     if (m0 == 0) {		/* not really needed */
 	return;
--- ./i386/conf/ALTQ.orig	Sun Mar  7 12:58:10 1999
+++ ./i386/conf/ALTQ	Sun Mar  7 12:58:10 1999
@@ -0,0 +1,219 @@
+#
+# GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks
+#
+# For more information read the handbook part System Administration -> 
+# Configuring the FreeBSD Kernel -> The Configuration File. 
+# The handbook is available in /usr/share/doc/handbook or online as
+# latest version from the FreeBSD World Wide Web server 
+# <URL:http://www.FreeBSD.ORG/>;
+#
+# An exhaustive list of options and more detailed explanations of the 
+# device lines is present in the ./LINT configuration file. If you are 
+# in doubt as to the purpose or necessity of a line, check first in LINT.
+#
+#	$Id: GENERIC,v 1.125 1998/10/16 01:30:11 obrien Exp $
+
+machine		"i386"
+cpu		"I386_CPU"
+cpu		"I486_CPU"
+cpu		"I586_CPU"
+cpu		"I686_CPU"
+ident		GENERIC
+maxusers	32
+
+options		MATH_EMULATE		#Support for x87 emulation
+options		INET			#InterNETworking
+options		FFS			#Berkeley Fast Filesystem
+options		FFS_ROOT		#FFS usable as root device [keep this!]
+options		MFS			#Memory Filesystem
+options		MFS_ROOT		#MFS usable as root device, "MFS" req'ed
+options		NFS			#Network Filesystem
+options		NFS_ROOT		#NFS usable as root device, "NFS" req'ed
+options		MSDOSFS			#MSDOS Filesystem
+options		"CD9660"		#ISO 9660 Filesystem
+options		"CD9660_ROOT"		#CD-ROM usable as root. "CD9660" req'ed
+options		PROCFS			#Process filesystem
+options		"COMPAT_43"		#Compatible with BSD 4.3 [KEEP THIS!]
+options		SCSI_DELAY=15000	#Be pessimistic about Joe SCSI device
+options		UCONSOLE		#Allow users to grab the console
+options		FAILSAFE		#Be conservative
+options		USERCONFIG		#boot -c editor
+options		VISUAL_USERCONFIG	#visual boot -c editor
+
+options		NMBCLUSTERS=2048
+options		MROUTING		# Multicast routing
+options		NATM			#native mode atm
+
+options		ALTQ		#alternate queueing
+options		CBQ		#class based queueing
+options		WFQ		#weighted fair queueing
+options		FIFOQ		#fifo queueing
+options		RED		#random early detection
+options		FLOWVALVE	#flowvalve for RED (needs RED)
+options		CBQ_RED		#red for cbq (needs CBQ and RED)
+options		RIO		#twin red for diffserv (needs RED)
+options		CBQ_RIO		#rio for cbq (needs CBQ, RIO, RED, CBQ_RED)
+options		LOCALQ		#local use
+options		ALTQ_ACCOUNT	#altq accounting
+options		ALTQ_ECN	#ecn extention to tcp
+
+config		kernel	root on wd0
+
+controller	isa0
+controller	eisa0
+controller	pci0
+
+controller	fdc0	at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
+disk		fd0	at fdc0 drive 0
+disk		fd1	at fdc0 drive 1
+# Unless you know very well what you're doing, leave ft0 at drive 2, or
+# remove the line entirely if you don't need it.  Trying to configure
+# it on another unit might cause surprises, see PR kern/7176.
+tape		ft0	at fdc0 drive 2
+
+options		"CMD640"	# work around CMD640 chip deficiency
+controller	wdc0	at isa? port "IO_WD1" bio irq 14 vector wdintr
+disk		wd0	at wdc0 drive 0
+disk		wd1	at wdc0 drive 1
+
+controller	wdc1	at isa? port "IO_WD2" bio irq 15 vector wdintr
+disk		wd2	at wdc1 drive 0
+disk		wd3	at wdc1 drive 1
+
+options		ATAPI		#Enable ATAPI support for IDE bus
+options		ATAPI_STATIC	#Don't do it as an LKM
+device		wcd0		#IDE CD-ROM
+device		wfd0		#IDE Floppy (e.g. LS-120)
+
+# A single entry for any of these controllers (ncr, ahb, ahc, amd) is
+# sufficient for any number of installed devices.
+controller	ncr0
+#controller	amd0
+controller	ahb0
+controller	ahc0
+controller	isp0
+
+# This controller offers a number of configuration options, too many to
+# document here  - see the LINT file in this directory and look up the
+# dpt0 entry there for much fuller documentation on this.
+controller      dpt0
+
+controller	adv0	at isa? port ? cam irq ?
+controller	adw0
+controller	bt0	at isa? port ? cam irq ?
+controller	aha0	at isa? port ? cam irq ?
+#controller	uha0	at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr
+#controller	aic0	at isa? port 0x340 bio irq 11 vector aicintr
+#controller	nca0	at isa? port 0x1f88 bio irq 10 vector ncaintr
+#controller	nca1	at isa? port 0x350 bio irq 5 vector ncaintr
+#controller	sea0	at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr
+
+controller	scbus0
+
+device		da0
+
+device		sa0
+
+device		pass0
+
+device		cd0	#Only need one of these, the code dynamically grows
+
+device		wt0	at isa? port 0x300 bio irq 5 drq 1 vector wtintr
+device		mcd0	at isa? port 0x300 bio irq 10 vector mcdintr
+
+controller	matcd0	at isa? port 0x230 bio
+
+device		scd0	at isa? port 0x230 bio
+
+# syscons is the default console driver, resembling an SCO console
+device		sc0	at isa? port "IO_KBD" conflicts tty irq 1 vector scintr
+# Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver
+#device		vt0	at isa? port "IO_KBD" conflicts tty irq 1 vector pcrint
+#options		XSERVER			# support for X server
+#options		FAT_CURSOR		# start with block cursor
+# If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines
+#options		PCVT_SCANSET=2		# IBM keyboards are non-std
+
+device		npx0	at isa? port "IO_NPX" irq 13 vector npxintr
+
+#
+# Laptop support (see LINT for more options)
+#
+device		apm0    at isa?	disable	flags 0x31 # Advanced Power Management
+
+# PCCARD (PCMCIA) support
+#controller	card0
+#device		pcic0	at card?
+#device		pcic1	at card?
+
+device		sio0	at isa? port "IO_COM1" flags 0x10 tty irq 4 vector siointr
+device		sio1	at isa? port "IO_COM2" tty irq 3 vector siointr
+device		sio2	at isa? disable port "IO_COM3" tty irq 5 vector siointr
+device		sio3	at isa? disable port "IO_COM4" tty irq 9 vector siointr
+
+device		lpt0	at isa? port? tty irq 7 vector lptintr
+
+device		psm0	at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr
+
+# Order is important here due to intrusive probes, do *not* alphabetize
+# this list of network interfaces until the probes have been fixed.
+# Right now it appears that the ie0 must be probed before ep0. See
+# revision 1.20 of this file.
+device de0
+device fxp0
+device tl0
+device tx0
+device vx0
+device xl0
+
+# ATM (en*) support
+device	en0
+device	en1
+
+device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr
+device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr
+device ep0 at isa? port 0x300 net irq 10 vector epintr
+device ex0 at isa? port? net irq? vector exintr
+device fe0 at isa? port 0x300 net irq ? vector feintr
+device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr
+device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr
+device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zeintr
+device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr
+device cs0 at isa? port 0x300 net irq ? vector csintr
+
+pseudo-device	loop
+pseudo-device	ether
+pseudo-device	atm
+pseudo-device	sl	1
+pseudo-device	ppp	1
+pseudo-device	tun	1
+pseudo-device	pty	16
+pseudo-device	gzip		# Exec gzipped a.out's
+
+#
+# Enable the kernel debugger.
+#
+options		DDB
+
+#
+# Don't drop into DDB for a panic. Intended for unattended operation
+# where you may want to drop to DDB from the console, but still want
+# the machine to recover from a panic
+#
+#options		DDB_UNATTENDED
+
+# KTRACE enables the system-call tracing facility ktrace(2).
+# This adds 4 KB bloat to your kernel, and slightly increases
+# the costs of each syscall.
+options		KTRACE		#kernel tracing
+
+# This provides support for System V shared memory.
+#
+options		SYSVSHM
+
+#  The `bpfilter' pseudo-device enables the Berkeley Packet Filter.  Be
+#  aware of the legal and administrative consequences of enabling this
+#  option.  The number of devices determines the maximum number of
+#  simultaneous BPF clients programs runnable.
+pseudo-device	bpfilter	4	#Berkeley packet filter
+
--- ./i386/conf/LINT.orig	Sun Feb 21 22:12:26 1999
+++ ./i386/conf/LINT	Sun Mar  7 12:58:10 1999
@@ -1929,6 +1929,22 @@
 options		SPX_HACK
 options		VFS_BIO_DEBUG
 
+# ALTQ options
+options		ALTQ		#alternate queueing
+options		CBQ		#class based queueing
+options		WFQ		#weighted fair queueing
+options		AFMAP		#atm flow mapping
+options		FIFOQ		#fifo queueing
+options		RED		#random early detection
+options		CBQ_RED		#red for cbq (needs CBQ and RED)
+options		RIO		#twin red for diffserv (needs RED)
+options		CBQ_RIO		#rio for cbq (needs CBQ, RIO, RED, CBQ_RED)
+options		LOCALQ		#local use
+options		ALTQ_ACCOUNT	#altq accounting
+options		ALTQ_ECN	#ecn extention to tcp (needs RED)
+options		ALTQ_IPSEC	#check ipsec in IPv4
+options		ALTQ_PPP	#sio modification for userland ppp
+
 # The 'dpt' driver provides support for DPT controllers (http://www.dpt.com/).
 # These have hardware RAID-{0,1,5} support, and do multi-initiator I/O.
 # The DPT controllers are commonly re-licensed under other brand-names -
--- ./i386/isa/if_ar.c.orig	Wed Dec 16 19:42:38 1998
+++ ./i386/isa/if_ar.c	Sun Mar  7 12:58:10 1999
@@ -346,6 +346,9 @@
 		ifp->if_ioctl = arioctl;
 		ifp->if_start = arstart;
 		ifp->if_watchdog = arwatchdog;
+#ifdef ALTQ
+		ifp->if_altqflags |= ALTQF_READY;
+#endif
 
 		sc->ifsppp.pp_flags = PP_KEEPALIVE;
 
--- ./i386/isa/if_cx.c.orig	Wed Dec 16 19:42:38 1998
+++ ./i386/isa/if_cx.c	Sun Mar  7 12:58:10 1999
@@ -281,6 +281,9 @@
 			c->ifp->if_ioctl = cxsioctl;
 			c->ifp->if_start = (start_func_t) cxstart;
 			c->ifp->if_watchdog = (watchdog_func_t) cxwatchdog;
+#ifdef ALTQ
+			c->ifp->if_altqflags |= ALTQF_READY;
+#endif
 			/* Init routine is never called by upper level? */
 			sppp_attach (c->ifp);
 			if_attach (c->ifp);
--- ./i386/isa/if_ed.c.orig	Tue Jan 19 01:21:38 1999
+++ ./i386/isa/if_ed.c	Sun Mar  7 12:58:10 1999
@@ -1684,6 +1684,9 @@
 			ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX |
 			    IFF_MULTICAST);
 
+#ifdef ALTQ
+		ifp->if_altqflags |= ALTQF_READY;
+#endif
 		/*
 		 * Attach the interface
 		 */
@@ -2071,6 +2074,12 @@
 		ifp->if_flags |= IFF_OACTIVE;
 		return;
 	}
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	    m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	}
+	else
+#endif
 	IF_DEQUEUE(&ifp->if_snd, m);
 	if (m == 0) {
 
--- ./i386/isa/if_ep.c.orig	Tue Jan 19 01:21:39 1999
+++ ./i386/isa/if_ep.c	Sun Mar  7 12:58:10 1999
@@ -615,6 +615,9 @@
     ifp->if_start = epstart;
     ifp->if_ioctl = epioctl;
     ifp->if_watchdog = epwatchdog;
+#ifdef ALTQ
+    ifp->if_altqflags |= ALTQF_READY;
+#endif
 
     if (!attached) {
 	if_attach(ifp);
@@ -810,6 +813,11 @@
     }
 startagain:
     /* Sneak a peek at the next packet */
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp))
+	m = (*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK);
+    else
+#endif
     m = ifp->if_snd.ifq_head;
     if (m == 0) {
 	splx(s);
@@ -828,6 +836,14 @@
     if (len + pad > ETHER_MAX_LEN) {
 	/* packet is obviously too large: toss it */
 	++ifp->if_oerrors;
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	    m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	    if (m != top)
+		panic("epstart: different mbuf dequeued!");
+	}
+	else
+#endif
 	IF_DEQUEUE(&ifp->if_snd, m);
 	m_freem(m);
 	goto readcheck;
@@ -842,6 +858,14 @@
 	    return;
 	}
     }
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp)) {
+	m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	if (m != top)
+	    panic("epstart: different mbuf dequeued!");
+    }
+    else
+#endif
     IF_DEQUEUE(&ifp->if_snd, m);
 
     outw(BASE + EP_W1_TX_PIO_WR_1, len); 
--- ./i386/isa/if_lnc.c.orig	Sun Jan 31 01:57:46 1999
+++ ./i386/isa/if_lnc.c	Sun Mar  7 12:58:10 1999
@@ -1240,6 +1240,9 @@
 	sc->arpcom.ac_if.if_type = IFT_ETHER;
 	sc->arpcom.ac_if.if_addrlen = ETHER_ADDR_LEN;
 	sc->arpcom.ac_if.if_hdrlen = ETHER_HDR_LEN;
+#ifdef ALTQ
+	sc->arpcom.ac_if.if_altqflags |= ALTQF_READY;
+#endif
 
 	/*
 	 * XXX -- should check return status of if_attach
@@ -1646,6 +1649,11 @@
 
 	do {
 
+#ifdef ALTQ
+		if (ALTQ_IS_ON(ifp))
+			head = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		else
+#endif
 		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, head);
 		if (!head)
 			return;
--- ./i386/isa/if_sr.c.orig	Mon Jan 18 22:27:03 1999
+++ ./i386/isa/if_sr.c	Sun Mar  7 12:58:10 1999
@@ -825,6 +825,9 @@
 		ifp->if_ioctl = srioctl;
 		ifp->if_start = srstart;
 		ifp->if_watchdog = srwatchdog;
+#ifdef ALTQ
+		ifp->if_altqflags |= ALTQF_READY;
+#endif
 
 		printf("sr%d: Adapter %d, port %d.\n",
 		       sc->unit, hc->cunit, sc->subunit);
@@ -1173,7 +1176,13 @@
 		 * hardcoded.  A packet can't be larger than 3 buffers (3 x
 		 * 512).
 		 */
+#if 0 /* defined(ALTQ) */
+		/* XXX use 6KB buffer instead of 16KB to reduce latency */
+		/* quick dirty hack, but very effective! */
+		if ((i + 3) >= (blkp->txmax * 6 / 16)) {  /* enough remains? */
+#else
 		if ((i + 3) >= blkp->txmax) {	/* enough remains? */
+#endif
 #if BUGGY > 9
 			printf("sr%d.srstart: i=%d (%d pkts); card full.\n",
 			       sc->unit, i, pkts);
--- ./net/if.h.orig	Sat Mar 21 14:36:20 1998
+++ ./net/if.h	Sun Mar  7 12:58:11 1999
@@ -44,6 +44,9 @@
 #ifndef KERNEL
 #include <sys/time.h>
 #endif
+#if 1 /* ALTQ */
+#include <net/if_altq.h>
+#endif
 
 /*
  * Structure describing information about an interface
--- ./net/if_atmsubr.c.orig	Fri Dec  4 23:54:52 1998
+++ ./net/if_atmsubr.c	Sun Mar  7 12:58:11 1999
@@ -35,6 +35,9 @@
 /*
  * if_atmsubr.c
  */
+#ifdef ALTQ
+#include "opt_altq.h"
+#endif
 
 #include "opt_inet.h"
 #include "opt_natm.h"
@@ -64,6 +67,10 @@
 #include <netnatm/natm.h>
 #endif
 
+#if defined(ALTQ) && defined(AFMAP)
+#include <netinet/altq_afmap.h>
+#endif
+
 #ifndef ETHERTYPE_IPV6
 #define ETHERTYPE_IPV6	0x86dd
 #endif
@@ -100,10 +107,25 @@
 	struct atmllc *atmllc;
 	struct atmllc *llc_hdr = NULL;
 	u_int32_t atm_flags;
+#ifdef ALTQ
+	struct pr_hdr pr_hdr;
+#endif
 
 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 		senderr(ENETDOWN);
 
+#ifdef ALTQ
+	/*
+	 * save a pointer to the protocol level header before adding
+	 * link headers.
+	 */
+	if (dst)
+		pr_hdr.ph_family = dst->sa_family;
+	else
+		pr_hdr.ph_family = AF_UNSPEC;
+	pr_hdr.ph_hdr = mtod(m, caddr_t);
+#endif /* ALTQ */
+
 	/*
 	 * check route
 	 */
@@ -161,6 +183,17 @@
 			 */
 			bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
 			llc_hdr = (struct atmllc *)(dst->sa_data + sizeof(atmdst));
+#ifdef ALTQ
+			/* modify pr_hdr to have a correct family */
+			switch (ATM_LLC_TYPE(llc_hdr)) {
+			case ETHERTYPE_IP:
+				pr_hdr.ph_family = AF_INET;
+				break;
+			case ETHERTYPE_IPV6:
+				pr_hdr.ph_family = AF_INET6;
+				break;
+			}
+#endif			
 			break;
 			
 		default:
@@ -174,6 +207,29 @@
 			senderr(EAFNOSUPPORT);
 		}
 
+#if defined(ALTQ) && defined(AFMAP)
+		if (ifp->if_altqflags & ALTQF_DRIVER1) {
+		        /* try to map flow to vpi/vci. */
+			struct flowinfo flow;
+		        struct afm *afm;
+
+			altq_extractflow(m, &pr_hdr, &flow, FIMB_ALL);
+		        if ((afm = afm_match(ifp, &flow)) != NULL) {
+			        /* matching entry found.  overwrite vpi:vci. */
+#if 0
+				printf("%s%d: atm_output:afmap vci %d -> %d\n",
+				       ifp->if_name, ifp->if_unit,
+				       ATM_PH_VCI(&atmdst), afm->afm_vci);
+#endif
+			        ATM_PH_VPI(&atmdst) = afm->afm_vpi;
+			        ATM_PH_SETVCI(&atmdst, afm->afm_vci);
+
+				afm->afms_packets++;
+				afm->afms_bytes = m->m_pkthdr.len;
+			}
+		}
+#endif /* ALTQ && AFMAP */
+
 		/*
 		 * must add atm_pseudohdr to data
 		 */
@@ -202,14 +258,37 @@
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        s = splimp();
+		error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+		splx(s);
+		if (error) {
+			IF_DROP(&ifp->if_snd);
+		}
+		else {
+			ifp->if_obytes += m->m_pkthdr.len;
+			if (m->m_flags & M_MCAST)
+				ifp->if_omcasts++;
+		}
+		return (error);
+	}
+#endif /* ALTQ */
+
 	s = splimp();
 	if (IF_QFULL(&ifp->if_snd)) {
 		IF_DROP(&ifp->if_snd);
+#ifdef ALTQ_ACCOUNT
+		ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCDROP);
+#endif
 		splx(s);
 		senderr(ENOBUFS);
 	}
 	ifp->if_obytes += m->m_pkthdr.len;
 	IF_ENQUEUE(&ifp->if_snd, m);
+#ifdef ALTQ_ACCOUNT
+	ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCOK);
+#endif
 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
 		(*ifp->if_start)(ifp);
 	splx(s);
--- ./net/if_ethersubr.c.orig	Tue Jan 12 13:07:00 1999
+++ ./net/if_ethersubr.c	Sun Mar  7 13:17:40 1999
@@ -33,6 +33,9 @@
  *	@(#)if_ethersubr.c	8.1 (Berkeley) 6/10/93
  * $Id: if_ethersubr.c,v 1.54 1999/01/12 12:07:00 eivind Exp $
  */
+#ifdef ALTQ
+#include "opt_altq.h"
+#endif
 
 #include "opt_atalk.h"
 #include "opt_inet.h"
@@ -139,6 +142,9 @@
 	int off, len = m->m_pkthdr.len, loop_copy = 0;
 	int hlen;	/* link layer header lenght */
 	struct arpcom *ac = (struct arpcom *)ifp;
+#ifdef ALTQ
+	struct pr_hdr pr_hdr;
+#endif
 
 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 		senderr(ENETDOWN);
@@ -167,6 +173,15 @@
 			    time_second < rt->rt_rmx.rmx_expire)
 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
 	}
+#ifdef ALTQ
+	/*
+	 * save a pointer to the protocol level header before adding
+	 * link headers.
+	 */
+	pr_hdr.ph_family = dst->sa_family;
+	pr_hdr.ph_hdr = mtod(m, caddr_t);
+#endif /* ALTQ */
+
 	hlen = ETHER_HDR_LEN;
 	switch (dst->sa_family) {
 #ifdef INET
@@ -397,10 +412,16 @@
 	 */
 	if (IF_QFULL(&ifp->if_snd)) {
 		IF_DROP(&ifp->if_snd);
+#ifdef ALTQ_ACCOUNT
+		ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCDROP);
+#endif
 		splx(s);
 		senderr(ENOBUFS);
 	}
 	IF_ENQUEUE(&ifp->if_snd, m);
+#ifdef ALTQ_ACCOUNT
+	ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCOK);
+#endif
 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
 		(*ifp->if_start)(ifp);
 	splx(s);
@@ -643,6 +664,22 @@
 #endif /* ISO || LLC || NETATALK */
 	}
 
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        s = splimp();
+		error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+		splx(s);
+		if (error) {
+			IF_DROP(&ifp->if_snd);
+		}
+		else {
+		    ifp->if_obytes += len + sizeof (struct ether_header);
+		    if (m->m_flags & M_MCAST)
+		    	ifp->if_omcasts++;
+		}
+		return (error);
+	}
+#endif /* ALTQ */
 	s = splimp();
 	if (IF_QFULL(inq)) {
 		IF_DROP(inq);
--- ./net/if_loop.c.orig	Sun Jul 12 18:46:52 1998
+++ ./net/if_loop.c	Sun Mar  7 12:58:11 1999
@@ -91,6 +91,9 @@
 static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
 
 static void loopattach __P((void *));
+#ifdef ALTQ
+static void lo_altqstart __P((struct ifnet *));
+#endif
 PSEUDO_SET(loopattach, if_loop);
 
 static int looutput __P((struct ifnet *ifp,
@@ -120,6 +123,10 @@
 	    ifp->if_ioctl = loioctl;
 	    ifp->if_output = looutput;
 	    ifp->if_type = IFT_LOOP;
+#ifdef ALTQ
+	    ifp->if_start = lo_altqstart;
+	    ifp->if_altqflags |= ALTQF_READY;
+#endif
 	    if_attach(ifp);
 #if NBPFILTER > 0
 	    bpfattach(ifp, DLT_NULL, sizeof(u_int));
@@ -230,6 +237,36 @@
 		m_adj(m, hlen);
 	}
 
+#ifdef ALTQ
+	/*
+	 * altq for loop is just for debugging.
+	 * only used when called for loop interface (not for
+	 * a simplex interface).
+	 */
+	if (ALTQ_IS_ON(ifp) && ifp->if_start == lo_altqstart) {
+		struct pr_hdr pr_hdr;
+		int32_t *afp;
+	        int error;
+
+		pr_hdr.ph_family = dst->sa_family;
+		pr_hdr.ph_hdr = mtod(m, caddr_t);
+
+		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();
+		error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+		splx(s);
+		if (error) {
+			IF_DROP(&ifp->if_snd);
+		}
+		return (error);
+	}
+#endif /* ALTQ */
+
 	switch (dst->sa_family) {
 #ifdef INET
 	case AF_INET:
@@ -280,6 +317,84 @@
 	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;
+	
+	if (!ALTQ_IS_ON(ifp))
+		return;
+    
+	while (1) {
+		s = splimp();
+		m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		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 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 */
 static void
--- ./net/if_sl.c.orig	Wed Jul 15 04:32:23 1998
+++ ./net/if_sl.c	Sun Mar  7 12:58:11 1999
@@ -68,6 +68,10 @@
 #include "sl.h"
 #if NSL > 0
 
+#ifdef ALTQ
+#include "opt_altq.h"
+#endif
+
 #include "bpfilter.h"
 #include "opt_inet.h"
 
@@ -225,6 +229,7 @@
 		sc->sc_fastq.ifq_maxlen = 32;
 		sc->sc_if.if_linkmib = sc;
 		sc->sc_if.if_linkmiblen = sizeof *sc;
+		sc->sc_if.if_altqflags |= ALTQF_READY;
 		if_attach(&sc->sc_if);
 #if NBPFILTER > 0
 		bpfattach(&sc->sc_if, DLT_SLIP, SLIP_HDRLEN);
@@ -473,6 +478,12 @@
 	register struct ip *ip;
 	register struct ifqueue *ifq;
 	int s;
+#ifdef ALTQ
+	struct pr_hdr pr_hdr;
+
+	pr_hdr.ph_family = dst->sa_family;
+	pr_hdr.ph_hdr = mtod(m, caddr_t);
+#endif
 
 	/*
 	 * `Cannot happen' (see slioctl).  Someday we will extend
@@ -503,14 +514,37 @@
 	if (ip->ip_tos & IPTOS_LOWDELAY)
 		ifq = &sc->sc_fastq;
 	s = splimp();
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        int error;
+		
+	        error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+	        if (error) {
+			splx(s);
+			IF_DROP(&sc->sc_if.if_snd);
+			sc->sc_if.if_oerrors++;
+			return (error);
+		}
+	}
+	else {
+#endif /* ALTQ */
 	if (IF_QFULL(ifq)) {
 		IF_DROP(ifq);
+#ifdef ALTQ_ACCOUNT
+		ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCDROP);
+#endif
 		m_freem(m);
 		splx(s);
 		sc->sc_if.if_oerrors++;
 		return (ENOBUFS);
 	}
 	IF_ENQUEUE(ifq, m);
+#ifdef ALTQ_ACCOUNT
+	ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCOK);
+#endif
+#ifdef ALTQ
+	}
+#endif
 	if (sc->sc_ttyp->t_outq.c_cc == 0)
 		slstart(sc->sc_ttyp);
 	splx(s);
@@ -562,11 +596,20 @@
 		 * Get a packet and send it to the interface.
 		 */
 		s = splimp();
+#ifdef ALTQ
+		if (ALTQ_IS_ON(&sc->sc_if))
+			m = (*sc->sc_if.if_altqdequeue)(&sc->sc_if,
+							ALTDQ_DEQUEUE);
+		else {
+#endif
 		IF_DEQUEUE(&sc->sc_fastq, m);
 		if (m)
 			sc->sc_if.if_omcasts++;		/* XXX */
 		else
 			IF_DEQUEUE(&sc->sc_if.if_snd, m);
+#ifdef ALTQ
+		}
+#endif
 		splx(s);
 		if (m == NULL)
 			return 0;
--- ./net/if_spppsubr.c.orig	Sun Dec 27 22:30:44 1998
+++ ./net/if_spppsubr.c	Sun Mar  7 12:58:11 1999
@@ -20,6 +20,10 @@
  * $Id: if_spppsubr.c,v 1.52 1998/12/27 21:30:44 phk Exp $
  */
 
+#ifdef ALTQ
+#include "opt_altq.h"
+#endif
+
 #include <sys/param.h>
 
 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -619,6 +623,9 @@
  */
 static int
 sppp_output(struct ifnet *ifp, struct mbuf *m,
+#ifdef ALTQ
+	struct pr_hdr pr_hdr;
+#endif
 	    struct sockaddr *dst, struct rtentry *rt)
 {
 	struct sppp *sp = (struct sppp*) ifp;
@@ -647,6 +654,18 @@
 		s = splimp();
 	}
 
+#ifdef ALTQ
+	/*
+	 * save a pointer to the protocol level header before adding
+	 * link headers.
+	 */
+	pr_hdr.ph_family = dst->sa_family;
+	pr_hdr.ph_hdr = mtod(m, caddr_t);
+#endif /* ALTQ */
+
+#ifdef ALTQ
+	if (!ALTQ_IS_ON(ifp)) {
+#endif
 	ifq = &ifp->if_snd;
 #ifdef INET
 	if (dst->sa_family == AF_INET) {
@@ -693,6 +712,9 @@
 			ifq = &sp->pp_fastq;
 	}
 #endif
+#ifdef ALTQ
+        }
+#endif
 
 	/*
 	 * Prepend general data packet PPP header. For now, IP only.
@@ -767,18 +789,39 @@
 		return (EAFNOSUPPORT);
 	}
 
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        int error, len;
+	        len = m->m_pkthdr.len;
+	        error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+	        if (error) {
+			IF_DROP (&ifp->if_snd);
+		}
+		else
+		        ifp->if_obytes += len + 3;
+	        splx(s);
+	        return (error);
+	}
+#endif /* ALTQ */
+
 	/*
 	 * Queue message on interface, and start output if interface
 	 * not yet active.
 	 */
 	if (IF_QFULL (ifq)) {
 		IF_DROP (&ifp->if_snd);
+#ifdef ALTQ_ACCOUNT
+		ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCDROP);
+#endif
 		m_freem (m);
 		++ifp->if_oerrors;
 		splx (s);
 		return (rv? rv: ENOBUFS);
 	}
 	IF_ENQUEUE (ifq, m);
+#ifdef ALTQ_ACCOUNT
+	ALTQ_ACCOUNTING(ifp, m, &pr_hdr, ALTEQ_ACCOK);
+#endif
 	if (! (ifp->if_flags & IFF_OACTIVE))
 		(*ifp->if_start) (ifp);
 
@@ -858,6 +901,12 @@
 {
 	struct sppp *sp = (struct sppp*) ifp;
 
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        (void)(*ifp->if_altqdequeue)(ifp, ALTDQ_FLUSH);
+	        return;
+	}
+#endif
 	sppp_qflush (&sp->pp_if.if_snd);
 	sppp_qflush (&sp->pp_fastq);
 	sppp_qflush (&sp->pp_cpq);
@@ -873,6 +922,11 @@
 	int empty, s;
 
 	s = splimp();
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp))
+	        empty = ((*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK) == NULL);
+	else
+#endif
 	empty = !sp->pp_fastq.ifq_head && !sp->pp_cpq.ifq_head &&
 		!sp->pp_if.if_snd.ifq_head;
 	splx(s);
@@ -890,6 +944,13 @@
 	int s;
 
 	s = splimp();
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        m = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	        splx(s);
+	        return (m);
+	}
+#endif /* ALTQ */
 	/*
 	 * Process only the control protocol queue until we have at
 	 * least one NCP open.
@@ -1071,6 +1132,11 @@
 				if (ifp->if_flags & IFF_UP) {
 					if_down (ifp);
 					sppp_qflush (&sp->pp_cpq);
+#ifdef ALTQ
+					if (ALTQ_IS_ON(ifp))
+			        		(void)(*ifp->if_altqdequeue)
+							(ifp, ALTDQ_FLUSH);
+#endif
 				}
 			}
 			++sp->pp_loopcnt;
@@ -1206,6 +1272,22 @@
 			sppp_print_bytes ((u_char*) (lh+1), len);
 		addlog(">\n");
 	}
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+		struct pr_hdr pr_hdr;
+	        int error, len;
+
+	        len = m->m_pkthdr.len;
+		altq_mkctlhdr(&pr_hdr);  /* fake a control type header */
+	        error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+	        if (error) {
+			IF_DROP (&ifp->if_snd);
+		}
+		else
+		        ifp->if_obytes += len + 3;
+	        return;
+	}
+#endif /* ALTQ */
 	if (IF_QFULL (&sp->pp_cpq)) {
 		IF_DROP (&sp->pp_fastq);
 		IF_DROP (&ifp->if_snd);
@@ -1514,6 +1596,10 @@
 			if_down (ifp);
 			sppp_qflush (&sp->pp_cpq);
 
+#ifdef ALTQ
+ 			if (ALTQ_IS_ON(ifp))
+ 			        (void)(*ifp->if_altqdequeue) (ifp, ALTDQ_FLUSH);
+#endif
 			/* Shut down the PPP link. */
 			/* XXX */
 			lcp.Down(sp);
@@ -2027,6 +2113,11 @@
 					if_down(ifp);
 					sppp_qflush(&sp->pp_cpq);
 					/* XXX ? */
+#ifdef ALTQ
+		 			if (ALTQ_IS_ON(ifp))
+ 			        		(void)(*ifp->if_altqdequeue)
+							(ifp, ALTDQ_FLUSH);
+#endif
 					lcp.Down(sp);
 					lcp.Up(sp);
 				}
@@ -3764,6 +3855,22 @@
 			sppp_print_bytes((u_char*) (lh+1), len);
 		addlog(">\n");
 	}
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+		struct pr_hdr pr_hdr;
+	        int error, len;
+
+	        len = m->m_pkthdr.len;
+		altq_mkctlhdr(&pr_hdr);  /* fake a control type header */
+	        error = (*ifp->if_altqenqueue)(ifp, m, &pr_hdr, ALTEQ_NORMAL);
+	        if (error) {
+			IF_DROP (&ifp->if_snd);
+		}
+		else
+		        ifp->if_obytes += len + 3;
+	        return;
+	}
+#endif /* ALTQ */
 	if (IF_QFULL (&sp->pp_cpq)) {
 		IF_DROP (&sp->pp_fastq);
 		IF_DROP (&ifp->if_snd);
@@ -3822,6 +3929,10 @@
 			printf (SPP_FMT "down\n", SPP_ARGS(ifp));
 			if_down (ifp);
 			sppp_qflush (&sp->pp_cpq);
+#ifdef ALTQ
+			if (ALTQ_IS_ON(ifp))
+			        (void)(*ifp->if_altqdequeue)(ifp, ALTDQ_FLUSH);
+#endif
 			if (! (sp->pp_flags & PP_CISCO)) {
 				/* XXX */
 				/* Shut down the PPP link. */
--- ./net/if_var.h.orig	Wed Dec 16 19:30:43 1998
+++ ./net/if_var.h	Sun Mar  7 12:58:11 1999
@@ -138,6 +138,16 @@
 		__P((struct ifnet *, struct sockaddr **, struct sockaddr *));
 	struct	ifqueue if_snd;		/* output queue */
 	struct	ifqueue *if_poll_slowq;	/* input queue for slow devices */
+#if 1 /* ALTQ */
+	/* alternate queueing related stuff */
+	int	if_altqtype;		/* queueing scheme id */
+	int	if_altqflags;		/* altq flags (e.g. ready, in-use) */
+	void	*if_altqp;		/* queue state */
+	int	(*if_altqenqueue)
+		__P((struct ifnet *, struct mbuf *, struct pr_hdr *, int));
+	struct mbuf *(*if_altqdequeue)
+		__P((struct ifnet *, int));
+#endif /* ALTQ */
 };
 typedef void if_init_f_t __P((void *));
 
--- ./netinet/in.h.orig	Mon Dec 14 19:09:13 1998
+++ ./netinet/in.h	Sun Mar  7 12:58:11 1999
@@ -424,6 +424,9 @@
 	{ "fastforwarding", CTLTYPE_INT }, \
 }
 
+#if 1 /* ALTQ */
+#include <netinet/in_altq.h>
+#endif
 
 #ifdef KERNEL
 struct ifnet; struct mbuf;	/* forward declarations for Standard C */
--- ./netinet/ip.h.orig	Sun Jun  7 14:00:13 1998
+++ ./netinet/ip.h	Sun Mar  7 12:58:11 1999
@@ -89,6 +89,11 @@
 #define	IPTOS_THROUGHPUT	0x08
 #define	IPTOS_RELIABILITY	0x04
 #define	IPTOS_MINCOST		0x02
+#if 1 /* ALTQ_ECN */
+/* ECN bits proposed by Sally Floyd */
+#define IPTOS_CE		0x01	/* congestion experienced */
+#define IPTOS_ECT		0x02	/* ECN-capable transport */
+#endif
 
 /*
  * Definitions for IP precedence (also in ip_tos) (hopefully unused)
--- ./netinet/ip_input.c.orig	Tue Jan 12 13:25:00 1999
+++ ./netinet/ip_input.c	Sun Mar  7 12:58:11 1999
@@ -1513,9 +1513,19 @@
 		break;
 
 	case ENOBUFS:
+#ifdef ALTQ
+		/*
+		 * don't generate ICMP_SOURCEQUENCH
+		 * (RFC1812 Requirements for IP Version 4 Routers)
+		 */
+		if (mcopy)
+			m_freem(mcopy);
+		return;
+#else
 		type = ICMP_SOURCEQUENCH;
 		code = 0;
 		break;
+#endif
 	}
 	icmp_error(mcopy, type, code, dest, destifp);
 }
--- ./netinet/ip_mroute.c.orig	Mon Jan 18 03:06:57 1999
+++ ./netinet/ip_mroute.c	Sun Mar  7 12:58:11 1999
@@ -29,6 +29,7 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
+#include <netinet/in_pcb.h>
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/in_var.h>
@@ -2128,6 +2129,12 @@
     static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
     register int s;
     struct ifnet *ifp;
+#ifdef ALTQ
+    /* support IP_RECVIF used by rsvpd rel4.2a1 */
+    struct inpcb *inp;
+    struct socket *so;
+    struct mbuf *opts;
+#endif
 
     if (rsvpdebug)
 	printf("rsvp_input: rsvp_on %d\n",rsvp_on);
@@ -2180,7 +2187,11 @@
     if (rsvpdebug)
 	printf("rsvp_input: check socket\n");
 
+#ifdef ALTQ
+    if ((so = viftable[vifi].v_rsvpd) == NULL) {
+#else
     if (viftable[vifi].v_rsvpd == NULL) {
+#endif
 	/* drop packet, since there is no specific socket for this
 	 * interface */
 	    if (rsvpdebug)
@@ -2195,12 +2206,33 @@
 	printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n",
 	       m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv)));
 
+#ifdef ALTQ
+    opts = NULL;
+    inp = (struct inpcb *)so->so_pcb;
+    if (inp->inp_flags & INP_CONTROLOPTS ||
+	inp->inp_socket->so_options & SO_TIMESTAMP)
+	ip_savecontrol(inp, &opts, ip, m);
+    if (sbappendaddr(&so->so_rcv,
+		     (struct sockaddr *)&rsvp_src,m, opts) == 0) {
+	m_freem(m);
+	if (opts)
+	    m_freem(opts);
+	if (rsvpdebug)
+	    printf("rsvp_input: Failed to append to socket\n");
+    }
+    else {
+	sorwakeup(so);
+	if (rsvpdebug)
+	    printf("rsvp_input: send packet up\n");
+    }
+#else /* !ALTQ */
     if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0)
 	if (rsvpdebug)
 	    printf("rsvp_input: Failed to append to socket\n");
     else
 	if (rsvpdebug)
 	    printf("rsvp_input: send packet up\n");
+#endif /* !ALTQ */
     
     splx(s);
 }
--- ./netinet/ip_output.c.orig	Fri Feb 19 19:56:58 1999
+++ ./netinet/ip_output.c	Sun Mar  7 12:58:11 1999
@@ -372,6 +372,12 @@
 #endif /* IPFIREWALL_FORWARD */
 	}
 #endif /* notdef */
+#ifdef ALTQ
+	/*
+	 * disable packet drop hack.
+	 * packetdrop should be done by queueing.
+	 */
+#else /* !ALTQ */
 	/*
 	 * Verify that we have any chance at all of being able to queue
 	 *      the packet or packet fragments
@@ -381,6 +387,7 @@
 			error = ENOBUFS;
 			goto bad;
 	}
+#endif /* !ALTQ */
 
 	/*
 	 * Look for broadcast address and
--- ./netinet/tcp.h.orig	Mon Jul 13 13:09:51 1998
+++ ./netinet/tcp.h	Sun Mar  7 12:58:11 1999
@@ -64,7 +64,13 @@
 #define	TH_PUSH	0x08
 #define	TH_ACK	0x10
 #define	TH_URG	0x20
+#if 1 /* ALTQ_ECN */
+#define	TH_ECNECHO	0x40		/* ecn echo */
+#define	TH_CWR		0x80		/* congestion window reduced */
+#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECNECHO|TH_CWR)
+#else
 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG)
+#endif
 
 	u_short	th_win;			/* window */
 	u_short	th_sum;			/* checksum */
--- ./netinet/tcp_input.c.orig	Thu Dec  3 21:23:20 1998
+++ ./netinet/tcp_input.c	Sun Mar  7 12:58:11 1999
@@ -88,6 +88,19 @@
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, delayed_ack, CTLFLAG_RW, 
 	&tcp_delack_enabled, 0, "");
 
+#ifdef ALTQ_ECN
+/*
+ * experimental ECN support based on 
+ *	draft-kksjf-ecn-03.txt and http://www-nrg.ee.lbl.gov/floyd/ECN-IP.txt
+ *
+ * NOTE: this is an experimental implementation.
+ *
+ */
+int tcp_ecn = 1;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_ECN, ecn,
+	CTLFLAG_RW, &tcp_ecn , 0, "");
+#endif /* ALTQ_ECN */
+
 u_long	tcp_now;
 struct inpcbhead tcb;
 struct inpcbinfo tcbinfo;
@@ -275,6 +288,9 @@
 	struct tcpopt to;		/* options in this segment */
 	struct rmxp_tao *taop;		/* pointer to our TAO cache entry */
 	struct rmxp_tao	tao_noncached;	/* in case there's no cached entry */
+#ifdef ALTQ_ECN
+	u_char ip_tos;
+#endif
 #ifdef TCPDEBUG
 	short ostate = 0;
 #endif
@@ -297,6 +313,10 @@
 		ti = mtod(m, struct tcpiphdr *);
 	}
 
+#ifdef ALTQ_ECN
+	/* save ip_tos before clearing it for checksum */
+	ip_tos = ((struct ip *)ti)->ip_tos;
+#endif
 	/*
 	 * Checksum extended TCP header and data.
 	 */
@@ -502,6 +522,11 @@
 	if (tp->t_state != TCPS_LISTEN)
 		tcp_dooptions(tp, optp, optlen, ti, &to);
 
+#ifdef ALTQ_ECN
+	/* if congestion experienced, set ECN bit in the next output. */
+	if ((ip_tos & (IPTOS_ECT|IPTOS_CE)) == (IPTOS_ECT|IPTOS_CE))
+		tp->t_flags |= TF_RCVD_CE;
+#endif
 	/*
 	 * Header prediction: check for the two common cases
 	 * of a uni-directional data xfer.  If the packet has
@@ -520,7 +545,11 @@
 	 * be TH_NEEDSYN.
 	 */
 	if (tp->t_state == TCPS_ESTABLISHED &&
+#ifdef ALTQ_ECN
+	    (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ECNECHO|TH_CWR|TH_ACK)) == TH_ACK &&
+#else
 	    (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
+#endif
 	    ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
 	    ((to.to_flag & TOF_TS) == 0 ||
 	     TSTMP_GEQ(to.to_tsval, tp->ts_recent)) &&
@@ -567,6 +596,11 @@
 				tcpstat.tcps_rcvackbyte += acked;
 				sbdrop(&so->so_snd, acked);
 				tp->snd_una = ti->ti_ack;
+#ifdef ALTQ_ECN
+				/* sync snc_rcvr with snd_una */
+				if (SEQ_GT(tp->snd_una, tp->snd_rcvr))
+					tp->snd_rcvr = tp->snd_una;
+#endif
 				m_freem(m);
 
 				/*
@@ -702,6 +736,18 @@
 		tp->irs = ti->ti_seq;
 		tcp_sendseqinit(tp);
 		tcp_rcvseqinit(tp);
+#ifdef ALTQ_ECN
+		tp->snd_rcvr = tp->snd_una;
+		/*
+		 * if both ECNECHO and CWR flag bits are set,
+		 * peer is ECN capable
+		 */
+		if (tcp_ecn &&
+		    (tiflags & (TH_ECNECHO|TH_CWR)) == (TH_ECNECHO|TH_CWR)) {
+			tp->t_flags |= TF_REQ_ECN;
+			tiflags &= ~(TH_ECNECHO|TH_CWR);
+		}
+#endif
 		/*
 		 * Initialization of the tcpcb for transaction;
 		 *   set SND.WND = SEG.WND,
@@ -833,6 +879,23 @@
 
 		tp->irs = ti->ti_seq;
 		tcp_rcvseqinit(tp);
+#ifdef ALTQ_ECN
+		tp->snd_rcvr = tp->snd_una;
+		/*
+		 * peer is ECN capable
+		 *  - if ECNECHO is set but CWR is not set for SYN-ACK
+		 *  - if both ECNECHO and CWR are set for simultaneous open
+		 */
+		if (tcp_ecn) {
+			if ((tiflags & (TH_ACK|TH_ECNECHO|TH_CWR))
+			    == (TH_ACK|TH_ECNECHO) ||
+			    (tiflags & (TH_ACK|TH_ECNECHO|TH_CWR))
+			    == (TH_ECNECHO|TH_CWR)) {
+				tp->t_flags |= TF_REQ_ECN;
+				tiflags &= ~(TH_ECNECHO|TH_CWR);
+			}
+		}
+#endif
 		if (tiflags & TH_ACK) {
 			/*
 			 * Our SYN was acked.  If segment contains CC.ECHO
@@ -1320,6 +1383,37 @@
 	case TCPS_LAST_ACK:
 	case TCPS_TIME_WAIT:
 
+#ifdef ALTQ_ECN
+		/*
+		 * if we receive ECN notify and we are not already in
+		 * receovery phase, reduce cwnd by half but don't slow-
+		 * start.
+		 */
+		if (tcp_ecn && (tiflags & TH_ECNECHO)) {
+			if (SEQ_GEQ(tp->snd_una, tp->snd_rcvr)) {
+				u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 /
+					tp->t_maxseg;
+				if (win < 2)
+					win = 2;
+				tp->snd_ssthresh = win * tp->t_maxseg;
+				tp->snd_cwnd = tp->snd_ssthresh;
+				tp->t_flags |= TF_SENDCWR;
+				/*
+				 * advance snd_rcvr to snd_max not to
+				 * reduce cwnd again until all outstanding
+				 * packets are acked.
+				 */
+				tp->snd_rcvr = tp->snd_max;
+			}
+		}
+		/*
+		 * if we receive CWR, we know that the peer has reduced
+		 * its congestion window.  stop sending ecn-echo.
+		 */
+		if (tiflags & TH_CWR)
+			tp->t_flags &= ~TF_RCVD_CE;
+#endif /* ALTQ_ECN */
+		    
 		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
 			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
 				tcpstat.tcps_rcvdupack++;
@@ -1352,6 +1446,17 @@
 					tp->t_dupacks = 0;
 				else if (++tp->t_dupacks == tcprexmtthresh) {
 					tcp_seq onxt = tp->snd_nxt;
+#ifdef ALTQ_ECN
+					if (SEQ_LT(tp->snd_una, tp->snd_rcvr)) {
+						/*
+						 * we are in recovery phase
+						 * and have already halved
+						 * cwnd within a roundtrip.
+						 * don't reduce cwnd again.
+						 */
+					}
+					else {
+#endif /* ALTQ_ECN */
 					u_int win =
 					    min(tp->snd_wnd, tp->snd_cwnd) / 2 /
 						tp->t_maxseg;
@@ -1359,6 +1464,12 @@
 					if (win < 2)
 						win = 2;
 					tp->snd_ssthresh = win * tp->t_maxseg;
+#ifdef ALTQ_ECN
+					tp->t_flags |= TF_SENDCWR;
+					/* mark we are in recovery phase */
+					tp->snd_rcvr = tp->snd_max;
+				        }
+#endif
 					tp->t_timer[TCPT_REXMT] = 0;
 					tp->t_rtt = 0;
 					tp->snd_nxt = ti->ti_ack;
@@ -1476,6 +1587,11 @@
 		}
 		sowwakeup(so);
 		tp->snd_una = ti->ti_ack;
+#ifdef ALTQ_ECN
+		/* sync snc_rcvr with snd_una */
+		if (SEQ_GT(tp->snd_una, tp->snd_rcvr))
+			tp->snd_rcvr = tp->snd_una;
+#endif
 		if (SEQ_LT(tp->snd_nxt, tp->snd_una))
 			tp->snd_nxt = tp->snd_una;
 
--- ./netinet/tcp_output.c.orig	Wed Jan 20 18:31:59 1999
+++ ./netinet/tcp_output.c	Sun Mar  7 12:58:11 1999
@@ -542,6 +542,30 @@
 		panic("tcp_output");
 	(void)memcpy(ti, tp->t_template, sizeof (struct tcpiphdr));
 
+#ifdef ALTQ_ECN
+	if (tcp_ecn) {
+		/*
+		 * if we have received congestion experienced segs,
+		 * set ECNECHO bit.
+		 * if this is a SYN seg, set ECNECHO and CWR for a pure SYN,
+		 * set only ECNECHO for SYN-ACK.
+		 */
+		if (tp->t_flags & TF_RCVD_CE)
+			flags |= TH_ECNECHO;
+		if ((flags & (TH_SYN|TH_ACK)) == TH_SYN)
+			flags |= (TH_ECNECHO|TH_CWR);
+		else if ((flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK))
+			flags |= TH_ECNECHO;
+		/*
+		 * if we have reduced the congestion window, notify
+		 * the peer by setting CWR bit.
+		 */
+		if (tp->t_flags & TF_SENDCWR) {
+			flags |= TH_CWR;
+			tp->t_flags &= ~TF_SENDCWR;
+		}
+	}
+#endif
 	/*
 	 * Fill in fields, remembering maximum advertised
 	 * window for use in delaying messages about window sizes.
@@ -679,6 +703,14 @@
 	((struct ip *)ti)->ip_len = m->m_pkthdr.len;
 	((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip_ttl;	/* XXX */
 	((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip_tos;	/* XXX */
+#ifdef ALTQ_ECN
+	/*
+	 * if peer is ECN capable and this is not a pure ack seg,
+	 * set ECN capable bit in IP header.
+	 */
+	if ((tp->t_flags & TF_REQ_ECN) && len > 0)
+		((struct ip *)ti)->ip_tos |= IPTOS_ECT;
+#endif
 #if 1
 	/*
 	 * See if we should do MTU discovery.  We do it only if the following
--- ./netinet/tcp_timer.c.orig	Fri Apr 24 11:25:35 1998
+++ ./netinet/tcp_timer.c	Sun Mar  7 12:58:11 1999
@@ -291,6 +291,10 @@
 		tp->snd_cwnd = tp->t_maxseg;
 		tp->snd_ssthresh = win * tp->t_maxseg;
 		tp->t_dupacks = 0;
+#ifdef ALTQ_ECN
+		tp->t_flags |= TF_SENDCWR;
+		tp->snd_rcvr = tp->snd_max;
+#endif
 		}
 		(void) tcp_output(tp);
 		break;
--- ./netinet/tcp_var.h.orig	Wed Jan 20 18:32:00 1999
+++ ./netinet/tcp_var.h	Sun Mar  7 12:58:11 1999
@@ -70,6 +70,11 @@
 #define	TF_REQ_CC	0x02000		/* have/will request CC */
 #define	TF_RCVD_CC	0x04000		/* a CC was received in SYN */
 #define	TF_SENDCCNEW	0x08000		/* send CCnew instead of CC in SYN */
+#ifdef ALTQ_ECN
+#define TF_REQ_ECN	0x10000		/* peer is ECN capable */
+#define TF_RCVD_CE	0x20000		/* send ECN in next seg */
+#define TF_SENDCWR	0x40000		/* send CWR in next seg */
+#endif
 #define	TF_MORETOCOME	0x10000		/* More data to be appended to sock */
 	int	t_force;		/* 1 if forcing out a byte */
 
@@ -85,6 +90,9 @@
 	tcp_seq	iss;			/* initial send sequence number */
 	tcp_seq	irs;			/* initial receive sequence number */
 
+#ifdef ALTQ_ECN
+	tcp_seq snd_rcvr;		/* outstanding seg at fastrecovery */
+#endif
 	tcp_seq	rcv_nxt;		/* receive next */
 	tcp_seq	rcv_adv;		/* advertised window */
 	u_long	rcv_wnd;		/* receive window */
@@ -305,7 +313,12 @@
 #define	TCPCTL_RECVSPACE	9	/* receive buffer space */
 #define	TCPCTL_KEEPINIT		10	/* receive buffer space */
 #define	TCPCTL_PCBLIST		11	/* list of all outstanding PCBs */
-#define TCPCTL_MAXID		12
+#ifdef ALTQ_ECN
+#define	TCPCTL_ECN		12	/* explicit congestion notification */
+#define TCPCTL_MAXID		13
+#else
+#define TCPCTL_MAXID		13
+#endif
 
 #define TCPCTL_NAMES { \
 	{ 0, 0 }, \
@@ -365,7 +378,9 @@
 extern	struct pr_usrreqs tcp_usrreqs;
 extern	u_long tcp_sendspace;
 extern	u_long tcp_recvspace;
-
+#ifdef ALTQ_ECN
+extern	int tcp_ecn;
+#endif
 #endif /* KERNEL */
 
 #endif /* _NETINET_TCP_VAR_H_ */
--- ./pci/if_de.c.orig	Mon Mar  1 18:03:24 1999
+++ ./pci/if_de.c	Sun Mar  7 12:58:12 1999
@@ -4243,6 +4243,11 @@
 #else
     struct mbuf *m0;
 #endif
+#ifdef 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) {
@@ -4393,6 +4398,28 @@
 		 * entries that we can use for one packet, so we have
 		 * recopy it into one mbuf and then try again.
 		 */
+#ifdef ALTQ
+		if (ALTQ_IS_ON(ifp)) {
+		    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;
+		    }
+		    tmp = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		    if (tmp != ombuf)
+			panic("tulip_txput: different mbuf dequeued!");
+		    compressed = 1;
+		}
+#endif
 		m = tulip_mbuf_compress(m);
 		if (m == NULL)
 		    goto finish;
@@ -4448,6 +4475,18 @@
      * The descriptors have been filled in.  Now get ready
      * to transmit.
      */
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp)) {
+	if (!compressed && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) {
+	    /* remove the mbuf from the queue */
+	    struct mbuf *tmp;
+	    tmp = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+	    if (tmp != ombuf)
+		panic("tulip_txput: different mbuf dequeued!");
+	}
+    }
+#endif
+
     IF_ENQUEUE(&sc->tulip_txq, m);
     m = NULL;
 
@@ -4516,6 +4555,16 @@
     /*
      * switch back to the single queueing ifstart.
      */
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp)) {
+	/*
+	 * de driver is too clever that it doesn't call if_start
+	 * when it thinks it doesn't need to, but altq needs it!
+	 */
+	sc->tulip_flags |= TULIP_WANTTXSTART;
+    }
+    else
+#endif
     sc->tulip_flags &= ~TULIP_WANTTXSTART;
     if (sc->tulip_txtimer == 0)
 	sc->tulip_txtimer = TULIP_TXTIMER;
@@ -4841,6 +4890,14 @@
     return error;
 }
 
+#ifdef 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
@@ -4859,6 +4916,21 @@
 	if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
 	    tulip_txput_setup(sc);
 
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	    struct mbuf *m, *m0;
+	    while ((m = (*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK)) != NULL) {
+		if ((m0 = tulip_txput(sc, m)) != NULL) {
+		    /* txput failed */
+		    if (m0 != m)
+			/* should not happen */
+			printf("tulip_if_start: bad mbuf dequeued!\n");
+		    break;
+		}
+	    }
+	}
+	else
+#endif /* ALTQ */
 	while (sc->tulip_if.if_snd.ifq_head != NULL) {
 	    struct mbuf *m;
 	    IF_DEQUEUE(&sc->tulip_if.if_snd, m);
@@ -4881,6 +4953,21 @@
     TULIP_PERFSTART(ifstart_one)
     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
 
+#ifdef ALTQ
+    if (ALTQ_IS_ON(ifp)) {
+	struct mbuf *m, *m0;
+	if ((sc->tulip_if.if_flags & IFF_RUNNING)
+	        && ((m = (*ifp->if_altqdequeue)(ifp, ALTDQ_PEEK)) != NULL)) {
+	    if ((m0 = tulip_txput(sc, m)) != NULL) {
+		/* txput tailed! */
+		if (m0 != m)
+		    /* should not happen */
+		    printf("tulip_if_start: bad mbuf dequeued!\n");
+	    }
+	}
+    }
+    else
+#endif /* !ALTQ */
     if ((sc->tulip_if.if_flags & IFF_RUNNING)
 	    && sc->tulip_if.if_snd.ifq_head != NULL) {
 	struct mbuf *m;
@@ -5080,6 +5167,9 @@
 
     tulip_reset(sc);
 
+#ifdef ALTQ
+    ifp->if_altqflags |= ALTQF_READY;
+#endif
 #if defined(__bsdi__) && _BSDI_VERSION >= 199510
     sc->tulip_pf = printf;
     TULIP_ETHER_IFATTACH(sc);
--- ./pci/if_fxp.c.orig	Mon Feb 15 09:47:10 1999
+++ ./pci/if_fxp.c	Sun Mar  7 12:58:19 1999
@@ -570,6 +570,9 @@
 	ifp->if_ioctl = fxp_ioctl;
 	ifp->if_start = fxp_start;
 	ifp->if_watchdog = fxp_watchdog;
+#ifdef ALTQ
+	ifp->if_altqflags |= ALTQF_READY;
+#endif
 
 	/*
 	 * Attach the interface.
@@ -812,14 +815,28 @@
 	 * NOTE: One TxCB is reserved to guarantee that fxp_mc_setup() can add
 	 *       a NOP command when needed.
 	 */
+#ifdef ALTQ
+	while (sc->tx_queued < FXP_NTXCB - 1) {
+#else
 	while (ifp->if_snd.ifq_head != NULL && sc->tx_queued < FXP_NTXCB - 1) {
+#endif
 		struct mbuf *m, *mb_head;
 		int segment;
 
 		/*
 		 * Grab a packet to transmit.
 		 */
+#ifdef ALTQ
+		if (ALTQ_IS_ON(ifp)) {
+		    mb_head = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		}
+		else
+			IF_DEQUEUE(&ifp->if_snd, mb_head);
+		if (mb_head == NULL)
+			break;
+#else
 		IF_DEQUEUE(&ifp->if_snd, mb_head);
+#endif
 
 		/*
 		 * Get pointer to next available tx desc.
@@ -969,6 +986,11 @@
 			/*
 			 * Try to start more packets transmitting.
 			 */
+#ifdef ALTQ
+			if (ALTQ_IS_ON(ifp))
+			        fxp_start(ifp);
+			else
+#endif
 			if (ifp->if_snd.ifq_head != NULL)
 				fxp_start(ifp);
 		}
--- ./pci/if_tl.c.orig	Mon Feb  1 22:32:52 1999
+++ ./pci/if_tl.c	Sun Mar  7 12:58:19 1999
@@ -1718,6 +1718,9 @@
 	ifp->if_watchdog = tl_watchdog;
 	ifp->if_init = tl_init;
 	ifp->if_mtu = ETHERMTU;
+#ifdef ALTQ
+	ifp->if_altqflags |= ALTQF_READY;
+#endif
 	ifp->if_snd.ifq_maxlen = TL_TX_LIST_CNT - 1;
 	callout_handle_init(&sc->tl_stat_ch);
 
@@ -2241,6 +2244,12 @@
 		CMD_PUT(sc, TL_CMD_ACK | r | type);
 	}
 
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+		tl_start(ifp);
+	}
+	else
+#endif
 	if (ifp->if_snd.ifq_head != NULL)
 		tl_start(ifp);
 
@@ -2410,6 +2419,12 @@
 	start_tx = sc->tl_cdata.tl_tx_free;
 
 	while(sc->tl_cdata.tl_tx_free != NULL) {
+#ifdef ALTQ
+		if (ALTQ_IS_ON(ifp)) {
+			m_head = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		}
+		else
+#endif
 		IF_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
@@ -2439,6 +2454,13 @@
 			bpf_mtap(ifp, cur_tx->tl_mbuf);
 #endif
 	}
+#ifdef ALTQ /* fix imported from 1.16.2.5 1998/12/05 */
+	/*
+	 * If there are no packets queued, bail.
+	 */
+	if (cur_tx == NULL)
+		return;
+#endif
 
 	/*
 	 * If there are no packets queued, bail.
--- ./pci/if_tx.c.orig	Mon Dec 14 07:32:56 1998
+++ ./pci/if_tx.c	Sun Mar  7 12:58:20 1999
@@ -227,6 +227,12 @@
 	epic_softc_t *sc = (epic_softc_t*)self;
 	struct pci_attach_args *pa = aux;
 	pci_chipset_tag_t pc = pa->pa_pc;
+#ifdef ALTQ
+	        if (ALTQ_IS_ON(ifp)) {
+			m0 = (*ifp->if_altqdequeue)(ifp, ALTDQ_FLUSH);
+			return;
+		}
+#endif
 	pci_intr_handle_t ih;
 	const char *intrstr = NULL;
 	struct ifnet *ifp;
@@ -242,6 +248,11 @@
 		printf(": can't find i/o space\n");
 		return;
 	}
+#ifdef ALTQ
+		if (ALTQ_IS_ON(ifp))
+			m0 = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		else
+#endif
 	if( bus_space_map(iot, iobase, iosize, 0, &sc->sc_sh)) {
 		printf(": can't map i/o space\n");
 		return;
@@ -492,6 +503,13 @@
 #else
 			ifp->if_flags |= IFF_LINK2;
 #endif
+#ifdef ALTQ
+	        if (ALTQ_IS_ON(&sc->epic_if)) {
+			epic_ifstart( &sc->epic_if );
+		}
+		else
+
+#endif
 		} else {
 			printf(", 10Mbps ");
 #if !defined(EPIC_NOIFMEDIA)
@@ -613,6 +631,12 @@
 			break;
 		}
 #endif
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+	        epic_ifstart(&sc->epic_if);
+	}
+	else
+#endif
 		default:
 			epic_stop(sc);
 			epic_init(sc);		
@@ -688,6 +712,9 @@
  */
 static int
 epic_common_attach(
+#ifdef ALTQ
+	ifp->if_altqflags |= ALTQF_READY;
+#endif
     epic_softc_t *sc)
 {
 	int i;
--- ./pci/if_xl.c.orig	Fri Feb 26 09:40:39 1999
+++ ./pci/if_xl.c	Sun Mar  7 12:58:20 1999
@@ -1462,6 +1462,9 @@
 	ifp->if_init = xl_init;
 	ifp->if_baudrate = 10000000;
 	ifp->if_snd.ifq_maxlen = XL_TX_LIST_CNT - 1;
+#ifdef ALTQ
+	ifp->if_altqflags |= ALTQF_READY;
+#endif
 
 	/*
 	 * Figure out the card type. 3c905B adapters have the
@@ -2058,6 +2061,12 @@
 
 	XL_SEL_WIN(7);
 
+#ifdef ALTQ
+	if (ALTQ_IS_ON(ifp)) {
+		xl_start(ifp);
+	}
+	else
+#endif
 	if (ifp->if_snd.ifq_head != NULL) {
 		xl_start(ifp);
 	}
@@ -2228,6 +2237,12 @@
 	start_tx = sc->xl_cdata.xl_tx_free;
 
 	while(sc->xl_cdata.xl_tx_free != NULL) {
+#ifdef ALTQ
+		if (ALTQ_IS_ON(ifp)) {
+			m_head = (*ifp->if_altqdequeue)(ifp, ALTDQ_DEQUEUE);
+		}
+		else
+#endif
 		IF_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
@@ -2257,6 +2272,13 @@
 			bpf_mtap(ifp, cur_tx->xl_mbuf);
 #endif
 	}
+#ifdef ALTQ /* fix imported from 1.5.2.14 1998/12/05 */
+	/*
+	 * If there are no packets queued, bail.
+	 */
+	if (cur_tx == NULL)
+		return;
+#endif
 
 	/*
 	 * If there are no packets queued, bail.

--lrZ03NoBR/3+SXJZ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=mkdiff

/usr/src/sys-altq find . -name "*.orig" | awk '{ print "diff -u ",$1,$1 }' | sed -e 's/.orig$//' | awk '{ print $0, ">> xxx/FreeBSD-3.1-990306.diff" }' | sh -x

--lrZ03NoBR/3+SXJZ--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990307142618.A4807>