Re: Patch to allow for the ATM "cell tax"

Linux Advanced Routing and Traffic Control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Thu, 2006-03-02 at 15:49 +0000, Andy Furniss wrote:
> Russell Stuart wrote:
> 
> > The following patch to tc allows it to perform an exact
> > ATM / ADSL rate calculation.
> 
> I probably haven't read the patch properly - but I don't think you can 
> do it exactly without patching net/sched/sched_htb.c aswell.
> Specifically you need to add overhead - 1 before htb shifts the length 
> to get the slot num (-1 because you need to get 48 and 49 payload length 
> to map to different slots 47 and 48 do). The table should be filled 
> according to this.

As Markus mentioned in another post on this thread, Jesper Dangaard
Brouer (http://www.adsl-optimizer.dk) has already written an iproute2
and Linux kernel patch that implements the above. ATM cell alignment is
done in tc_core.c, and the per packet overhead is passed to the relevant
kernel modules.

I have made some very minor changes to the patches, so that they apply
cleanly to iproute2-20051007 and kernel 2.6.15. You will find them
attached to this mail.

> > When using this command lines, you always specify the ADSL
> > link capacity as quoted by the modem.  Eg, if you are
> > controlling incoming traffic on a 512k/128k link, you
> > specify the link speed as 512000bps.
> 
> You need to look at the atm user rate shown by your modem, for me in the 
> past it was 288/576 this was sold as 250/500 by teleco and 256/512 by isp.
> 
> You also need to back off a couple of kbit (egress - ingress more for 
> different reasons) - one of my modems does cell qos bases on rate of 
> whole cells/sec - don't kmow how common that is. Also if you run exactly 
> on the rate and queue formed when starting/restarting scripts it would 
> not drain till the traffic stopped.

Setting the MTU to 1478 is probably a good idea to prevent excessive
cell usage. Reasoning behind this being: 1488 is the largest multiple of
48 under 1500, less 2 bytes for the PPP header and 8 for the AAL5
footer.

Perhaps you can confirm this isn't way off the mark Andy? :)

-- 
Adam James <ad@xxxxxxxxxxxxxxxx>
diff -Naur -p iproute-20051007.orig/include/linux/pkt_sched.h iproute-20051007.overhead/include/linux/pkt_sched.h
--- iproute-20051007.orig/include/linux/pkt_sched.h	2006-02-15 23:04:06.000000000 +0000
+++ iproute-20051007.overhead/include/linux/pkt_sched.h	2006-02-15 23:03:28.000000000 +0000
@@ -82,7 +82,7 @@ struct tc_ratespec
 	unsigned char	cell_log;
 	unsigned char	__reserved;
 	unsigned short	feature;
-	short		addend;
+	unsigned short	overhead;
 	unsigned short	mpu;
 	__u32		rate;
 };
@@ -484,7 +484,7 @@ struct tc_ratespec
 	unsigned char	cell_log;
 	unsigned char	__reserved;
 	unsigned short	feature;
-	short		addend;
+	unsigned short	overhead;
 	unsigned short	mpu;
 	__u32		rate;
 };
diff -Naur -p iproute-20051007.orig/tc/q_htb.c iproute-20051007.overhead/tc/q_htb.c
--- iproute-20051007.orig/tc/q_htb.c	2006-02-15 23:04:06.000000000 +0000
+++ iproute-20051007.overhead/tc/q_htb.c	2006-02-15 23:03:28.000000000 +0000
@@ -350,6 +350,9 @@ static void explain(void)
 		" mpu      minimum packet size used in rate computations\n"
 		" overhead per-packet size overhead used in rate computations\n"
 
+		" cell_size    used to calculate ATM SAR overhead \n"
+		" cell_payload (SAR = segmentation and reassembly) \n"
+
 		" ceil     definite upper class rate (no borrows) {rate}\n"
 		" cburst   burst but for ceil {computed}\n"
 		" mtu      max packet size we create rate map for {1600}\n"
