1839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna/*
2839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna * tc_stab.c		"tc qdisc ... stab *".
3839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *
4839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *		This program is free software; you can redistribute it and/or
5839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *		modify it under the terms of the GNU General Public License
6839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *		as published by the Free Software Foundation; either version
7839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *		2 of the License, or (at your option) any later version.
8839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *
9839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna * Authors:	Jussi Kivilinna, <jussi.kivilinna@mbnet.fi>
10839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna *
11839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna */
12839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
13839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <stdio.h>
14839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <stdlib.h>
15839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <unistd.h>
16839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <syslog.h>
17839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <fcntl.h>
18839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <math.h>
19839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <sys/socket.h>
20839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <netinet/in.h>
21839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <arpa/inet.h>
22839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <string.h>
23839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include <malloc.h>
24839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
25839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include "utils.h"
26839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include "tc_util.h"
27839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include "tc_core.h"
28839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#include "tc_common.h"
29839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
30839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnastatic void stab_help(void)
31839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna{
32839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	fprintf(stderr,
33839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"Usage: ... stab [ mtu BYTES ] [ tsize SLOTS ] [ mpu BYTES ] \n"
34839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"                [ overhead BYTES ] [ linklayer TYPE ] ...\n"
35839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"   mtu       : max packet size we create rate map for {2047}\n"
36839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"   tsize     : how many slots should size table have {512}\n"
37839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"   mpu       : minimum packet size used in rate computations\n"
38839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"   overhead  : per-packet size overhead used in rate computations\n"
39839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"   linklayer : adapting to a linklayer e.g. atm\n"
40839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		"Example: ... stab overhead 20 linklayer atm\n");
41839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
42839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	return;
43839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna}
44839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
45839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnaint check_size_table_opts(struct tc_sizespec *s)
46839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna{
47839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	return s->linklayer >= LINKLAYER_ETHERNET || s->mpu != 0 ||
48839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna							s->overhead != 0;
49839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna}
50839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
51839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnaint parse_size_table(int *argcp, char ***argvp, struct tc_sizespec *sp)
52839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna{
53839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	char **argv = *argvp;
54839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	int argc = *argcp;
55839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	struct tc_sizespec s;
56839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
57839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	memset(&s, 0, sizeof(s));
58839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
59839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	NEXT_ARG();
60839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (matches(*argv, "help") == 0) {
61839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		stab_help();
62839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		return -1;
63839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
64839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	while (argc > 0) {
65839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if (matches(*argv, "mtu") == 0) {
66839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			NEXT_ARG();
67839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (s.mtu)
68839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				duparg("mtu", *argv);
69839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (get_u32(&s.mtu, *argv, 10)) {
70839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				invarg("mtu", "invalid mtu");
71839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				return -1;
72839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			}
73839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		} else if (matches(*argv, "mpu") == 0) {
74839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			NEXT_ARG();
75839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (s.mpu)
76839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				duparg("mpu", *argv);
77839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (get_u32(&s.mpu, *argv, 10)) {
78839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				invarg("mpu", "invalid mpu");
79839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				return -1;
80839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			}
81839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		} else if (matches(*argv, "overhead") == 0) {
82839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			NEXT_ARG();
83839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (s.overhead)
84839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				duparg("overhead", *argv);
85839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (get_integer(&s.overhead, *argv, 10)) {
86839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				invarg("overhead", "invalid overhead");
87839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				return -1;
88839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			}
89839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		} else if (matches(*argv, "tsize") == 0) {
90839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			NEXT_ARG();
91839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (s.tsize)
92839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				duparg("tsize", *argv);
93839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (get_u32(&s.tsize, *argv, 10)) {
94839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				invarg("tsize", "invalid table size");
95839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				return -1;
96839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			}
97839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		} else if (matches(*argv, "linklayer") == 0) {
98839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			NEXT_ARG();
99839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (s.linklayer != LINKLAYER_UNSPEC)
100839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				duparg("linklayer", *argv);
101839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			if (get_linklayer(&s.linklayer, *argv)) {
102839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				invarg("linklayer", "invalid linklayer");
103839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				return -1;
104839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			}
105839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		} else
106839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			break;
107839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		argc--; argv++;
108839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
109839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
110839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (!check_size_table_opts(&s))
111839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		return -1;
112839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
113839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	*sp = s;
114839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	*argvp = argv;
115839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	*argcp = argc;
116839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	return 0;
117839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna}
118839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
119839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinnavoid print_size_table(FILE *fp, const char *prefix, struct rtattr *rta)
120839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna{
121839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	struct rtattr *tb[TCA_STAB_MAX + 1];
122839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	SPRINT_BUF(b1);
123839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
124839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	parse_rtattr_nested(tb, TCA_STAB_MAX, rta);
125839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
126839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (tb[TCA_STAB_BASE]) {
127839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		struct tc_sizespec s = {0};
128839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		memcpy(&s, RTA_DATA(tb[TCA_STAB_BASE]),
129839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				MIN(RTA_PAYLOAD(tb[TCA_STAB_BASE]), sizeof(s)));
130839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
131839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		fprintf(fp, "%s", prefix);
132839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if (s.linklayer)
133839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			fprintf(fp, "linklayer %s ",
134839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna					sprint_linklayer(s.linklayer, b1));
135839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if (s.overhead)
136839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			fprintf(fp, "overhead %d ", s.overhead);
137839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if (s.mpu)
138839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			fprintf(fp, "mpu %u ", s.mpu);
139839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if (s.mtu)
140839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			fprintf(fp, "mtu %u ", s.mtu);
141839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		if (s.tsize)
142839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			fprintf(fp, "tsize %u ", s.tsize);
143839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
144839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
145839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#if 0
146839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	if (tb[TCA_STAB_DATA]) {
147839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		unsigned i, j, dlen;
148839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		__u16 *data = RTA_DATA(tb[TCA_STAB_DATA]);
149839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		dlen = RTA_PAYLOAD(tb[TCA_STAB_DATA]) / sizeof(__u16);
150839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
151839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		fprintf(fp, "\n%sstab data:", prefix);
152839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		for (i = 0; i < dlen/12; i++) {
153839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			fprintf(fp, "\n%s %3u:", prefix, i * 12);
154839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna			for (j = 0; i * 12 + j < dlen; j++)
155839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna				fprintf(fp, " %05x", data[i * 12 + j]);
156839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna		}
157839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna	}
158839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna#endif
159839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna}
160839c8456fbe08fc2497857673805b84dffb45507Jussi Kivilinna
161