q_hfsc.c revision 8f34caafbdbc8f87d228d577872591e138caadb1
1aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger/*
27518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger * q_hfsc.c	HFSC.
3aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *
4aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		This program is free software; you can redistribute it and/or
5aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		modify it under the terms of the GNU General Public License
6aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		as published by the Free Software Foundation; either version
7aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *		2 of the License, or (at your option) any later version.
8aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *
97518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger * Authors:	Patrick McHardy, <kaber@trash.net>
10aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *
11aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger */
12aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
13aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdio.h>
14aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdlib.h>
15aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <unistd.h>
16aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <syslog.h>
17aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <fcntl.h>
18aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <sys/socket.h>
19aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <netinet/in.h>
20aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <arpa/inet.h>
21aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <string.h>
227518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger#include <math.h>
23aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
24aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include "utils.h"
25aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include "tc_util.h"
26aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
277518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int hfsc_get_sc(int *, char ***, struct tc_service_curve *);
28aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
297518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic void
317518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerexplain_qdisc(void)
327518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
337518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(stderr,
347518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"Usage: ... hfsc [ default CLASSID ]\n"
357518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
367518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" default: default class for unclassified packets\n"
377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	);
387518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic void
417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerexplain_class(void)
427518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(stderr,
44b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger		"Usage: ... hfsc [ [ rt SC ] [ ls SC ] | [ sc SC ] ] [ ul SC ]\n"
457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
467518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"SC := [ [ m1 BPS ] [ d SEC ] m2 BPS\n"
477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" m1 : slope of first segment\n"
497518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" d  : x-coordinate of intersection\n"
507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" m2 : slope of second segment\n"
517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"Alternative format:\n"
537518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"SC := [ [ umax BYTE ] dmax SEC ] rate BPS\n"
557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" umax : maximum unit of work\n"
577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" dmax : maximum delay\n"
587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		" rate : rate\n"
597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		"\n"
607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	);
617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
637518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic void
647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerexplain1(char *arg)
657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(stderr, "HFSC: Illegal \"%s\"\n", arg);
677518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
687518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
697518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
707518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
717518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
727518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct tc_hfsc_qopt qopt;
737518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
747518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	memset(&qopt, 0, sizeof(qopt));
757518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
767518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	while (argc > 0) {
777518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (matches(*argv, "default") == 0) {
787518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			NEXT_ARG();
797518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			if (qopt.defcls != 0) {
807518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				fprintf(stderr, "HFSC: Double \"default\"\n");
817518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				return -1;
827518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			}
837518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			if (get_u16(&qopt.defcls, *argv, 16) < 0) {
847518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				explain1("default");
857518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				return -1;
867518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			}
877518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		} else if (matches(*argv, "help") == 0) {
887518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain_qdisc();
897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		} else {
917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain_qdisc();
937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		argc--, argv++;
967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	addattr_l(n, 1024, TCA_OPTIONS, &qopt, sizeof(qopt));
997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
1007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
1017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
1037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
104aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
1057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct tc_hfsc_qopt *qopt;
1067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (opt == NULL)
1087518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return 0;
1097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (RTA_PAYLOAD(opt) < sizeof(*qopt))
1107518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
1117518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	qopt = RTA_DATA(opt);
1127518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1137518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (qopt->defcls != 0)
1147518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		fprintf(f, "default %x ", qopt->defcls);
1157518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1167518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
117aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
1197518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
1207518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
1227518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct tc_hfsc_stats *st;
1237518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1247518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (xstats == NULL)
1257518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return 0;
1267518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (RTA_PAYLOAD(xstats) < sizeof(*st))
1277518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
1287518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	st = RTA_DATA(xstats);
1297518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(f, " period %u ", st->period);
1317518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (st->work != 0)
132b906243b62c832f24473de3ead7d7feef0e75e4bnet[shemminger]!shemminger		fprintf(f, "work %llu bytes ", (unsigned long long) st->work);
1337518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (st->rtwork != 0)
134b906243b62c832f24473de3ead7d7feef0e75e4bnet[shemminger]!shemminger		fprintf(f, "rtwork %llu bytes ", (unsigned long long) st->rtwork);
1357518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(f, "level %u ", st->level);
1367518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(f, "\n");
1377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1387518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
1397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
1407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
1427518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
1437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger                     struct nlmsghdr *n)
1447518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
1457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct tc_service_curve rsc, fsc, usc;
1467518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	int rsc_ok, fsc_ok, usc_ok;
1477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct rtattr *tail;
1487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1497518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	memset(&rsc, 0, sizeof(rsc));
1507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	memset(&fsc, 0, sizeof(fsc));
1517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	memset(&usc, 0, sizeof(usc));
1527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	rsc_ok = fsc_ok = usc_ok = 0;
1537518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	while (argc > 0) {
1557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (matches(*argv, "rt") == 0) {
1567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			NEXT_ARG();
1577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			if (hfsc_get_sc(&argc, &argv, &rsc) < 0) {
1587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				explain1("rt");
1597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				return -1;
1607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			}
1617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			rsc_ok = 1;
1627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		} else if (matches(*argv, "ls") == 0) {
1637518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			NEXT_ARG();
1647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			if (hfsc_get_sc(&argc, &argv, &fsc) < 0) {
1657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				explain1("ls");
1667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				return -1;
1677518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			}
1687518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fsc_ok = 1;
169b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger		} else if (matches(*argv, "sc") == 0) {
170b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			NEXT_ARG();
171b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			if (hfsc_get_sc(&argc, &argv, &rsc) < 0) {
172b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger				explain1("sc");
173b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger				return -1;
174b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			}
175b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			memcpy(&fsc, &rsc, sizeof(fsc));
176b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			rsc_ok = 1;
177b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			fsc_ok = 1;
1787518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		} else if (matches(*argv, "ul") == 0) {
1797518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			NEXT_ARG();
1807518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			if (hfsc_get_sc(&argc, &argv, &usc) < 0) {
1817518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				explain1("ul");
1827518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger				return -1;
1837518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			}
1847518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			usc_ok = 1;
1857518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		} else if (matches(*argv, "help") == 0) {
1867518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain_class();
1877518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
1887518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		} else {
1897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
1907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain_class();
1917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
1927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
1937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		argc--, argv++;
1947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
1957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
1967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (!(rsc_ok || fsc_ok || usc_ok)) {
1977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		fprintf(stderr, "HFSC: no parameters given\n");
1987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		explain_class();
1997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
2007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
2017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (usc_ok && !fsc_ok) {
2027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		fprintf(stderr, "HFSC: Upper-limit Service Curve without "
2037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		                "Link-Share Service Curve\n");
2047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		explain_class();
2057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
2067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
2077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2084a86fe19bc7f125d3eb40366277f87da4cda78ddn);	tail = NLMSG_TAIL(n);
2097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2107518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
2117518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (rsc_ok)
2127518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		addattr_l(n, 1024, TCA_HFSC_RSC, &rsc, sizeof(rsc));
2137518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (fsc_ok)
2147518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc));
2157518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (usc_ok)
2167518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc));
2177518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2184a86fe19bc7f125d3eb40366277f87da4cda78ddvoid *) NLMSG_TAIL(n) - (void *) tail;	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
2197518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
220aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
221aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
2227518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic void
2237518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_sc(FILE *f, char *name, struct tc_service_curve *sc)
224aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{
2257518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	SPRINT_BUF(b1);
2267518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2277518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(f, "%s ", name);
2287518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(f, "m1 %s ", sprint_rate(sc->m1, b1));
2298f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	fprintf(f, "d %s ", sprint_time(tc_core_ktime2time(sc->d), b1));
2307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	fprintf(f, "m2 %s ", sprint_rate(sc->m2, b1));
231aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}
232aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
2337518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
2347518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
2357518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
2367518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct rtattr *tb[TCA_HFSC_MAX+1];
2377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
2387518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (opt == NULL)
2407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return 0;
2417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
242ac2fc2df5e117f6bf20d823f4bf1d9390ffbedf4tb, TCA_HFSC_MAX, opt);	parse_rtattr_nested(tb, TCA_HFSC_MAX, opt);
2437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2447518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (tb[TCA_HFSC_RSC]) {
2457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (RTA_PAYLOAD(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
2467518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fprintf(stderr, "HFSC: truncated realtime option\n");
2477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		else
2487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			rsc = RTA_DATA(tb[TCA_HFSC_RSC]);
2497518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
2507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (tb[TCA_HFSC_FSC]) {
2517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (RTA_PAYLOAD(tb[TCA_HFSC_FSC]) < sizeof(*fsc))
2527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fprintf(stderr, "HFSC: truncated linkshare option\n");
2537518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		else
2547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fsc = RTA_DATA(tb[TCA_HFSC_FSC]);
2557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
2567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (tb[TCA_HFSC_USC]) {
2577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (RTA_PAYLOAD(tb[TCA_HFSC_USC]) < sizeof(*usc))
2587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			fprintf(stderr, "HFSC: truncated upperlimit option\n");
2597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		else
2607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			usc = RTA_DATA(tb[TCA_HFSC_USC]);
2617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
2627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
263ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
264b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger	if (rsc != NULL && fsc != NULL &&
265b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger	    memcmp(rsc, fsc, sizeof(*rsc)) == 0)
266b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger		hfsc_print_sc(f, "sc", rsc);
267b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger	else {
268b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger		if (rsc != NULL)
269b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			hfsc_print_sc(f, "rt", rsc);
270b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger		if (fsc != NULL)
271b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger			hfsc_print_sc(f, "ls", fsc);
272b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger	}
2737518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (usc != NULL)
2747518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		hfsc_print_sc(f, "ul", usc);
2757518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2767518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
2777518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
278ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
27995812b56a5a66e7e9a21744cfe8bc0bb9791ea98net[shemminger]!kaberstruct qdisc_util hfsc_qdisc_util = {
280f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.id		= "hfsc",
281f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.parse_qopt	= hfsc_parse_opt,
282f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.print_qopt	= hfsc_print_opt,
283f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.print_xstats	= hfsc_print_xstats,
284f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.parse_copt	= hfsc_parse_class_opt,
285f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.print_copt	= hfsc_print_class_opt,
286aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger};
287aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger
2887518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
2897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc)
2907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
2917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	char **argv = *argvp;
2927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	int argc = *argcp;
2937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	unsigned int m1 = 0, d = 0, m2 = 0;
2947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
2957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (matches(*argv, "m1") == 0) {
2967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
2977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (get_rate(&m1, *argv) < 0) {
2987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain1("m1");
2997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
3007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
3017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
3037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (matches(*argv, "d") == 0) {
3057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3068f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy		if (get_time(&d, *argv) < 0) {
3077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain1("d");
3087518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
3097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
3107518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3117518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
3127518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3137518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (matches(*argv, "m2") == 0) {
3147518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3157518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (get_rate(&m2, *argv) < 0) {
3167518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain1("m2");
3177518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
3187518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
3197518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	} else
3207518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
3217518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3227518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	sc->m1 = m1;
323f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy	sc->d  = tc_core_time2ktime(d);
3247518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	sc->m2 = m2;
3257518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3267518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	*argvp = argv;
3277518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	*argcp = argc;
3287518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
3297518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
3307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3317518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
3327518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc)
3337518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
3347518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	char **argv = *argvp;
3357518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	int argc = *argcp;
3367518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	unsigned int umax = 0, dmax = 0, rate = 0;
3377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3387518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (matches(*argv, "umax") == 0) {
3397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (get_size(&umax, *argv) < 0) {
3417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain1("umax");
3427518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
3437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
3447518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
3467518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (matches(*argv, "dmax") == 0) {
3487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3498f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy		if (get_time(&dmax, *argv) < 0) {
3507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain1("dmax");
3517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
3527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
3537518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
3557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (matches(*argv, "rate") == 0) {
3577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		NEXT_ARG();
3587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		if (get_rate(&rate, *argv) < 0) {
3597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			explain1("rate");
3607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger			return -1;
3617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		}
3627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	} else
3637518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
3647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (umax != 0 && dmax == 0) {
3667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		fprintf(stderr, "HFSC: umax given but dmax is zero.\n");
3677518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
3687518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
3697518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
370f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy	if (dmax != 0 && ceil(1.0 * umax * TIME_UNITS_PER_SEC / dmax) > rate) {
3717518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		/*
3727518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		 * concave curve, slope of first segment is umax/dmax,
3737518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		 * intersection is at dmax
3747518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		 */
375f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy		sc->m1 = ceil(1.0 * umax * TIME_UNITS_PER_SEC / dmax); /* in bps */
376f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy		sc->d  = tc_core_time2ktime(dmax);
3777518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		sc->m2 = rate;
3787518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	} else {
3797518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		/*
3807518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		 * convex curve, slope of first segment is 0, intersection
3817518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		 * is at dmax - umax / rate
3827518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		 */
3837518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		sc->m1 = 0;
384f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy		sc->d  = tc_core_time2ktime(ceil(dmax - umax * TIME_UNITS_PER_SEC / rate));
3857518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		sc->m2 = rate;
3867518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
3877518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3887518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	*argvp = argv;
3897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	*argcp = argc;
3907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
3917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
3927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
3937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int
3947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_get_sc(int *argcp, char ***argvp, struct tc_service_curve *sc)
3957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{
3967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (hfsc_get_sc1(argcp, argvp, sc) < 0 &&
3977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	    hfsc_get_sc2(argcp, argvp, sc) < 0)
3987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
3997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
4007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	if (sc->m1 == 0 && sc->m2 == 0) {
4017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		fprintf(stderr, "HFSC: Service Curve has two zero slopes\n");
4027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger		return -1;
4037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	}
4047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger
4057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger	return 0;
4067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger}
407