@@ -416,7 +419,9 @@ static int htb_parse_class_opt(struct qd
 	unsigned buffer=0,cbuffer=0;
 	int cell_log=-1,ccell_log = -1;
 	unsigned mtu, mpu;
-	unsigned char mpu8 = 0, overhead = 0;
+	unsigned short cell_size, cell_payload;
+	unsigned char mpu8 = 0;
+	unsigned short overhead = 0;
 	struct rtattr *tail;
 
 	memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
@@ -440,7 +445,7 @@ static int htb_parse_class_opt(struct qd
 			}
 		} else if (matches(*argv, "overhead") == 0) {
 			NEXT_ARG();
-			if (get_u8(&overhead, *argv, 10)) {
+			if (get_u16(&overhead, *argv, 10)) {
 				explain1("overhead"); return -1;
 			}
 		} else if (matches(*argv, "quantum") == 0) {
@@ -448,6 +453,16 @@ static int htb_parse_class_opt(struct qd
 			if (get_u32(&opt.quantum, *argv, 10)) {
 				explain1("quantum"); return -1;
 			}
+		} else if (matches(*argv, "cell_size") == 0) {
+			NEXT_ARG();
+			if (get_u16(&cell_size, *argv, 10)) {
+				explain1("cell_size"); return -1;
+			}
+		} else if (matches(*argv, "cell_payload") == 0) {
+			NEXT_ARG();
+			if (get_u16(&cell_payload, *argv, 10)) {
+				explain1("cell_payload"); return -1;
+			}
 		} else if (matches(*argv, "burst") == 0 ||
 			strcmp(*argv, "buffer") == 0 ||
 			strcmp(*argv, "maxburst") == 0) {
@@ -513,10 +528,11 @@ static int htb_parse_class_opt(struct qd
 	   sute that buffer is larger than mtu and to have some safeguard space */
 	if (!buffer) buffer = opt.rate.rate / get_hz() + mtu;
 	if (!cbuffer) cbuffer = opt.ceil.rate / get_hz() + mtu;
-
+	
+	opt.ceil.mpu = mpu8; opt.rate.mpu = mpu8;
+	opt.ceil.overhead = overhead; opt.rate.overhead = overhead;
 /* encode overhead and mpu, 8 bits each, into lower 16 bits */
 	mpu = (unsigned)mpu8 | (unsigned)overhead << 8;
-	opt.ceil.mpu = mpu; opt.rate.mpu = mpu;
 
 	if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, mpu)) < 0) {
 		fprintf(stderr, "htb: failed to calculate rate table.\n");
@@ -579,8 +595,8 @@ static int htb_print_opt(struct qdisc_ut
 		fprintf(f, "cburst %s/%u mpu %s overhead %s ",
 			sprint_size(cbuffer, b1),
 			1<<hopt->ceil.cell_log,
-			sprint_size(hopt->ceil.mpu&0xFF, b2),
-			sprint_size((hopt->ceil.mpu>>8)&0xFF, b3));
+			sprint_size(hopt->ceil.mpu, b2),
+			sprint_size(hopt->ceil.overhead, b3));
 		fprintf(f, "level %d ", (int)hopt->level);
 	    } else {
 		fprintf(f, "burst %s ", sprint_size(buffer, b1));
diff -Naur -p iproute-20051007.orig/tc/tc_core.c iproute-20051007.overhead/tc/tc_core.c
--- iproute-20051007.orig/tc/tc_core.c	2004-07-30 21:26:15.000000000 +0100
+++ iproute-20051007.overhead/tc/tc_core.c	2006-02-15 23:03:28.000000000 +0000
@@ -42,6 +42,35 @@ unsigned tc_calc_xmittime(unsigned rate,
 	return tc_core_usec2tick(1000000*((double)size/rate));
 }
 
+#ifndef ATM_CELL_SIZE
+#define ATM_CELL_SIZE               53  /* ATM cell size incl. header */
+#endif
+#ifndef ATM_CELL_PAYLOAD
+#define ATM_CELL_PAYLOAD            48  /* ATM payload size */
+#endif
+
+#define ATM_ALIGN y
+
+/*
+ The align_to_cells is used for determining the (ATM) SAR alignment
+ overhead at the ATM layer. (SAR = Segmentation And Reassembly)
+ This is for example needed when scheduling packet on an ADSL
+ connection.  The ATM-AAL overhead should preferably be added in the
+ kernel when doing table lookups (due to precision/alignment of the
+ table), if not the ATM-AAL overhead should be added to the size
+ before calling the function.  --Hawk, d.7/11-2004. <hawk@xxxxxxx>
+ */
+unsigned tc_align_to_cells(unsigned size, int cell_size, int cell_payload) 
+{
+  int linksize, cells;
+  cells = size / cell_payload;
+  if ((size % cell_payload) > 0) {
+    cells++;
+  }
+  linksize = cells * cell_size;
+  return linksize;
+}
+
 /*
    rtab[pkt_len>>cell_log] = pkt_xmit_time
  */
@@ -62,11 +91,16 @@ int tc_calc_rtable(unsigned bps, __u32 *
 			cell_log++;
 	}
 	for (i=0; i<256; i++) {
-		unsigned sz = (i<<cell_log);
-		if (overhead)
-			sz += overhead;
+		unsigned sz = ((i+1)<<cell_log);
+		if (overhead) {
+			// Is now done in the kernel (eg. sch_htb.c, func L2T )
+			// sz += overhead; 
+		}
 		if (sz < mpu)
 			sz = mpu;
+#ifdef ATM_ALIGN
+		sz = tc_align_to_cells(sz, ATM_CELL_SIZE, ATM_CELL_PAYLOAD);
+#endif
 		rtab[i] = tc_core_usec2tick(1000000*((double)sz/bps));
 	}
 	return cell_log;
diff -Naur -p linux-source-2.6.15.orig/include/linux/pkt_sched.h linux-source-2.6.15.overhead/include/linux/pkt_sched.h
--- linux-source-2.6.15.orig/include/linux/pkt_sched.h	2006-01-03 03:21:10.000000000 +0000
+++ linux-source-2.6.15.overhead/include/linux/pkt_sched.h	2006-02-15 16:47:46.000000000 +0000
@@ -78,7 +78,7 @@ struct tc_ratespec
 	unsigned char	cell_log;
 	unsigned char	__reserved;
 	unsigned short	feature;
-	short		addend;
+	unsigned short	overhead;
 	unsigned short	mpu;
 	__u32		rate;
 };
diff -Naur -p linux-source-2.6.15.orig/net/sched/police.c linux-source-2.6.15.overhead/net/sched/police.c
--- linux-source-2.6.15.orig/net/sched/police.c	2006-01-03 03:21:10.000000000 +0000
+++ linux-source-2.6.15.overhead/net/sched/police.c	2006-02-15 16:53:55.000000000 +0000
@@ -33,8 +33,8 @@
 #include <net/sock.h>
 #include <net/act_api.h>
 
-#define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
-#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
+#define L2T(p,L)   ((p)->R_tab->data[((L)-1+(p)->R_tab->rate.overhead)>>(p)->R_tab->rate.cell_log])
+#define L2T_P(p,L) ((p)->P_tab->data[((L)-1+(p)->P_tab->rate.overhead)>>(p)->P_tab->rate.cell_log])
 #define PRIV(a) ((struct tcf_police *) (a)->priv)
 
 /* use generic hash table */
diff -Naur -p linux-source-2.6.15.orig/net/sched/sch_cbq.c linux-source-2.6.15.overhead/net/sched/sch_cbq.c
--- linux-source-2.6.15.orig/net/sched/sch_cbq.c	2006-01-03 03:21:10.000000000 +0000
+++ linux-source-2.6.15.overhead/net/sched/sch_cbq.c	2006-02-15 16:47:46.000000000 +0000
@@ -193,7 +193,7 @@ struct cbq_sched_data
 };
 
 
