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