aboutsummaryrefslogtreecommitdiffstats
path: root/package/qos-scripts/files/usr/lib/qos/tcrules.awk
blob: 7bef85b0d01d42e3bcf6279e4eb1ef2280dd82f0 (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
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)
}

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 (rtm1[i] > 0) {
			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" 
	}
}
n> /* raw vga text mode */ #define COLUMNS 80 /* The number of columns. */ #define LINES 25 /* The number of lines. */ #define ATTRIBUTE 7 /* The attribute of an character. */ #define VGA_BASE 0xB8000 /* The video memory address. */ /* VGA Index and Data Registers */ #define VGA_REG_INDEX 0x03D4 /* VGA index register */ #define VGA_REG_DATA 0x03D5 /* VGA data register */ #define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */ #define VGA_IDX_CURSTART 0x0A /* cursor start */ #define VGA_IDX_CUREND 0x0B /* cursor end */ #define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */ #define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */ /* Save the X and Y position. */ static int xpos, ypos; /* Point to the video memory. */ static volatile unsigned char *video = (unsigned char *) VGA_BASE; static void video_initcursor(void) { u8 val; outb(VGA_IDX_CURMSL, VGA_REG_INDEX); val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */ outb(VGA_IDX_CURSTART, VGA_REG_INDEX); outb(0, VGA_REG_DATA); outb(VGA_IDX_CUREND, VGA_REG_INDEX); outb(val, VGA_REG_DATA); } static void video_poscursor(unsigned int x, unsigned int y) { unsigned short pos; /* Calculate new cursor position as a function of x and y */ pos = (y * COLUMNS) + x; /* Output the new position to VGA card */ outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */ outb((u8) (pos), VGA_REG_DATA); outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */ outb((u8) (pos >> 8), VGA_REG_DATA); }; static void video_newline(void) { xpos = 0; if (ypos < LINES - 1) { ypos++; } else { int i; memmove((void *) video, (void *) (video + 2 * COLUMNS), (LINES - 1) * COLUMNS * 2); for (i = ((LINES - 1) * 2 * COLUMNS); i < 2 * COLUMNS * LINES;) { video[i++] = 0; video[i++] = ATTRIBUTE; } } } /* Put the character C on the screen. */ static void video_putchar(int c) { int p=1; if (c == '\n' || c == '\r') { video_newline(); return; } if (c == '\b') { if (xpos) xpos--; c=' '; p=0; } if (xpos >= COLUMNS) video_newline(); *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; if (p) xpos++; video_poscursor(xpos, ypos); } static void video_cls(void) { int i; for (i = 0; i < 2 * COLUMNS * LINES;) { video[i++] = 0; video[i++] = ATTRIBUTE; } xpos = 0; ypos = 0; video_initcursor(); video_poscursor(xpos, ypos); } void video_init(void) { video=phys_to_virt((unsigned char*)VGA_BASE); } /* * keyboard driver */ static const char normal[] = { 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f }; static const char shifted[] = { 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8', '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f }; static int key_ext; static int key_lshift = 0, key_rshift = 0, key_caps = 0; static char last_key; static void keyboard_cmd(unsigned char cmd, unsigned char val) { outb(cmd, 0x60); /* wait until keyboard controller accepts cmds: */ while (inb(0x64) & 2); outb(val, 0x60); while (inb(0x64) & 2); } static char keyboard_poll(void) { unsigned int c; if (inb(0x64) & 1) { c = inb(0x60); switch (c) { case 0xe0: key_ext = 1; return 0; case 0x2a: key_lshift = 1; return 0; case 0x36: key_rshift = 1; return 0; case 0xaa: key_lshift = 0; return 0; case 0xb6: key_rshift = 0; return 0; case 0x3a: if (key_caps) { key_caps = 0; keyboard_cmd(0xed, 0); } else { key_caps = 1; keyboard_cmd(0xed, 4); /* set caps led */ } return 0; } if (key_ext) { // void printk(const char *format, ...); printk("extended keycode: %x\n", c); key_ext = 0; return 0; } if (c & 0x80) /* unhandled key release */ return 0; if (key_lshift || key_rshift) return key_caps ? normal[c] : shifted[c]; else return key_caps ? shifted[c] : normal[c]; } return 0; } static int keyboard_dataready(void) { if (last_key) return 1; last_key = keyboard_poll(); return (last_key != 0); } static unsigned char keyboard_readdata(void) { char tmp; while (!keyboard_dataready()); tmp = last_key; last_key = 0; return tmp; } #endif /* ****************************************************************** * common functions, implementing simple concurrent console * ****************************************************************** */ static int arch_putchar(int c) { #ifdef CONFIG_DEBUG_CONSOLE_SERIAL serial_putchar(c); #endif #ifdef CONFIG_DEBUG_CONSOLE_VGA video_putchar(c); #endif return c; } static int arch_availchar(void) { #ifdef CONFIG_DEBUG_CONSOLE_SERIAL if (uart_charav(CONFIG_SERIAL_PORT)) return 1; #endif #ifdef CONFIG_DEBUG_CONSOLE_VGA if (keyboard_dataready()) return 1; #endif return 0; } static int arch_getchar(void) { #ifdef CONFIG_DEBUG_CONSOLE_SERIAL if (uart_charav(CONFIG_SERIAL_PORT)) return (uart_getchar(CONFIG_SERIAL_PORT)); #endif #ifdef CONFIG_DEBUG_CONSOLE_VGA if (keyboard_dataready()) return (keyboard_readdata()); #endif return 0; } void cls(void) { #ifdef CONFIG_DEBUG_CONSOLE_SERIAL serial_cls(); #endif #ifdef CONFIG_DEBUG_CONSOLE_VGA video_cls(); #endif } struct _console_ops arch_console_ops = { .putchar = arch_putchar, .availchar = arch_availchar, .getchar = arch_getchar }; #endif // CONFIG_DEBUG_CONSOLE