-#define L2T(cl,len)	((cl)->R_tab->data[(len)>>(cl)->R_tab->rate.cell_log])
+#define L2T(cl,len)	((cl)->R_tab->data[((len)-1+(cl)->R_tab->rate.overhead)>>(cl)->R_tab->rate.cell_log])
 
 
 static __inline__ unsigned cbq_hash(u32 h)
diff -Naur -p linux-source-2.6.15.orig/net/sched/sch_htb.c linux-source-2.6.15.overhead/net/sched/sch_htb.c
--- linux-source-2.6.15.orig/net/sched/sch_htb.c	2006-01-03 03:21:10.000000000 +0000
+++ linux-source-2.6.15.overhead/net/sched/sch_htb.c	2006-02-15 16:47:46.000000000 +0000
@@ -206,7 +206,8 @@ struct htb_class
 static __inline__ long L2T(struct htb_class *cl,struct qdisc_rate_table *rate,
 	int size)
 { 
-    int slot = size >> rate->rate.cell_log;
+    int overhead = rate->rate.overhead;
+    int slot = (size-1+overhead) >> rate->rate.cell_log;
     if (slot > 255) {
 	cl->xstats.giants++;
 	slot = 255;
diff -Naur -p linux-source-2.6.15.orig/net/sched/sch_tbf.c linux-source-2.6.15.overhead/net/sched/sch_tbf.c
--- linux-source-2.6.15.orig/net/sched/sch_tbf.c	2006-01-03 03:21:10.000000000 +0000
+++ linux-source-2.6.15.overhead/net/sched/sch_tbf.c	2006-02-15 16:47:46.000000000 +0000
@@ -132,8 +132,8 @@ struct tbf_sched_data
 	struct Qdisc	*qdisc;		/* Inner qdisc, default - bfifo queue */
 };
 
-#define L2T(q,L)   ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log])
-#define L2T_P(q,L) ((q)->P_tab->data[(L)>>(q)->P_tab->rate.cell_log])
+#define L2T(q,L)   ((q)->R_tab->data[((L)-1+(q)->R_tab->rate.overhead)>>(q)->R_tab->rate.cell_log])
+#define L2T_P(q,L) ((q)->P_tab->data[((L)-1+(q)->P_tab->rate.overhead)>>(q)->P_tab->rate.cell_log])
 
 static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
_______________________________________________
LARTC mailing list
LARTC@xxxxxxxxxxxxxxx
http://mailman.ds9a.nl/cgi-bin/mailman/listinfo/lartc

[Index of Archives]     [LARTC Home Page]     [Netfilter]     [Netfilter Development]     [Network Development]     [Bugtraq]     [GCC Help]     [Yosemite News]     [Linux Kernel]     [Fedora Users]
  Powered by Linux