Index: target/linux/x86/base-files/lib/upgrade/platform.sh
===================================================================
--- target/linux/x86/base-files/lib/upgrade/platform.sh	(revision 31220)
+++ target/linux/x86/base-files/lib/upgrade/platform.sh	(working copy)
@@ -26,8 +26,14 @@
 	# partition that points to the active rootfs partition.
 	# however this only matters if we actually need to preserve the config files
 	[ "$SAVE_CONFIG" -eq 1 ] || return 0
+	#&&& hb9xar: need ROOTFS here as well...
+	local ROOTFS
+	grep -q -e "jffs2" -e "squashfs" /proc/cmdline \
+		&& ROOTFS="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "block2mtd.block2mtd") { print substr($2,1,index($2, ",")-1) }' < /proc/cmdline)" \
+		|| ROOTFS="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "root") { print $2 }' < /proc/cmdline)"
+
 	grep rootfs /proc/mtd >/dev/null || {
-		echo /dev/hda2,65536,rootfs > /sys/module/block2mtd/parameters/block2mtd
+		echo /dev/${ROOTFS},65536,rootfs > /sys/module/block2mtd/parameters/block2mtd
 	}
 }
 append sysupgrade_pre_upgrade x86_prepare_ext2
Index: target/linux/x86/generic/config-2.6.32
===================================================================
--- target/linux/x86/generic/config-2.6.32	(revision 31220)
+++ target/linux/x86/generic/config-2.6.32	(working copy)
@@ -1,6 +1,20 @@
+CONFIG_GEODE_MFGPT_TIMER=y
+# CONFIG_GEODE_WDT is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_ILLEGAL_POINTER_VALUE=0
 CONFIG_K8_NB=y
+# CONFIG_M486 is not set
+CONFIG_MGEODE_LX=y
 CONFIG_PATA_LEGACY=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PCIEAER=y
 CONFIG_PCIEPORTBUS=y
+CONFIG_X86_DEBUGCTLMSR=y
+# CONFIG_X86_DS is not set
+CONFIG_X86_L1_CACHE_SHIFT=5
+CONFIG_X86_TSC=y
+CONFIG_X86_USE_3DNOW=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+# CONFIG_CRASHLOG is not set
Index: package/qos-scripts/files/usr/lib/qos/generate.sh
===================================================================
--- package/qos-scripts/files/usr/lib/qos/generate.sh	(revision 31220)
+++ package/qos-scripts/files/usr/lib/qos/generate.sh	(working copy)
@@ -282,6 +282,9 @@
 	}
 	config_get upload "$iface" upload
 	config_get_bool halfduplex "$iface" halfduplex
+	#&&& code relies on halfduplex being empty/undefined if false
+	if [ "$halfduplex" != 1 ];  then unset halfduplex; fi
+
 	config_get download "$iface" download
 	config_get classgroup "$iface" classgroup
 	config_get_bool overhead "$iface" overhead 0
@@ -321,6 +324,20 @@
 			append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate:$qdisc_esfq" "$N"
 		done
 		append ${prefix}q "$(tcrules)" "$N"
+
+		#&&&+++xar: start qosmon if required
+		config_get_bool dynamicbw      "$iface" dynamicbw      0
+		config_get      dynamicbwcycle "$iface" dynamicbwcycle 1000
+		config_get      dynamicbwip    "$iface" dynamicbwip
+		config_get      dynamicbwrtt   "$iface" dynamicbwrtt
+
+		if [ $dynamicbw -eq 1 -a "$dynamicbwip" != "" ]; then
+			# kill a possibly running qosmon instance
+			append ${prefix}q "for pid in \`pidof qosmon\`; do grep -q $dev /proc/\$pid/cmdline && kill \$pid; done" "$N"
+			# and start a new one
+			append ${prefix}q "qosmon -d $dev -x -b $dynamicbwcycle $dynamicbwip $rate $dynamicbwrtt" "$N"
+		fi
+		#&&&---
 		export dev_${dir}="ifconfig $dev up txqueuelen 5 >&- 2>&-
 tc qdisc del dev $dev root >&- 2>&-
 tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0
@@ -399,6 +416,9 @@
 		config_get upload "$iface" upload
 		config_get download "$iface" download
 		config_get halfduplex "$iface" halfduplex
+		#&&& code relies on halfduplex being empty/undefined if false
+		if [ "$halfduplex" != 1 ];  then unset halfduplex; fi
+
 		download="${download:-${halfduplex:+$upload}}"
 		add_insmod ipt_IMQ
 		append up "iptables -t mangle -A OUTPUT -o $device -j qos_${cg}" "$N"
Index: package/qos-scripts/files/usr/bin/qos-stop
===================================================================
--- package/qos-scripts/files/usr/bin/qos-stop	(revision 31220)
+++ package/qos-scripts/files/usr/bin/qos-stop	(working copy)
@@ -1,5 +1,13 @@
 #!/bin/sh
+
+# kill any possibly running qosmon
+killall -q qosmon
+
 for iface in $(tc qdisc show | grep hfsc | awk '{print $5}'); do
 	tc qdisc del dev "$iface" root
 done
 /usr/lib/qos/generate.sh firewall stop | sh
+
+# and just to be sure...
+sleep 1
+killall -q -9 qosmon
Index: package/qos-scripts/files/etc/config/qos
===================================================================
--- package/qos-scripts/files/etc/config/qos	(revision 31220)
+++ package/qos-scripts/files/etc/config/qos	(working copy)
@@ -1,11 +1,17 @@
 # QoS configuration for OpenWrt
 
 # INTERFACES:
-config interface wan
+config interface wlan
 	option classgroup  "Default"
-	option enabled      0
-	option upload       128
-	option download     1024
+	option enabled      1
+	option overhead     0
+	option halfduplex   1
+	option dynamicbw    0
+	option dynamicbwcycle 1000
+	option dynamicbwip  "127.0.0.1"
+	option dynamicbwrtt 25
+	option upload       10000
+	option download     10000
 
 # RULES:
 config classify
@@ -25,6 +31,13 @@
 config reclassify
 	option target       "Priority"
 	option proto        "icmp"
+config reclassify
+	option target       "Priority"
+	option proto        "ospf"
+config reclassify
+	option target       "Priority"
+	option proto        "tcp"
+	option ports        "179"
 config default
 	option target       "Bulk"
 	option portrange    "1024-65535"
@@ -55,9 +68,9 @@
 	option maxsize     400
 	option avgrate     10
 	option priority    20
-config class "Priority_down"
-	option packetsize  1000
-	option avgrate     10
+#config class "Priority_down"
+#	option packetsize  1000
+#	option avgrate     10
 
 
 config class "Express"
@@ -71,8 +84,8 @@
 	option packetdelay 100
 	option avgrate     10
 	option priority    5
-config class "Normal_down"
-	option avgrate     20
+#config class "Normal_down"
+#	option avgrate     20
 
 config class "Bulk"
 	option avgrate     1
