aboutsummaryrefslogtreecommitdiffstats
path: root/package/qos-scripts/files/usr/lib/qos/tcrules.awk
blob: ebda50640bb9c4cbd9d6acf4bbb4d7d4941eec64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
BEGIN {
	dmax=100
	if (!(linespeed > 0)) linespeed = 128
	FS=":"
	n = 0
}

($1 != "") {
	n++
	class[n] = $1
	prio[n] = $2
	avgrate[n] = ($3 * linespeed / 100)
	pktsize[n] = $4
	delay[n] = $5
	maxrate[n] = ($6 * linespeed / 100)
	qdisc_esfq[n] = $7
}

END {
	allocated = 0
	maxdelay = 0

	for (i = 1; i <= n; i++) {
		# set defaults
		if (!(pktsize[i] > 0)) pktsize[i] = 1500
		if (!(prio[i] > 0)) prio[i] = 1

		allocated += avgrate[i]
		sum_prio += prio[i]
		if ((avgrate[i] > 0) && !(delay[i] > 0)) {
			sum_rtprio += prio[i]
		}
	}
	
	# allocation of m1 in rt classes:
	# sum(d * m1) must not exceed dmax * (linespeed - allocated)
	dmax = 0
	for (i = 1; i <= n; i++) {
		if (avgrate[i] > 0) {
			rtm2[i] = avgrate[i]
			if (delay[i] > 0) {
				d[i] = delay[i]
			} else {
				d[i] = 2 * pktsize[i] * 1000 / (linespeed * 1024)
				if (d[i] > dmax) dmax = d[i]
			}
		}
	}	

	ds_avail = dmax * (linespeed - allocated)
	for (i = 1; i <= n; i++) {
		lsm1[i] = 0
		rtm1[i] = 0
		lsm2[i] = linespeed * prio[i] / sum_prio
		if ((avgrate[i] > 0) && (d[i] > 0)) {
			if (!(delay[i] > 0)) {
				ds = ds_avail * prio[i] / sum_rtprio
				ds_avail -= ds
				rtm1[i] = rtm2[i] + ds/d[i]
			}
			lsm1[i] = rtm1[i]
		}
		else {
			d[i] = 0
		}
	}

	# main qdisc
	for (i = 1; i <= n; i++) {
		printf "tc class add dev "device" parent 1:1 classid 1:"class[i]"0 hfsc"
		if (qdisc_esfq[i] != "") {
			# user requested esfq
			print "esfq " qdisc_esfq[i] " limit " ql
		} else if (rtm1[i] > 0) {
			# rt class - use sfq
			printf " rt m1 " int(rtm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(rtm2[i])"kbit"
		}
		printf " ls m1 " int(lsm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(lsm2[i]) "kbit"
		print " ul rate " int(maxrate[i]) "kbit"
	}

	# leaf qdisc
	avpkt = 1200
	for (i = 1; i <= n; i++) {
		printf "tc qdisc add dev "device" parent 1:"class[i]"0 handle "class[i]"00: "

		# RED parameters - also used to determine the queue length for sfq
		# calculate min value. for links <= 256 kbit, we use 1500 bytes
		# use 50 ms queue length as min threshold for faster links
		# max threshold is fixed to 3*min
		base_pkt=3000
		base_rate=256
		min_lat=50
		if (maxrate[i] <= base_rate) min = base_pkt
		else min = int(maxrate[i] * 1024 / 8 * 0.05)
		max = 3 * min
		limit = (min + max) * 3

		if (rtm1[i] > 0) {
			# rt class - use sfq
			print "sfq perturb 2 limit "  limit
		} else {
			# non-rt class - use RED

			avpkt = pktsize[i]
			# don't use avpkt values less than 500 bytes
			if (avpkt < 500) avpkt = 500
			# if avpkt is too close to min, scale down avpkt to allow proper bursting
			if (avpkt > min * 0.70) avpkt *= 0.70


			# according to http://www.cs.unc.edu/~jeffay/papers/IEEE-ToN-01.pdf a drop
			# probability somewhere between 0.1 and 0.2 should be a good tradeoff
			# between link utilization and response time (0.1: response; 0.2: utilization)
			prob="0.12"
		
			rburst=int((2*min + max) / (3 * avpkt))
			if (rburst < 2) rburst = 2
			print "red min " min " max " max " burst " rburst " avpkt " avpkt " limit " limit " probability " prob " ecn"
		}
	}
	
	# filter rule
	for (i = 1; i <= n; i++) {
		print "tc filter add dev "device" parent 1: prio "class[i]" protocol ip handle "class[i]" fw flowid 1:"class[i] "0" 
	}
}
span class="c1">/////////////////////////////// // from arch/x86/flushtlb.c /////////////////////////////// u32 tlbflush_clock; u32 tlbflush_time[NR_CPUS]; /////////////////////////////// // from arch/x86/memory.c /////////////////////////////// void init_percpu_info(void) { dummy(); //memset(percpu_info, 0, sizeof(percpu_info)); } #if 0 void free_page_type(struct pfn_info *page, unsigned int type) { dummy(); } #endif /////////////////////////////// //// misc memory stuff /////////////////////////////// unsigned long __get_free_pages(unsigned int mask, unsigned int order) { void *p = alloc_xenheap_pages(order); memset(p,0,PAGE_SIZE<<order); return (unsigned long)p; } void __free_pages(struct page *page, unsigned int order) { if (order) BUG(); free_xenheap_page(page); } void *pgtable_quicklist_alloc(void) { return alloc_xenheap_pages(0); } void pgtable_quicklist_free(void *pgtable_entry) { free_xenheap_page(pgtable_entry); } /////////////////////////////// // from arch/ia64/traps.c /////////////////////////////// void show_registers(struct pt_regs *regs) { printf("*** ADD REGISTER DUMP HERE FOR DEBUGGING\n"); } int is_kernel_text(unsigned long addr) { extern char _stext[], _etext[]; if (addr >= (unsigned long) _stext && addr <= (unsigned long) _etext) return 1; return 0; } unsigned long kernel_text_end(void) { extern char _etext[]; return (unsigned long) _etext; } /////////////////////////////// // from common/keyhandler.c /////////////////////////////// void dump_pageframe_info(struct domain *d) { printk("dump_pageframe_info not implemented\n"); } /////////////////////////////// // called from arch/ia64/head.S /////////////////////////////// void console_print(char *msg) { printk("console_print called, how did start_kernel return???\n"); } void kernel_thread_helper(void) { printk("kernel_thread_helper not implemented\n"); dummy(); } void sys_exit(void) { printk("sys_exit not implemented\n"); dummy(); } //////////////////////////////////// // called from unaligned.c //////////////////////////////////// void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */ { printk("die_if_kernel: called, not implemented\n"); } long ia64_peek (struct task_struct *child, struct switch_stack *child_stack, unsigned long user_rbs_end, unsigned long addr, long *val) { printk("ia64_peek: called, not implemented\n"); } long ia64_poke (struct task_struct *child, struct switch_stack *child_stack, unsigned long user_rbs_end, unsigned long addr, long val) { printk("ia64_poke: called, not implemented\n"); } void ia64_sync_fph (struct task_struct *task) { printk("ia64_sync_fph: called, not implemented\n"); } void ia64_flush_fph (struct task_struct *task) { printk("ia64_flush_fph: called, not implemented\n"); } //////////////////////////////////// // called from irq_ia64.c:init_IRQ() // (because CONFIG_IA64_HP_SIM is specified) //////////////////////////////////// void hpsim_irq_init(void) { } // accomodate linux extable.c //const struct exception_table_entry * void *search_module_extables(unsigned long addr) { return NULL; } void *__module_text_address(unsigned long addr) { return NULL; } void *module_text_address(unsigned long addr) { return NULL; } void cs10foo(void) {} void cs01foo(void) {} unsigned long context_switch_count = 0; #include <asm/vcpu.h> void context_switch(struct vcpu *prev, struct vcpu *next) { //printk("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); //printk("@@@@@@ context switch from domain %d (%x) to domain %d (%x)\n", //prev->domain->domain_id,(long)prev&0xffffff,next->domain->domain_id,(long)next&0xffffff); //if (prev->domain->domain_id == 1 && next->domain->domain_id == 0) cs10foo(); //if (prev->domain->domain_id == 0 && next->domain->domain_id == 1) cs01foo(); //printk("@@sw%d/%x %d->%d\n",smp_processor_id(), hard_smp_processor_id (), // prev->domain->domain_id,next->domain->domain_id); if(VMX_DOMAIN(prev)){ vtm_domain_out(prev); } context_switch_count++; switch_to(prev,next,prev); if(VMX_DOMAIN(current)){ vtm_domain_in(current); } // leave this debug for now: it acts as a heartbeat when more than // one domain is active { static long cnt[16] = { 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50}; static int i = 100; int id = ((struct vcpu *)current)->domain->domain_id & 0xf; if (!cnt[id]--) { printk("%x",id); cnt[id] = 500000; } if (!i--) { printk("+",id); i = 1000000; } } if (VMX_DOMAIN(current)){ vmx_load_all_rr(current); }else{ extern char ia64_ivt; ia64_set_iva(&ia64_ivt); ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) | VHPT_ENABLED); if (!is_idle_task(current->domain)) { load_region_regs(current); vcpu_load_kernel_regs(current); if (vcpu_timer_expired(current)) vcpu_pend_timer(current); } if (vcpu_timer_expired(current)) vcpu_pend_timer(current); } } void context_switch_finalise(struct vcpu *next) { /* nothing to do */ } void continue_running(struct vcpu *same) { /* nothing to do */ } void panic_domain(struct pt_regs *regs, const char *fmt, ...) { va_list args; char buf[128]; struct vcpu *v = current; static volatile int test = 1; // so can continue easily in debug extern spinlock_t console_lock; unsigned long flags; loop: printf("$$$$$ PANIC in domain %d (k6=%p): ", v->domain->domain_id, __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT]); va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printf(buf); if (regs) show_registers(regs); domain_pause_by_systemcontroller(current->domain); v->domain->shutdown_code = SHUTDOWN_crash; set_bit(_DOMF_shutdown, v->domain->domain_flags); if (v->domain->domain_id == 0) { int i = 1000000000L; // if domain0 crashes, just periodically print out panic // message to make post-mortem easier while(i--); goto loop; } }