Index: package/qos-scripts/src/Makefile
===================================================================
--- package/qos-scripts/src/Makefile	(revision 0)
+++ package/qos-scripts/src/Makefile	(revision 0)
@@ -0,0 +1,33 @@
+BINDIR = /usr/sbin
+TCDIR:=$(BUILD_DIR)/iproute2*
+
+#The ncurses library only needed if we remove the ONLYBG switch
+#below.  Mostly for debug
+#ONLYBGFLAG = -D ONLYBG
+LDLIBS += -lncurses
+
+TCOBJS := $(TCDIR)/tc/tc_util.o
+TCOBJS += $(TCDIR)/tc/tc_core.o
+TCOBJS += $(TCDIR)/tc/q_hfsc.o
+TCOBJS += $(TCDIR)/lib/libnetlink.a
+TCOBJS += $(TCDIR)/lib/libutil.a
+LDFLAGS += -Wl,-export-dynamic
+
+all: qosmon
+
+qosmon: qosmon.o
+	$(CC) $(LDFLAGS) $^ $(TCOBJS) -o $@ $(LDLIBS)
+
+qosmon.o: qosmon.c
+	$(CC) $(ONLYBGFLAG) $(CFLAGS) -I $(TCDIR)/include -I $(TCDIR)/tc -c $^ -o $@
+
+install: all uninstall
+	-mkdir -p $(BINDIR)
+	cp qosmon  $(BINDIR)
+
+uninstall:
+	rm -f $(BINDIR)/qosmon
+
+clean:
+	rm -rf *.o *~ .*sw* qosmon
+
Index: package/qos-scripts/src/qosmon.c
===================================================================
--- package/qos-scripts/src/qosmon.c	(revision 0)
+++ package/qos-scripts/src/qosmon.c	(revision 0)
@@ -0,0 +1,1129 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*  qosmon - An active QoS monitor for gargoyle routers. 
+ *           Created By Paul Bixel
+ *           http://www.gargoyle-router.com
+ *        
+ *  Copyright © 2010 by Paul Bixel <pbix@bigfoot.com>
+ * 
+ *  This file is free software: you may copy, redistribute and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation, either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  This file is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+*/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <errno.h>
+
+#include "SNAPSHOT.h"
+#include "utils.h"
+#include "tc_util.h"
+#include "tc_common.h"
+
+#include <netdb.h>
+#include <signal.h>
+#include <netinet/ip_icmp.h>
+
+#ifndef ONLYBG
+#include <ncurses.h>
+#endif
+
+#define MAXPACKET   100 /* max packet size */
+#define BACKGROUND  3   /* Detact and run in the background */
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN  64
+#endif
+
+//&&&
+#define BW_VAL_INIT	0.9	// initial BW set by qosmon	(default: 90%)
+#define BW_LIM_LOW	0.1	// lowest BW limit set by qosmon  (default: 20%)
+#define BW_LIM_HIGH	0.95	// highest BW limit set by qosmon (default: 90%)
+#define BW_RTT_IGNORE	5	// ignore RTT values > n* last	(default. 5)
+//#define BW_RAMP_DOWN	0.03	// BW reduce speed		(default: 3%)
+//#define BW_RAMP_UP	0.01	// BW increase speed		(default: 0.5%)
+
+#define BW_SLOPE_MIN	0.001
+#define BW_SLOPE_MAX	0.03
+#define BW_SLOPE_OFFSET	1.00	// 100% RTT offset -> BW_SLOPE_MAX
+
+#define BW_UPDATE_THRES	0.01	// new BW applied if delta >	(default: 1%)
+#define BW_MINLOAD_INC	0.20	// min link load to start increasing (default: 95%)
+#define BW_GO_WAIT	0.05	// below this load, WATCH -> WAIT (default: 25%)
+#define BW_GO_WATCH	0.10	// above this load, WAIT -> WATCH (default: 30%)
+#define BW_GO_FREE	0.75	// above this load, WAIT -> FREE  (default: 75%)
+#define BW_RTT_INCREASE	0.7	// below n* avg RTT start raising BW (default: 70%)
+#define BW_CLASS_ACTIVE	1000	// bps to consider a class as active (default: 4000)
+
+u_char  packet[MAXPACKET];
+int pingflags, options;
+int DCAlimit=1;
+char *device="imq0";
+
+#define DEAMON (pingflags & BACKGROUND)
+
+struct rtnl_handle rth;
+
+int s;              /* Socket file descriptor */
+struct hostent *hp; /* Pointer to host info */
+struct timezone tz; /* leftover */
+
+struct sockaddr_in whereto;/* Who to ping */
+int datalen=64-8;   /* How much data */
+
+const char usage[] =
+"Usage:  qosmon [options] pingtime pingtarget bandwidth [pinglimit]\n" 
+"              pingtime   - The ping interval the monitor will use when active in ms.\n"
+"              pingtarget - The URL or IP address of the target host for the monitor.\n"
+"              bandwidth  - The maximum download speed the WAN link will support in kbps.\n"
+"              pinglimit  - Optional pinglimit to use for control, otherwise measured.\n"
+"              Options:\n"
+"                 -b      - Run in the background\n"
+"                 -d imq0 - IMQ device to deal with (default: imq0)\n"
+"                 -x      - Adjust with just 1 active traffic class (default: 2)\n";
+
+char *hostname;
+char hnamebuf[MAXHOSTNAMELEN];
+
+uint16_t ntransmitted = 0;   /* sequence # for outbound packets = #sent */
+uint16_t ident;
+uint16_t nreceived = 0;      /* # of packets we got back */
+
+// For our digital filters we use Y = Y(-1) + alpha * (X - Y(-1))
+// where alpha = Sample_Period / (TC + Sample_Period)
+
+int fil_triptime;           //usec 
+int alpha;                  //Actually alpha * 1000
+int period;                 //PING period In milliseconds
+int rawfltime;              //Trip time in milliseconds
+double slope;               //adaptive slope (%/min)
+
+// Struct of data we keep on our classes
+struct CLASS_STATS {
+   int        ID;          //Class leaf ID
+   __u64      bytes;       //Work bytes last query
+   u_char     backlog;     //Number of packets waiting
+   u_char     actflg;      //True when the class is considered active
+   long int   cbw_flt;     //Class bandwidth subject to filter. (bps)
+};
+
+#define STATCNT 30
+struct CLASS_STATS dnstats[STATCNT];
+struct CLASS_STATS *classptr;
+u_char classcnt;
+u_char errorflg;
+u_char firstflg=1;       //First pass flag
+
+u_char DCA;              //Number of download classes active
+u_char pingon=0;         //Set to one when pinger becomes active.
+int    pinglimit=0;      //Maximum ping time to allow before reacting. 
+
+float BWTC;              //Time constant of the bandwidth filter
+int DBW_UL;              //This the absolute limit of the link passed in as a parameter.
+int dbw_ul;              //This is the last value of the limit sent to the kernel.
+int new_dbw_ul;          //The new link limit proposed by the state machine.
+long int dbw_fil;        //Filtered total download load (bps).
+
+#define QMON_CHK   0
+#define QMON_INIT  1
+#define QMON_WATCH 2
+#define QMON_WAIT  3
+#define QMON_FREE  4
+#define QMON_CHILL 5
+#define QMON_EXIT  6
+char *statename[]= {"CHECK","INIT","WATCH","WAIT","FREE","CHILL","DISABLED"};
+unsigned char qstate=QMON_CHK;
+
+u_short cnt_mismatch=0;
+u_short cnt_errorflg=0;
+u_short last_errorflg=0;
+
+FILE *statusfd;          //Filestream for updating our status to.              
+char sigterm=0;          //Set when we get a signal to terminal   
+int sel_err=0;           //Last error code returned by select
+
+#define DAEMON_NAME "qosmon"
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+
+/* In a world were size is everything we can avoid linking to libm
+   if we can come up with replacements for rint() and ceil().  This will
+   save around 64k of RAM.
+
+   rint() is used in tc_util.c in five places.  By code inspection I can see that
+   the parameter x will always be less than or equal to LONG_MAX so the following
+   simplified rint() will work for us.
+*/
+double rint(double x)
+{
+   long i;
+   if (x > LONG_MAX) i = LONG_MAX; else i = x+.5;
+   return i;
+}
+
+/*  ceil() is used in q_hfsc.c in three places.  There I can see that x is always
+    positive and less than LONG_MAX.  This leads to a much simplified routine.
+*/
+double ceil(double x)
+{
+   long i;
+
+   if (x > LONG_MAX) x = LONG_MAX;
+   i = x;
+   if ((double)i != x) i++;
+   return i;
+}
+
+
+
+/*
+ *          F I N I S H
+ *
+ * Sets a global to cause the main loop to terminate.
+ */
+void finish(int parm)
+{
+    sigterm=parm;
+}
+
+/*
+ *          I N _ C K S U M
+ *
+ * Checksum routine for Internet Protocol family headers (C Version)
+ *
+ */
+int in_cksum(u_short *addr, int len)
+{
+    int nleft = len;
+    u_short *w = addr;
+    u_short answer;
+    int sum = 0;
+
+    /*
+     *  Our algorithm is simple, using a 32 bit accumulator (sum),
+     *  we add sequential 16 bit words to it, and at the end, fold
+     *  back all the carry bits from the top 16 bits into the lower
+     *  16 bits.
+     */
+    while( nleft > 1 )  {
+        sum += *w++;
+        nleft -= 2;
+    }
+
+    /* mop up an odd byte, if necessary */
+    if( nleft == 1 ) {
+        u_short u = 0;
+
+        *(u_char *)(&u) = *(u_char *)w ;
+        sum += u;
+    }
+
+    /*
+     * add back carry outs from top 16 bits to low 16 bits
+     */
+    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+    sum += (sum >> 16);         /* add carry */
+    answer = ~sum;              /* truncate to 16 bits */
+    return (answer);
+}
+
+/*
+ *          P I N G E R
+ * 
+ * Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
+ * will be added on by the kernel.  The ID field is our UNIX process ID,
+ * and the sequence number is an ascending integer.  The first 8 bytes
+ * of the data portion are used to hold a UNIX "timeval" struct in VAX
+ * byte-order, to compute the round-trip time.
+ */
+void pinger(void)
+{
+    static u_char outpack[MAXPACKET];
+    struct icmp *icp = (struct icmp *) outpack;
+    int i, cc;
+    struct timeval *tp = (struct timeval *) &outpack[8];
+    u_char *datap = &outpack[8+sizeof(struct timeval)];
+
+    icp->icmp_type = ICMP_ECHO;
+    icp->icmp_code = 0;
+    icp->icmp_cksum = 0;
+    icp->icmp_seq = ++ntransmitted;
+    icp->icmp_id = ident;       /* ID */
+
+    cc = datalen+8;         /* skips ICMP portion */
+
+    gettimeofday( tp, &tz );
+
+    for( i=8; i<datalen; i++)   /* skip 8 for time */
+        *datap++ = i;
+
+    /* Compute ICMP checksum here */
+    icp->icmp_cksum = in_cksum( (u_short *) icp, cc );
+
+    /* cc = sendto(s, msg, len, flags, to, tolen) */
+    i = sendto( s, outpack, cc, 0, (const struct sockaddr *)  &whereto, sizeof(whereto) );
+    
+}
+
+
+/*
+ *          T V S U B
+ * 
+ * Subtract 2 timeval structs:  out = out - in.
+ * 
+ * Out is assumed to be >= in.
+ */
+void tvsub(register struct timeval *out, register struct timeval *in)
+{
+    if( (out->tv_usec -= in->tv_usec) < 0 )   {
+        out->tv_sec--;
+        out->tv_usec += 1000000;
+    }
+    out->tv_sec -= in->tv_sec;
+}
+
+/*
+ *          P R _ P A C K
+ *
+ * Print out the packet, if it came from us.  This logic is necessary
+ * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
+ * which arrive ('tis only fair).  This permits multiple copies of this
+ * program to be run without having intermingled output (or statistics!).
+ */
+char pr_pack( void *buf, int cc, struct sockaddr_in *from )
+{
+    struct ip *ip;
+    struct icmp *icp;
+    long *lp = (long *) packet;
+    struct timeval tv;
+    struct timeval *tp;
+    int hlen,triptime;
+    struct in_addr tip;
+
+    from->sin_addr.s_addr = ntohl( from->sin_addr.s_addr );
+    gettimeofday( &tv, &tz );
+
+    ip = (struct ip *) buf;
+    hlen = ip->ip_hl << 2;
+    if (cc < hlen + ICMP_MINLEN) {
+        tip.s_addr = ntohl(*(uint32_t *) &from->sin_addr);
+        return 0;
+    }
+    cc -= hlen;
+    icp = (struct icmp *)(buf + hlen);
+    if( icp->icmp_type != ICMP_ECHOREPLY )  {
+        tip.s_addr = ntohl(*(uint32_t *) &from->sin_addr);
+        return 0;
+    }
+
+    if( icp->icmp_id != ident )
+        return 0;           /* 'Twas not our ECHO */
+
+    nreceived++;
+
+    //If it was not the packet we are looking for return now.
+    if (icp->icmp_seq != ntransmitted) return 0;
+    
+    tp = (struct timeval *)&icp->icmp_data[0];
+    tvsub( &tv, tp );
+    triptime = tv.tv_sec*1000+(tv.tv_usec/1000);
+            
+    //We are now ready to update the filtered round trip time.
+    //Check for some possible errors first.
+    if (triptime > period) triptime = period; 
+
+    //If this was the most recent one we sent then update the rawfltime.
+    rawfltime=triptime;
+
+    //return 1 if we got a valid time.
+    return 1;
+
+}
+
+
+//These variables referenced but not used by the tc code we link to.
+int filter_ifindex;
+int use_iec = 0;
+int resolve_hosts = 0;
+
+
+int print_class(const struct sockaddr_nl *who,
+               struct nlmsghdr *n, void *arg)
+{
+    struct tcmsg *t = NLMSG_DATA(n);
+    int len = n->nlmsg_len;
+    struct rtattr * tb[TCA_MAX+1];
+    int leafid;
+    long long work;
+    int actflg;
+
+    if (n->nlmsg_type != RTM_NEWTCLASS && n->nlmsg_type != RTM_DELTCLASS) {
+        fprintf(stderr, "Not a class\n");
+        return 0;
+    }
+    len -= NLMSG_LENGTH(sizeof(*t));
+    if (len < 0) {
+        fprintf(stderr, "Wrong len %d\n", len);
+        return -1;
+    }
+
+    memset(tb, 0, sizeof(tb));
+    parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
+
+    if (tb[TCA_KIND] == NULL) {
+        fprintf(stderr, "print_class: NULL kind\n");
+        return -1;
+    }
+
+    if (n->nlmsg_type == RTM_DELTCLASS) return 0;
+
+    //We only deal with hfsc classes.
+    if (strcmp((char*)RTA_DATA(tb[TCA_KIND]),"hfsc")) return 0;
+ 
+    //Reject the root node
+    if (t->tcm_parent == TC_H_ROOT) return 0;
+
+    //A previous error backs us out.
+    if (errorflg) return 0;
+
+    //If something has changed about the class structure or we reached the 
+    //end of the array we need to reset and back out.
+    if (classcnt >= STATCNT) {
+       errorflg=1;
+       return 0;
+    }
+
+    //Get the leafid or set to -1 if parent.
+    if (t->tcm_info) leafid = t->tcm_info>>16;
+     else leafid = -1;
+
+    //If this is not the first pass and the leafid does not
+    //match then the class list changed so backout.
+    if ((!firstflg) && (leafid != classptr->ID) ) {
+       errorflg=1;
+       return 0;
+    }
+ 
+    //First time through so record the ID.
+    if (firstflg) {
+       classptr->ID = leafid;      
+    }  
+ 
+    //Pickup some hfsc basic stats
+    if (tb[TCA_STATS]) {
+        struct tc_stats st;
+
+        /* handle case where kernel returns more/less than we know about */
+        memset(&st, 0, sizeof(st));
+        memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
+        work = st.bytes;
+        classptr->backlog = st.qlen;
+    } else {
+        errorflg=1;
+        return 0;
+    }
+
+         
+    //Avoid a big jolt on the first pass.
+    if (firstflg) classptr->bytes = work;
+
+    //Update the filtered bandwidth based on what happened unless a rollover occured.
+    actflg=0;
+    if (work >= classptr->bytes) {
+        long int bw;
+        bw = (work - classptr->bytes)*8000/period;  //bps per second x 1000 here
+
+        //Convert back to bps as part of the filter calculation 
+        classptr->cbw_flt=(bw-classptr->cbw_flt)*BWTC/1000+classptr->cbw_flt;
+
+        //A class is considered active if its BW exceeds BW_CLASS_ACTIVE 
+        if ((leafid != -1) && (classptr->cbw_flt > BW_CLASS_ACTIVE)) {DCA++;actflg=1;}
+
+        //Calculate the total link load by adding up all the classes.
+        if (leafid == -1) {
+            dbw_fil = 0;
+        } else {
+            dbw_fil += classptr->cbw_flt;
+        } 
+
+    }
+
+    classptr->bytes = work;
+    classptr->actflg = actflg;
+
+    classptr++;
+    classcnt++;
+    return 0;
+}
+
+/*Gather stats for classes attached to device d */
+int class_list(char *d)
+{
+    struct tcmsg t;
+
+    DCA =0;
+    memset(&t, 0, sizeof(t));
+    t.tcm_family = AF_UNSPEC;
+
+    ll_init_map(&rth);
+
+    if (d[0]) {
+        if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) {
+            fprintf(stderr, "Cannot find device \"%s\"\n", d);
+            return 1;
+        }
+        filter_ifindex = t.tcm_ifindex;
+    }
+
+    if (rtnl_dump_request(&rth, RTM_GETTCLASS, &t, sizeof(t)) < 0) {
+        perror("Cannot send dump request");
+        return 1;
+    }
+
+    if (rtnl_dump_filter(&rth, print_class, stdout, NULL, NULL) < 0) {
+        fprintf(stderr, "Dump terminated\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+
+/*
+ *       tc_class_modify
+ *
+ * This function changes the upper limit rate of the imqx class to match
+ * the rate passed in as the sole parameter.  This is the throttle means
+ * we will use to maintian the QoS performance as the link becomes saturated.
+ *
+ * The structure of this code is gleaned from the source code of 'tc' and is
+ * specific the the gargoyle QoS design.
+ */
+int tc_class_modify(__u32 rate)
+{
+    struct {
+        struct nlmsghdr     n;
+        struct tcmsg        t;
+        char            buf[4096];
+    } req;
+
+    char  k[16];
+    __u32 handle;
+
+    if (dbw_ul == rate) return 0;
+    dbw_ul=rate;
+
+    memset(&req, 0, sizeof(req));
+    memset(k, 0, sizeof(k));
+
+    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
+    req.n.nlmsg_flags = NLM_F_REQUEST;
+    req.n.nlmsg_type = RTM_NEWTCLASS;
+    req.t.tcm_family = AF_UNSPEC;
+
+    //We are only going to modify the upper limit rate of the parent class.
+    if (get_tc_classid(&handle, "1:1")) {
+         fprintf(stderr,"invalid class ID");
+         return 1;
+    }
+    req.t.tcm_handle = handle;
+
+    if (get_tc_classid(&handle, "1:0")) {
+        fprintf(stderr,"invalid parent ID");
+        return 1;
+    }
+    req.t.tcm_parent = handle;
+     
+    strcpy(k,"hsfc");
+    addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
+
+    {
+        struct tc_service_curve usc;
+        struct rtattr *tail;
+
+        memset(&usc, 0, sizeof(usc));
+
+        usc.m2 = rate/8;
+
+        tail = NLMSG_TAIL(&req.n);
+
+        addattr_l(&req.n, 1024, TCA_OPTIONS, NULL, 0);
+        addattr_l(&req.n, 1024, TCA_HFSC_USC, &usc, sizeof(usc));
+
+        tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
+    }
+
+
+    //Communicate our change to the kernel.
+    ll_init_map(&rth);
+
+    if ((req.t.tcm_ifindex = ll_name_to_index(device)) == 0) {
+            fprintf(stderr, "Cannot find device %s\n",device);
+            return 1;
+    }
+
+
+    if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+        return 2;
+
+    return 0;
+}
+
+/*
+    This function is periodically called and updates the
+    status file for the deamon.  The status file can then
+    be viewed by other processes to tell what is going on.
+*/
+void update_status( FILE* fd )
+{
+
+    struct CLASS_STATS *cptr=dnstats;
+    u_char i;
+    char nstr[10];
+    int dbw;
+
+    //Link includes the ping traffic when the pinger is on.
+    if (pingon) dbw = dbw_fil + 64 * 8 * 1000/period;
+           else dbw = dbw_fil; 
+
+    //Update the status file.
+    rewind(fd);
+    ftruncate(fileno(fd), 0);
+    fprintf(fd,"State: %s\n",statename[qstate]);
+    fprintf(fd,"Link limit: %d (kbps)\n",dbw_ul/1000);
+    fprintf(fd,"Fair Link limit: %d (kbps)\n",new_dbw_ul/1000);
+    fprintf(fd,"Link load: %d (kbps)\n",dbw/1000);
+    fprintf(fd,"Adaptive slope: %.2f %%/min\n",slope*100.0);
+
+    if (pingon)
+        fprintf(fd,"Ping: %d (ms)\n",rawfltime);
+    else
+        fprintf(fd,"Ping: off\n");
+
+    fprintf(fd,"Filtered ping: %d (ms)\n",fil_triptime/1000);
+    fprintf(fd,"Ping time limit: %d (ms)\n",pinglimit/1000);
+    fprintf(fd,"Classes Active: %u\n",DCA);
+
+    fprintf(fd,"Errors: (mismatch,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err); 
+	
+
+    i=0;
+    while ((i++<STATCNT) && (cptr->ID != 0)) {
+        fprintf(fd,"ID %4X, Active %u, Backlog %u, BW bps (filtered): %d\n",
+              (short unsigned) cptr->ID,
+              cptr->actflg,
+              cptr->backlog,
+              cptr->cbw_flt);
+        cptr++;
+    }
+
+    fflush(fd);
+
+#ifndef ONLYBG
+    if (DEAMON) return;
+
+    //Home the cursor
+    mvprintw(0,0,"");
+    printw("\nqosmon status\n");
+
+    if (pingon) {
+        sprintf(nstr,"%d",rawfltime);
+    } else {
+        strcpy(nstr,"*");
+    }
+
+    printw("ping (%s/%d) DCA=%d, plim=%d, state=%s\n",nstr,fil_triptime/1000,
+		DCA,pinglimit/1000,statename[qstate]);
+    printw("Link Limit=%6d, Fair Limit=%6d, Current Load=%6d (kbps)\n", 
+		dbw_ul/1000,new_dbw_ul/1000,dbw/1000);
+    printw("pings sent=%d, pings received=%d\n", 
+		ntransmitted,nreceived);
+
+    printw("Defined classes for %s\n",device); 
+    printw("Errors: (mismatches,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err); 
+    cptr=dnstats;
+    i=0; 
+    while ((i++<STATCNT) && (cptr->ID != 0)) {
+        printw("ID %4X, Active %u, Backlog %u, BW (filtered kbps): %d\n",
+              (short unsigned) cptr->ID,
+              cptr->actflg,
+              cptr->backlog,
+              (int) cptr->cbw_flt/1000);
+        cptr++;
+    }
+
+    refresh();
+#endif
+
+}
+
+/*
+ *          M A I N
+ */
+int main(int argc, char *argv[])
+{
+    struct sockaddr_in from;
+    char **av = argv;
+    struct sockaddr_in *to = &whereto;
+    int on = 1;
+    struct protoent *proto;
+    char *statusfile=NULL;
+
+    argc--, av++;
+    while (argc > 0 && *av[0] == '-') {
+        while (*++av[0]) switch (*av[0]) {
+            case 'b':
+                pingflags |= BACKGROUND;
+                break;
+            case 'x':
+                DCAlimit=0;
+                break;
+
+            case 'd':
+                argc--, av++;
+                device=strdup(av[0]);
+                break;
+        }
+        argc--, av++;
+    }
+    if ((argc < 3) || (argc >4))  {
+        printf(usage);
+        exit(1);
+    }
+
+#ifdef ONLYBG
+    if (!(pingflags & BACKGROUND)) {
+        fprintf(stderr, "Must use the -b switch\n", av[0]);
+        exit(1);        
+    }
+#endif
+
+    //The first parameter is the ping time in ms.
+    period = atoi( av[0] );
+    if ((period > 2000) || (period < 100)) {
+        fprintf(stderr, "Invalid ping interval '%s'\n", av[0]);
+        exit(1);        
+    }
+
+    bzero((char *)&whereto, sizeof(whereto) );
+    to->sin_family = AF_INET;
+    to->sin_addr.s_addr = inet_addr(av[1]);
+    if(to->sin_addr.s_addr != (unsigned)-1) {
+        strcpy(hnamebuf, av[1]);
+        hostname = hnamebuf;
+    } else {
+        hp = gethostbyname(av[1]);
+        if (hp) {
+            to->sin_family = hp->h_addrtype;
+            bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
+            hostname = hp->h_name;
+        } else {
+            fprintf(stderr, "%s: unknown host %s\n", argv[1], av[1]);
+            exit(1);
+        }
+    }
+
+    //The third parameter is the maximum download speed in kbps.
+    DBW_UL = atoi( av[2] );
+    if ((DBW_UL < 100) || (DBW_UL >= INT_MAX/1000)) {
+        fprintf(stderr, "Invalid download bandwidth '%s'\n", av[2]);
+        exit(1);        
+    }
+
+    //Convert kbps to bps.
+    dbw_ul = DBW_UL = DBW_UL*1000;
+
+    //The fourth optional parameter is the pinglimit in ms.
+    if (argc == 4) {
+        pinglimit = atoi( av[3] )*1000;
+    }
+
+
+    ident = getpid() & 0xFFFF;
+
+    if ((proto = getprotobyname("icmp")) == NULL) {
+        fprintf(stderr, "icmp: unknown protocol\n");
+        exit(10);
+    }
+
+    // where alpha = Sample_Period / (TC + Sample_Period)
+//&&&    alpha = (period*1000. / (3000. + period)); 
+//&&&xar: faster filter
+    alpha = (period*1000. / (2000. + period)); 
+
+    //Class bandwidth filter time constants  
+    BWTC= (period*1000. / (7500. + period));
+
+    //Check that we have access to tc functions.
+    tc_core_init();
+    if (rtnl_open(&rth, 0) < 0) {
+        fprintf(stderr, "Cannot open rtnetlink\n");
+        exit(1);
+    }
+
+    //Make sure the imqx device is present and that we can scan it.
+    classptr=dnstats;
+    errorflg=0;       
+    class_list(device);
+    if (errorflg) {
+        fprintf(stderr, "Cannot scan ingress device %s\n",device);
+        exit(1);
+    }
+
+    //If running in the background fork()
+    if (DEAMON) {
+
+        /* Ignore most signals in background */  
+        signal( SIGINT,  SIG_IGN );
+        signal( SIGQUIT, SIG_IGN );
+        signal( SIGCHLD, SIG_IGN );
+        signal( SIGALRM, SIG_IGN );
+        signal( SIGUSR1, SIG_IGN );
+        signal( SIGUSR2, SIG_IGN );
+        signal( SIGHUP,  SIG_IGN );
+        signal( SIGTSTP, SIG_IGN );
+        signal( SIGPIPE, (__sighandler_t) finish );
+        signal( SIGSEGV, (__sighandler_t) finish );
+        signal( SIGILL, (__sighandler_t) finish );
+        signal( SIGFPE, (__sighandler_t) finish );
+        signal( SIGSYS, (__sighandler_t) finish );
+        signal( SIGURG, (__sighandler_t) finish );
+        signal( SIGTTIN, (__sighandler_t) finish );
+        signal( SIGTTOU, (__sighandler_t) finish );
+
+    	//daemonize();
+        if ( daemon( 0, 0) < 0 )
+	   	{
+            fprintf(stderr,"deamon() failed with %i\n",errno);
+            exit( 1 );
+	    }
+
+        /* Initialize the logging interface */
+        openlog( DAEMON_NAME, LOG_PID, LOG_LOCAL5 );
+    }
+
+    //SIGTERM is what we expect to kill us.
+    signal( SIGTERM, (__sighandler_t) finish );
+
+    //Create the status file and ping socket
+    //These are called here because the above daemon() call closes
+    //open files.
+    //&&& need unique statusfile name (qosmon.status.device)
+    statusfile=malloc(32);
+    snprintf(statusfile,31,"/tmp/qosmon.status.%s",device);
+    statusfd = fopen(statusfile,"w");
+    s = socket(AF_INET, SOCK_RAW, proto->p_proto);
+
+
+    //Check that things opened correctly.
+    if (DEAMON) {
+        if (statusfd == NULL) {
+            syslog( LOG_CRIT, "Cannot open %s - %i",statusfile,errno );
+            exit(EXIT_FAILURE);
+        }
+  
+        if (s < 0) {
+            syslog( LOG_CRIT, "Cannot open ping socket - %i",errno );
+            exit(EXIT_FAILURE);
+        }
+
+        syslog(LOG_INFO, "starting socketfd = %i, statusfd = %i",s,fileno(statusfd));
+    }
+
+#ifndef ONLYBG
+    else {
+        if (statusfd == NULL) {
+	        fprintf(stderr, "Cannot open %s - %i",statusfile,errno );
+            exit(EXIT_FAILURE);
+        }
+  
+        if (s < 0) {
+	        fprintf( stderr, "Cannot open ping socket - %i",errno );
+            exit(EXIT_FAILURE);
+        }
+
+        //Ctrl-C terminates       
+        signal( SIGINT, (__sighandler_t) finish );
+
+        //Close terminal terminates       
+        signal( SIGHUP, (__sighandler_t) finish );
+
+        setlinebuf( stdout );
+
+        //Bring up ncurses
+        initscr();
+
+    }
+#endif
+
+    //Clear all initial stats.
+    memset((void *)&dnstats,0,sizeof(dnstats));
+
+    //Initialize the fair linklimit to a reasonable number.
+    new_dbw_ul= DBW_UL * BW_VAL_INIT;
+
+    while (!sigterm) {
+        int len = sizeof (packet);
+        socklen_t fromlen = sizeof (from);
+        int cc;
+        u_char chill;
+        struct timeval timeout;
+        fd_set fdmask;
+        FD_ZERO(&fdmask);
+        FD_SET(s , &fdmask);
+
+        //This variable will be set in pr_pack() if we get a pong that matched
+        //our ping, but in case we don't get we initialize to the period.
+        rawfltime=period;
+
+        //Send the next ping
+        if (pingon) pinger();
+        
+        //Wait for the pong(s).
+        timeout.tv_sec = 0;
+        timeout.tv_usec = period*1000;
+    
+        //Need a loop here to clean out any old pongs that show up.
+        while  ( (sel_err=select(s+1, &fdmask, NULL, NULL, &timeout)) == 1 ) {
+        
+              //If we got here then data is waiting. try to read the whole packet
+              if ( (cc=recvfrom(s,packet,len,0,(struct sockaddr *) &from, &fromlen)) < 0) {
+                  continue;
+              }
+              
+              //OK there is a whole packet, get it and record the triptime. 
+              pr_pack( packet, cc, &from );      
+        }
+
+        //If select returns anything other than 1 or 0 then die.
+        if (sel_err) break;
+
+        //Gather new statistics
+        classptr=dnstats;
+        cc=classcnt;
+        classcnt=0;
+        errorflg=0;       
+        class_list(device);
+
+        //If there was an error or the number of classes changed then reset everything
+        if (errorflg || (!firstflg && (cc !=classcnt))) {
+
+            if (errorflg) {cnt_errorflg++; last_errorflg=errorflg;}
+              else if (cc != classcnt) cnt_mismatch++;
+
+            firstflg=1;
+            pingon=0;
+            qstate=QMON_CHK; 
+            continue;
+        }
+
+        //Update the filtered ping response time based on what happened.
+        //If we are not pinging then no change in the filtered value.
+        if (pingon) {
+           //&&&xar eliminate single spikes in RTT time ("Ausreisser")
+           static int lastrawfltime = 0;
+           if (lastrawfltime == 0) {lastrawfltime = rawfltime;}
+           else if (rawfltime > (BW_RTT_IGNORE*lastrawfltime)) {
+              lastrawfltime = rawfltime;
+           } else {
+              lastrawfltime = rawfltime;
+
+              fil_triptime = ((rawfltime*1000 - fil_triptime)*alpha)/1000 + fil_triptime;
+           }
+        }
+
+        //Run the state machine
+        switch (qstate) {
+
+            // Wait to see if the ping targer will respond at all before doing anything
+            case QMON_CHK: 
+                pingon=1;
+
+                //If we get two pings go ahead and lower the link speed.
+                if (nreceived >= 2) {
+
+                    //If the pinglimit was entered on the command line go
+                    //directly to the WATCH state otherwise automatically
+                    //determine an appropriate ping limit.
+                    if (pinglimit) {
+                        dbw_ul=0;  //Forces an update in QMON_WATCH
+                        fil_triptime = rawfltime*1000;
+                        qstate=QMON_WATCH;
+                     } else {
+                         tc_class_modify(DBW_UL/8);
+                         nreceived=0;
+                         qstate=QMON_INIT;
+                     }
+                } 
+                break; 
+
+            // Take a measurement of the practical ping time we can expect in an unsaturated
+            // link.  We do this by making pings and using the filter response after
+            // throttling all traffic in the link.
+            case QMON_INIT:
+                //Wait for seconds then re-initialize the filter.
+                if (nreceived < (7000/period)+1) fil_triptime = rawfltime*1000;
+
+                //After 12 seconds we have measured our ping response entitlement.
+                //Move on to the watch state. 
+                if (nreceived > (12000/period)+1) {
+                    qstate=QMON_WATCH;
+                    dbw_ul=0;  //Forces an update in QMON_WATCH
+
+                    //For simplicity just use a multiple on the measure ping time.
+                    pinglimit = fil_triptime*2.5;
+                    if (pinglimit < 35) pinglimit=35;
+                }
+                break;
+
+            // In the WATCH state we observe ping times as long as the
+            // link remains active.  While we are observing we adjust the 
+            // link upper limit speed to maintain a reasonable ping.
+            // Once the amount of data we are recieving dies down we enter the WAIT state
+            case QMON_WATCH:
+                pingon=1;
+/*&&&xar:
+ * Implement an adaptive slope for raising/lowering the limit.
+ * The slope is governed by the deviation (in %) from the target RTT.
+ *
+ * rttdev = abs(fil_triptime - pinglimit) / pinglimit   ->% offset from target RTT
+ *
+ * slope = slope_min + rttdev *(slope_max - slope_min)  -> slope (in %/min)
+ *
+ * -> calc_slope()
+ */
+/*
+ * calculate dynamic slope
+ */
+{
+    double rttdev;
+#if 0
+//    rttdev = 1.0* abs(fil_triptime - pinglimit) / pinglimit / BW_SLOPE_OFFSET;
+// digital 3% / 0.1% seems to be better (more stable) than a linear slope
+    rttdev = abs(fil_triptime - pinglimit) / pinglimit / BW_SLOPE_OFFSET;
+    if (rttdev > 1) rttdev=1;
+    slope = BW_SLOPE_MIN + rttdev *(BW_SLOPE_MAX - BW_SLOPE_MIN);
+#else
+    rttdev = 1.0* (fil_triptime - pinglimit) / pinglimit;
+    if (rttdev > 0) {
+/* RTT too large */
+        if      (rttdev < 0.50)  { slope = BW_SLOPE_MIN; }
+        else if (rttdev < 2)     { slope = (BW_SLOPE_MAX + BW_SLOPE_MIN)/2; }
+        else                     { slope = BW_SLOPE_MAX; }
+    } else if (rttdev < 0) {
+/* RTT smaller than target */
+        if      (rttdev > -0.5)  { slope = BW_SLOPE_MIN; }
+        else if (rttdev > -0.75) { slope = (BW_SLOPE_MAX + BW_SLOPE_MIN)/2; }
+        else                     { slope = BW_SLOPE_MAX; }
+    } else { slope = 0; }
+#endif
+}
+
+                //Ping times too long then ramp down at BW_RAMP_DOWN/sec 
+                //Repond in this direction quickly to restore performance fast.
+                if (fil_triptime > pinglimit) {
+//&&&                   new_dbw_ul = new_dbw_ul * (1.0 - BW_RAMP_DOWN * period/1000);
+                   new_dbw_ul = new_dbw_ul * (1.0 - slope * period/1000);
+                   if (new_dbw_ul < DBW_UL*BW_LIM_LOW) new_dbw_ul=DBW_UL*BW_LIM_LOW;
+                }
+
+                //Ping times acceptable then ramp up at BW_RAMP_UP/sec 
+                //Try to creep up on the limit to avoid oscillation.
+                //Only increase the download bw if the link load indicates its needed.
+                if ((fil_triptime < BW_RTT_INCREASE * pinglimit) && (dbw_fil > new_dbw_ul * BW_MINLOAD_INC)) {
+//&&&                   new_dbw_ul = new_dbw_ul * (1.0 + BW_RAMP_UP * period/1000);
+                   new_dbw_ul = new_dbw_ul * (1.0 + slope * period/1000);
+                   if (new_dbw_ul > DBW_UL*BW_LIM_HIGH) new_dbw_ul=DBW_UL*BW_LIM_HIGH;
+                }
+
+                //Modify parent download limit as needed.
+                if (abs(dbw_ul-new_dbw_ul) > BW_UPDATE_THRES*DBW_UL) tc_class_modify(new_dbw_ul);
+
+                if ((dbw_fil < BW_GO_WAIT * new_dbw_ul) || (DCA <= DCAlimit) ) qstate=QMON_WAIT;
+                break;
+                    
+            // In the wait state we have a nearly idle link or only one class active.
+            // In these cases it is not necessary to monitor delay times so the active
+            // ping is disabled.
+            case QMON_WAIT:
+                pingon=0;
+                if ((DCA > DCAlimit) && (dbw_fil > BW_GO_WATCH * new_dbw_ul)) qstate=QMON_WATCH;
+                else if ((DCA <= 1) && (dbw_fil > BW_GO_FREE * new_dbw_ul)) {
+                    qstate=QMON_FREE;
+                    tc_class_modify(DBW_UL);
+                }
+                break;
+                      
+            // In the free state we are relaxing the upper limit on the link because
+            // only once class is active and we want to maximize our throughput.
+            // If a second class becomes active we need to return to the watch state
+            // and enforce the upper limit that we last observed to maintain our ping
+            // times.
+            case QMON_FREE:
+                if (DCA>DCAlimit) {
+                    qstate=QMON_CHILL;
+                    tc_class_modify(new_dbw_ul);
+                    chill=(2000/period)+1;
+                }
+                break;
+
+            //Coming out of the FREE state we need to give some time for the downlink
+            //to respond to our class_modify before we begin monitoring again
+            case QMON_CHILL:
+                if (chill-- <= 0) {
+                    qstate=QMON_WATCH;
+                    pingon=1;
+                } 
+                break;
+        }
+
+        update_status(statusfd);
+
+        //If we get here the first pass is over. 
+        firstflg=0;
+ 
+    }  //Next ping
+
+
+    qstate=QMON_EXIT;
+
+    //We got a signal to terminate so start by restoring the root TC class to
+    //the original upper limit.
+    tc_class_modify(DBW_UL);
+    
+    update_status(statusfd);
+
+    //Write a message in the system log
+    if (DEAMON) {
+      syslog( LOG_NOTICE, "terminated sigterm=%i, sel_err=%i", sigterm, sel_err );
+      closelog();
+    } 
+
+#ifndef ONLYBG
+    else { 
+      endwin();
+      fflush(stdout);
+    }
+#endif
+
+}
+
Index: package/qos-scripts/Makefile
===================================================================
--- package/qos-scripts/Makefile	(revision 31220)
+++ package/qos-scripts/Makefile	(working copy)
@@ -9,7 +9,7 @@
 
 PKG_NAME:=qos-scripts
 PKG_VERSION:=1.2.1
-PKG_RELEASE:=3.2
+PKG_RELEASE:=3.2xar
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 
@@ -18,7 +18,7 @@
 define Package/qos-scripts
   SECTION:=utils
   CATEGORY:=Base system
-  DEPENDS:=+tc +kmod-sched +iptables +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra +iptables-mod-imq
+  DEPENDS:=+tc +kmod-sched +iptables +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra +iptables-mod-imq +libncurses
   TITLE:=QoS scripts
   PKGARCH:=all
 endef
@@ -34,17 +34,29 @@
 endef
 
 define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+	$(CP) ./src/* $(PKG_BUILD_DIR)/
 endef
 
 define Build/Configure
 endef
 
 define Build/Compile
+	-$(MAKE) -C $(PKG_BUILD_DIR) clean
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+	$(TARGET_CONFIGURE_OPTS) \
+	CFLAGS="$(TARGET_CFLAGS) -I $(STAGING_DIR)/usr/include" \
+	LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib" \
+	BUILD_DIR="$(BUILD_DIR)" \
+	all
 endef
 
 define Package/qos-scripts/install
 	$(INSTALL_DIR) $(1)
 	$(CP) ./files/* $(1)/
+
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/qosmon $(1)/usr/sbin/qosmon
 endef
 
 $(eval $(call BuildPackage,qos-scripts))
Index: package/block-mount/files/fstab.config
===================================================================
--- package/block-mount/files/fstab.config	(revision 31220)
+++ package/block-mount/files/fstab.config	(working copy)
@@ -8,13 +8,13 @@
 	
 config mount
 	option target	/home
-	option device	/dev/sda1
+	option device	/dev/sdc1
 	option fstype	ext3
 	option options	rw,sync
 	option enabled	0
 	option enabled_fsck 0
 
 config swap
-	option device	/dev/sda2
+	option device	/dev/sdc2
 	option enabled	0
 
Index: package/hostapd/files/wpa_supplicant.sh
===================================================================
--- package/hostapd/files/wpa_supplicant.sh	(revision 31220)
+++ package/hostapd/files/wpa_supplicant.sh	(working copy)
@@ -117,6 +117,7 @@
 	config_get ssid "$vif" ssid
 	config_get bssid "$vif" bssid
 	bssid=${bssid:+"bssid=$bssid"}
+	[ "$proto" != "" ] && proto1="proto=$proto" || proto1=""
 	rm -rf /var/run/wpa_supplicant-$ifname
 	cat > /var/run/wpa_supplicant-$ifname.conf <<EOF
 ctrl_interface=/var/run/wpa_supplicant-$ifname
@@ -125,7 +126,7 @@
 	ssid="$ssid"
 	$bssid
 	key_mgmt=$key_mgmt
-	$proto
+	$proto1
 	$ieee80211w
 	$passphrase
 	$pairwise
@@ -144,6 +145,8 @@
 	$wep_tx_keyidx
 }
 EOF
-	[ -z "$proto" -a "$key_mgmt" != "NONE" ] || \
+#&&& start wpa_supplicant in any case - non-encrypted connection just means 
+#&&& that wpa_supplicant has to take care of automatic reassociating
+#&&&	[ -z "$proto" -a "$key_mgmt" != "NONE" ] || \
 		wpa_supplicant ${bridge:+ -b $bridge} -B -P "/var/run/wifi-${ifname}.pid" -D ${driver:-wext} -i "$ifname" -c /var/run/wpa_supplicant-$ifname.conf $options
 }
Index: package/base-files/files/etc/openwrt_release
===================================================================
--- package/base-files/files/etc/openwrt_release	(revision 31220)
+++ package/base-files/files/etc/openwrt_release	(working copy)
@@ -1,4 +1,4 @@
 DISTRIB_ID="OpenWrt"
-DISTRIB_RELEASE="10.03.1"
+DISTRIB_RELEASE="10.03.1 HAMNET-R2.0"
 DISTRIB_CODENAME="backfire"
-DISTRIB_DESCRIPTION="OpenWrt Backfire 10.03.1"
+DISTRIB_DESCRIPTION="HAMNET-R2.0 OpenWrt Backfire 10.03.1"
Index: package/base-files/files/etc/profile
===================================================================
--- package/base-files/files/etc/profile	(revision 31220)
+++ package/base-files/files/etc/profile	(working copy)
@@ -13,3 +13,5 @@
 
 [ -x /usr/bin/arp ] || arp() { cat /proc/net/arp; }
 [ -z /bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
+
+alias ll='ls -al'
Index: package/base-files/files/etc/config/system
===================================================================
--- package/base-files/files/etc/config/system	(revision 31220)
+++ package/base-files/files/etc/config/system	(working copy)
@@ -2,8 +2,8 @@
 	option hostname	OpenWrt
 	option timezone	UTC
 
-config timeserver ntp
-	list server	0.openwrt.pool.ntp.org
-	list server	1.openwrt.pool.ntp.org
-	list server	2.openwrt.pool.ntp.org
-	list server	3.openwrt.pool.ntp.org
+config 'led'
+	option 'name' 'Heartbeat'
+	option 'sysfs' 'alix:1'
+	option 'trigger' 'heartbeat'
+
Index: package/base-files/files/etc/config/network
===================================================================
--- package/base-files/files/etc/config/network	(revision 31220)
+++ package/base-files/files/etc/config/network	(working copy)
@@ -7,8 +7,14 @@
 	option netmask	255.0.0.0
 
 config interface lan
-	option ifname	eth0
-	option type 	bridge
-	option proto	static
-	option ipaddr	192.168.1.1
-	option netmask	255.255.255.0
+	option type     bridge
+	option ifname   "eth0 eth1"
+	option proto    dhcp
+#	option ipaddr   192.168.101.1
+#	option netmask  255.255.255.0
+	option stp      1
+
+config interface wlan
+	option proto    static
+	option ipaddr   10.0.0.1
+	option netmask  255.255.255.0
Index: package/base-files/files/etc/banner
===================================================================
--- package/base-files/files/etc/banner	(revision 31220)
+++ package/base-files/files/etc/banner	(working copy)
@@ -3,8 +3,5 @@
  |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
  |_______||   __|_____|__|__||________||__|  |____|
           |__| W I R E L E S S   F R E E D O M
- Backfire (10.03.1, $R) ------------------------
-  * 1/3 shot Kahlua    In a shot glass, layer Kahlua 
-  * 1/3 shot Bailey's  on the bottom, then Bailey's, 
-  * 1/3 shot Vodka     then Vodka.
- ---------------------------------------------------
+ Backfire (10.03.1, $R) -- ALIX 4 HAMNET R2.0
+ --------------------------------------------------
Index: package/base-files/files/etc/sysctl.conf
===================================================================
--- package/base-files/files/etc/sysctl.conf	(revision 31220)
+++ package/base-files/files/etc/sysctl.conf	(working copy)
@@ -21,3 +21,7 @@
 net.bridge.bridge-nf-call-arptables=0
 net.bridge.bridge-nf-call-ip6tables=0
 net.bridge.bridge-nf-call-iptables=0
+
+# HAMNET: disable IPV6 by default on all interfaces
+net.ipv6.conf.all.disable_ipv6=1
+
Index: package/opkg/files/opkg.conf
===================================================================
--- package/opkg/files/opkg.conf	(revision 31220)
+++ package/opkg/files/opkg.conf	(working copy)
@@ -1,4 +1,5 @@
-src/gz packages http://downloads.openwrt.org/backfire/10.03.1/$S/packages
+src/gz packages http://hamnet.tuxworld.ch/download/images_Alix/backfire_10.03.1_HAMNET-R2.0/packages
+src/gz updates  http://hamnet.tuxworld.ch/download/images_Alix/backfire_10.03.1_HAMNET-R2.0/updates
 dest root /
 dest ram /tmp
 lists_dir ext /var/opkg-lists
Index: package/dnsmasq/files/dhcp.conf
===================================================================
--- package/dnsmasq/files/dhcp.conf	(revision 31220)
+++ package/dnsmasq/files/dhcp.conf	(working copy)
@@ -22,9 +22,7 @@
 
 config dhcp lan
 	option interface	lan
-	option start 	100
-	option limit	150
-	option leasetime	12h
+	option ignore	1
 
 config dhcp wan
 	option interface	wan
Index: package/crda/Makefile
===================================================================
--- package/crda/Makefile	(revision 31220)
+++ package/crda/Makefile	(working copy)
@@ -60,6 +60,10 @@
 	NLLIBS="-lnl-tiny -lm" \
 	REG_BIN="$(DL_DIR)/$(PKG_REGULATORY_SOURCE)" \
 	crda
+#&&&
+define Build/Configure
+	cp files/HAMNET_OWRT.key.pub.pem $(PKG_BUILD_DIR)/pubkeys/
+endef
 
 define Package/crda/install
 	$(INSTALL_DIR) $(1)/sbin
@@ -68,7 +72,8 @@
 	$(INSTALL_DIR) $(1)/usr/lib/crda
 	$(INSTALL_BIN) $(PKG_BUILD_DIR)/crda $(1)/sbin/
 	$(INSTALL_DATA) ./files/hotplug.rule $(1)/etc/hotplug.d/platform/10-regulatory
-	$(INSTALL_DATA) $(DL_DIR)/$(PKG_REGULATORY_SOURCE) $(1)/usr/lib/crda/regulatory.bin
+#&&&	$(INSTALL_DATA) $(DL_DIR)/$(PKG_REGULATORY_SOURCE) $(1)/usr/lib/crda/regulatory.bin
+	$(INSTALL_DATA) ./files/regulatory.bin $(1)/usr/lib/crda/regulatory.bin
 endef
 
 $(eval $(call BuildPackage,crda))
Index: package/kernel/modules/other.mk
===================================================================
--- package/kernel/modules/other.mk	(revision 31220)
+++ package/kernel/modules/other.mk	(working copy)
@@ -425,6 +425,22 @@
 
 $(eval $(call KernelPackage,softdog))
 
+
+define KernelPackage/geode-wdt
+  SUBMENU:=$(OTHER_MENU)
+  TITLE:=Geode watchdog driver
+  KCONFIG:=CONFIG_GEODE_WDT
+  FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/geodewdt.$(LINUX_KMOD_SUFFIX)
+  AUTOLOAD:=$(call AutoLoad,50,geodewdt)
+endef
+
+define KernelPackage/geode-wdt/description
+ Geode Hardware watchdog driver
+endef
+
+$(eval $(call KernelPackage,geode-wdt))
+
+
 define KernelPackage/rdc321x-wdt
   SUBMENU:=$(OTHER_MENU)
   TITLE:=RDC321x watchdog
Index: package/iwinfo/src/iwinfo_lib.c
===================================================================
--- package/iwinfo/src/iwinfo_lib.c	(revision 31220)
+++ package/iwinfo/src/iwinfo_lib.c	(working copy)
@@ -51,6 +51,9 @@
 
 const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[] = {
 	{ 0x3030 /* 00 */, "World" },
+	{ 0x5841 /* XA */, "HAMNET HB9" },
+	{ 0x5844 /* XD */, "HAMNET DL" },
+	{ 0x5858 /* Xx */, "HAMNET Testing" },
 	{ 0x4144 /* AD */, "Andorra" },
 	{ 0x4145 /* AE */, "United Arab Emirates" },
 	{ 0x4146 /* AF */, "Afghanistan" },
Index: package/mac80211/files/lib/wifi/mac80211.sh
===================================================================
--- package/mac80211/files/lib/wifi/mac80211.sh	(revision 31220)
+++ package/mac80211/files/lib/wifi/mac80211.sh	(working copy)
@@ -1,5 +1,6 @@
 #!/bin/sh
-append DRIVERS "mac80211"
+#&&& HAMNET: don't use vanilla 80211
+#&&& append DRIVERS "mac80211"
 
 mac80211_hostapd_setup_base() {
 	local phy="$1"
Index: package/busybox/patches/9999-xar_unlinktruncate.patch
===================================================================
--- package/busybox/patches/9999-xar_unlinktruncate.patch	(revision 0)
+++ package/busybox/patches/9999-xar_unlinktruncate.patch	(revision 0)
@@ -0,0 +1,14 @@
+--- busybox-1.15.3/libbb/remove_file.c.orig	2012-04-03 19:50:35.000000000 +0200
++++ busybox-1.15.3/libbb/remove_file.c	2012-04-03 19:50:39.000000000 +0200
+@@ -93,6 +93,11 @@
+ 			return 0;
+ 	}
+ 
++/*&&&+++*/
++	if (truncate(path, 0) < 0) {
++		//bb_perror_msg("cannot truncate '%s'", path);
++	}
++/*&&&---*/
+ 	if (unlink(path) < 0) {
+ 		bb_perror_msg("cannot remove '%s'", path);
+ 		return -1;
Index: package/busybox/Makefile
===================================================================
--- package/busybox/Makefile	(revision 31220)
+++ package/busybox/Makefile	(working copy)
@@ -74,6 +74,9 @@
 		ARCH="$(ARCH)" \
 		CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \
 		install
+	#&&& disable 'halt' and 'poweroff'
+	rm -f $(PKG_INSTALL_DIR)/sbin/halt
+	rm -f $(PKG_INSTALL_DIR)/sbin/poweroff
 endef
 
 define Package/busybox/install
Index: package/firewall/files/firewall.config
===================================================================
--- package/firewall/files/firewall.config	(revision 31220)
+++ package/firewall/files/firewall.config	(working copy)
@@ -2,7 +2,7 @@
 	option syn_flood	1
 	option input		ACCEPT
 	option output		ACCEPT 
-	option forward		REJECT
+	option forward		ACCEPT
 # Uncomment this line to disable ipv6 rules
 #	option disable_ipv6	1
 
@@ -11,85 +11,86 @@
 	option network		'lan'
 	option input		ACCEPT 
 	option output		ACCEPT 
-	option forward		REJECT
+	option forward		ACCEPT
 
 config zone
-	option name		wan
-	option network		'wan'
-	option input		REJECT
+	option name		wlan
+	option network		'wlan'
+	option input		ACCEPT
 	option output		ACCEPT 
-	option forward		REJECT
-	option masq		1 
-	option mtu_fix		1
+	option forward		ACCEPT
+	option masq		0
+	option mtu_fix		0
 
 config forwarding 
 	option src      	lan
-	option dest     	wan
+	option dest     	wlan
 
 # We need to accept udp packets on port 68,
 # see https://dev.openwrt.org/ticket/4108
-config rule
-	option name		Allow-DHCP-Renew
-	option src		wan
-	option proto		udp
-	option dest_port	68
-	option target		ACCEPT
-	option family		ipv4
+#&&& no DHCP client used on HAMNET routers
+#config rule
+#	option name		Allow-DHCP-Renew
+#	option src		wlan
+#	option proto		udp
+#	option dest_port	68
+#	option target		ACCEPT
+#	option family		ipv4
 
 # Allow IPv4 ping
-config rule
-	option name		Allow-Ping
-	option src		wan
-	option proto		icmp
-	option icmp_type	echo-request
-	option family		ipv4
-	option target		ACCEPT
+#config rule
+#	option name		Allow-Ping
+#	option src		wlan
+#	option proto		icmp
+#	option icmp_type	echo-request
+#	option family		ipv4
+#	option target		ACCEPT
 
 # Allow DHCPv6 replies
 # see https://dev.openwrt.org/ticket/10381
-config rule
-	option name		Allow-DHCPv6
-	option src		wan
-	option proto		udp
-	option src_ip		fe80::/10
-	option src_port		547
-	option dest_ip		fe80::/10
-	option dest_port	546
-	option family		ipv6
-	option target		ACCEPT
+#config rule
+#	option name		Allow-DHCPv6
+#	option src		wlan
+#	option proto		udp
+#	option src_ip		fe80::/10
+#	option src_port		547
+#	option dest_ip		fe80::/10
+#	option dest_port	546
+#	option family		ipv6
+#	option target		ACCEPT
 
 # Allow essential incoming IPv6 ICMP traffic
-config rule
-	option name		Allow-ICMPv6-Input
-	option src		wan
-	option proto	icmp
-	list icmp_type		echo-request
-	list icmp_type		destination-unreachable
-	list icmp_type		packet-too-big
-	list icmp_type		time-exceeded
-	list icmp_type		bad-header
-	list icmp_type		unknown-header-type
-	list icmp_type		router-solicitation
-	list icmp_type		neighbour-solicitation
-	option limit		1000/sec
-	option family		ipv6
-	option target		ACCEPT
+#config rule
+#	option name		Allow-ICMPv6-Input
+#	option src		wlan
+#	option proto	icmp
+#	list icmp_type		echo-request
+#	list icmp_type		destination-unreachable
+#	list icmp_type		packet-too-big
+#	list icmp_type		time-exceeded
+#	list icmp_type		bad-header
+#	list icmp_type		unknown-header-type
+#	list icmp_type		router-solicitation
+#	list icmp_type		neighbour-solicitation
+#	option limit		1000/sec
+#	option family		ipv6
+#	option target		ACCEPT
 
 # Allow essential forwarded IPv6 ICMP traffic
-config rule                                   
-	option name		Allow-ICMPv6-Forward
-	option src		wan
-	option dest		*
-	option proto		icmp
-	list icmp_type		echo-request
-	list icmp_type		destination-unreachable
-	list icmp_type		packet-too-big
-	list icmp_type		time-exceeded
-	list icmp_type		bad-header
-	list icmp_type		unknown-header-type
-	option limit		1000/sec
-	option family		ipv6
-	option target		ACCEPT
+#config rule                                   
+#	option name		Allow-ICMPv6-Forward
+#	option src		wlan
+#	option dest		*
+#	option proto		icmp
+#	list icmp_type		echo-request
+#	list icmp_type		destination-unreachable
+#	list icmp_type		packet-too-big
+#	list icmp_type		time-exceeded
+#	list icmp_type		bad-header
+#	list icmp_type		unknown-header-type
+#	option limit		1000/sec
+#	option family		ipv6
+#	option target		ACCEPT
 
 # include a file with users custom iptables rules
 config include
@@ -97,17 +98,17 @@
 
 
 ### EXAMPLE CONFIG SECTIONS
-# do not allow a specific ip to access wan
+# do not allow a specific ip to access wlan
 #config rule
 #	option src		lan
 #	option src_ip	192.168.45.2
-#	option dest		wan
+#	option dest		wlan
 #	option proto	tcp
 #	option target	REJECT 
 
-# block a specific mac on wan
+# block a specific mac on wlan
 #config rule
-#	option dest		wan
+#	option dest		wlan
 #	option src_mac	00:11:22:33:44:66
 #	option target	REJECT 
 
@@ -117,9 +118,9 @@
 #	option proto	ICMP
 #	option target	DROP
 
-# port redirect port coming in on wan to lan
+# port redirect port coming in on wlan to lan
 #config redirect
-#	option src			wan
+#	option src			wlan
 #	option src_dport	80
 #	option dest			lan
 #	option dest_ip		192.168.16.235
@@ -133,7 +134,7 @@
 #	option src_ip	192.168.45.2
 #	option src_mac	00:11:22:33:44:55
 #	option src_port	80
-#	option dest		wan
+#	option dest		wlan
 #	option dest_ip	194.25.2.129
 #	option dest_port	120
 #	option proto	tcp
