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" 4641f6004139e3dd8c8ab0d62ad0142f92b22e8c4aMichal Soltys "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" 6041f6004139e3dd8c8ab0d62ad0142f92b22e8c4aMichal Soltys "Remarks:\n" 6141f6004139e3dd8c8ab0d62ad0142f92b22e8c4aMichal Soltys " - at least one of 'rt', 'ls' or 'sc' must be specified\n" 6241f6004139e3dd8c8ab0d62ad0142f92b22e8c4aMichal Soltys " - 'ul' can only be specified with 'ls' or 'sc'\n" 6341f6004139e3dd8c8ab0d62ad0142f92b22e8c4aMichal Soltys "\n" 647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger ); 657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 677518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic void 687518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerexplain1(char *arg) 697518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 707518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: Illegal \"%s\"\n", arg); 717518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 727518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 737518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 747518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) 757518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 767518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct tc_hfsc_qopt qopt; 777518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 787518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger memset(&qopt, 0, sizeof(qopt)); 797518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 807518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger while (argc > 0) { 817518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "default") == 0) { 827518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 837518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (qopt.defcls != 0) { 847518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: Double \"default\"\n"); 857518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 867518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 877518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (get_u16(&qopt.defcls, *argv, 16) < 0) { 887518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("default"); 897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else if (matches(*argv, "help") == 0) { 927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain_qdisc(); 937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else { 957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv); 967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain_qdisc(); 977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger argc--, argv++; 1007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 1017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger addattr_l(n, 1024, TCA_OPTIONS, &qopt, sizeof(qopt)); 1037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 1047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 1057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 1077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) 108aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 1097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct tc_hfsc_qopt *qopt; 1107518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1117518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (opt == NULL) 1127518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 1137518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (RTA_PAYLOAD(opt) < sizeof(*qopt)) 1147518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1157518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger qopt = RTA_DATA(opt); 1167518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1177518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (qopt->defcls != 0) 1187518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, "default %x ", qopt->defcls); 1197518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1207518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 122aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 1237518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 1247518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats) 125aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 1267518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct tc_hfsc_stats *st; 1277518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1287518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (xstats == NULL) 1297518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 1307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (RTA_PAYLOAD(xstats) < sizeof(*st)) 1317518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1327518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger st = RTA_DATA(xstats); 1337518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1347518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, " period %u ", st->period); 1357518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (st->work != 0) 136b906243b62c832f24473de3ead7d7feef0e75e4bnet[shemminger]!shemminger fprintf(f, "work %llu bytes ", (unsigned long long) st->work); 1377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (st->rtwork != 0) 138b906243b62c832f24473de3ead7d7feef0e75e4bnet[shemminger]!shemminger fprintf(f, "rtwork %llu bytes ", (unsigned long long) st->rtwork); 1397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, "level %u ", st->level); 1407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, "\n"); 1417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1427518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 1437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 1447518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 1467518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, 1477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct nlmsghdr *n) 1487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 1497518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct tc_service_curve rsc, fsc, usc; 1507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger int rsc_ok, fsc_ok, usc_ok; 1517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct rtattr *tail; 1527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1537518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger memset(&rsc, 0, sizeof(rsc)); 1547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger memset(&fsc, 0, sizeof(fsc)); 1557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger memset(&usc, 0, sizeof(usc)); 1567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger rsc_ok = fsc_ok = usc_ok = 0; 1577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 1587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger while (argc > 0) { 1597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "rt") == 0) { 1607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 1617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (hfsc_get_sc(&argc, &argv, &rsc) < 0) { 1627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("rt"); 1637518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 1657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger rsc_ok = 1; 1667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else if (matches(*argv, "ls") == 0) { 1677518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 1687518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (hfsc_get_sc(&argc, &argv, &fsc) < 0) { 1697518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("ls"); 1707518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1717518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 1727518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fsc_ok = 1; 173b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger } else if (matches(*argv, "sc") == 0) { 174b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger NEXT_ARG(); 175b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger if (hfsc_get_sc(&argc, &argv, &rsc) < 0) { 176b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger explain1("sc"); 177b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger return -1; 178b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger } 179b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger memcpy(&fsc, &rsc, sizeof(fsc)); 180b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger rsc_ok = 1; 181b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger fsc_ok = 1; 1827518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else if (matches(*argv, "ul") == 0) { 1837518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 1847518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (hfsc_get_sc(&argc, &argv, &usc) < 0) { 1857518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("ul"); 1867518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1877518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 1887518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger usc_ok = 1; 1897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else if (matches(*argv, "help") == 0) { 1907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain_class(); 1917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else { 1937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv); 1947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain_class(); 1957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 1967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 1977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger argc--, argv++; 1987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 1997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (!(rsc_ok || fsc_ok || usc_ok)) { 2017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: no parameters given\n"); 2027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain_class(); 2037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 2047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 2057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (usc_ok && !fsc_ok) { 2067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: Upper-limit Service Curve without " 2077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger "Link-Share Service Curve\n"); 2087518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain_class(); 2097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 2107518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 2117518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2124a86fe19bc7f125d3eb40366277f87da4cda78ddn); tail = NLMSG_TAIL(n); 2137518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2147518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); 2157518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (rsc_ok) 2167518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger addattr_l(n, 1024, TCA_HFSC_RSC, &rsc, sizeof(rsc)); 2177518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (fsc_ok) 2187518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc)); 2197518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (usc_ok) 2207518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc)); 2217518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2224a86fe19bc7f125d3eb40366277f87da4cda78ddvoid *) NLMSG_TAIL(n) - (void *) tail; tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; 2237518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 224aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 225aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 2267518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic void 2277518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_sc(FILE *f, char *name, struct tc_service_curve *sc) 228aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 2297518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger SPRINT_BUF(b1); 2307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2317518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, "%s ", name); 2327518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, "m1 %s ", sprint_rate(sc->m1, b1)); 2338f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy fprintf(f, "d %s ", sprint_time(tc_core_ktime2time(sc->d), b1)); 2347518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(f, "m2 %s ", sprint_rate(sc->m2, b1)); 235aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 236aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 2377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 2387518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) 2397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 2407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct rtattr *tb[TCA_HFSC_MAX+1]; 2417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL; 2427518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (opt == NULL) 2447518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 2457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 246ac2fc2df5e117f6bf20d823f4bf1d9390ffbedf4tb, TCA_HFSC_MAX, opt); parse_rtattr_nested(tb, TCA_HFSC_MAX, opt); 2477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (tb[TCA_HFSC_RSC]) { 2497518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (RTA_PAYLOAD(tb[TCA_HFSC_RSC]) < sizeof(*rsc)) 2507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: truncated realtime option\n"); 2517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger else 2527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger rsc = RTA_DATA(tb[TCA_HFSC_RSC]); 2537518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 2547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (tb[TCA_HFSC_FSC]) { 2557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (RTA_PAYLOAD(tb[TCA_HFSC_FSC]) < sizeof(*fsc)) 2567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: truncated linkshare option\n"); 2577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger else 2587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fsc = RTA_DATA(tb[TCA_HFSC_FSC]); 2597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 2607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (tb[TCA_HFSC_USC]) { 2617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (RTA_PAYLOAD(tb[TCA_HFSC_USC]) < sizeof(*usc)) 2627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: truncated upperlimit option\n"); 2637518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger else 2647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger usc = RTA_DATA(tb[TCA_HFSC_USC]); 2657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 2667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 267ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 268b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger if (rsc != NULL && fsc != NULL && 269b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger memcmp(rsc, fsc, sizeof(*rsc)) == 0) 270b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger hfsc_print_sc(f, "sc", rsc); 271b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger else { 272b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger if (rsc != NULL) 273b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger hfsc_print_sc(f, "rt", rsc); 274b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger if (fsc != NULL) 275b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger hfsc_print_sc(f, "ls", fsc); 276b7de67dad5255cb9942b0fbed9f1fda95ff916e5net[shemminger]!shemminger } 2777518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (usc != NULL) 2787518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger hfsc_print_sc(f, "ul", usc); 2797518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2807518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 2817518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 282ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 28395812b56a5a66e7e9a21744cfe8bc0bb9791ea98net[shemminger]!kaberstruct qdisc_util hfsc_qdisc_util = { 284f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger .id = "hfsc", 285f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger .parse_qopt = hfsc_parse_opt, 286f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger .print_qopt = hfsc_print_opt, 287f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger .print_xstats = hfsc_print_xstats, 288f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger .parse_copt = hfsc_parse_class_opt, 289f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger .print_copt = hfsc_print_class_opt, 290aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}; 291aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 2927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 2937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc) 2947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 2957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger char **argv = *argvp; 2967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger int argc = *argcp; 2977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger unsigned int m1 = 0, d = 0, m2 = 0; 2987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 2997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "m1") == 0) { 3007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (get_rate(&m1, *argv) < 0) { 3027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("m1"); 3037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3087518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "d") == 0) { 3097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3108f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy if (get_time(&d, *argv) < 0) { 3117518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("d"); 3127518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3137518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3147518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3157518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3167518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3177518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "m2") == 0) { 3187518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3197518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (get_rate(&m2, *argv) < 0) { 3207518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("m2"); 3217518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3227518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3237518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else 3247518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3257518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3267518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger sc->m1 = m1; 327f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy sc->d = tc_core_time2ktime(d); 3287518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger sc->m2 = m2; 3297518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3307518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger *argvp = argv; 3317518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger *argcp = argc; 3327518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 3337518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 3347518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3357518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 3367518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc) 3377518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 3387518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger char **argv = *argvp; 3397518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger int argc = *argcp; 3407518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger unsigned int umax = 0, dmax = 0, rate = 0; 3417518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3427518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "umax") == 0) { 3437518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3447518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (get_size(&umax, *argv) < 0) { 3457518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("umax"); 3467518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3477518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3487518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3497518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3507518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3517518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "dmax") == 0) { 3527518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3538f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy if (get_time(&dmax, *argv) < 0) { 3547518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("dmax"); 3557518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3567518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3577518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3587518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3597518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3607518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (matches(*argv, "rate") == 0) { 3617518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger NEXT_ARG(); 3627518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (get_rate(&rate, *argv) < 0) { 3637518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger explain1("rate"); 3647518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3657518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3667518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else 3677518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3687518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3697518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (umax != 0 && dmax == 0) { 3707518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: umax given but dmax is zero.\n"); 3717518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 3727518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3737518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 374f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy if (dmax != 0 && ceil(1.0 * umax * TIME_UNITS_PER_SEC / dmax) > rate) { 3757518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger /* 3767518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger * concave curve, slope of first segment is umax/dmax, 3777518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger * intersection is at dmax 3787518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger */ 379f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy sc->m1 = ceil(1.0 * umax * TIME_UNITS_PER_SEC / dmax); /* in bps */ 380f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy sc->d = tc_core_time2ktime(dmax); 3817518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger sc->m2 = rate; 3827518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } else { 3837518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger /* 3847518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger * convex curve, slope of first segment is 0, intersection 3857518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger * is at dmax - umax / rate 3867518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger */ 3877518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger sc->m1 = 0; 388f0bda7e5a52d880a85af698a041afa7dc379e76ePatrick McHardy sc->d = tc_core_time2ktime(ceil(dmax - umax * TIME_UNITS_PER_SEC / rate)); 3897518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger sc->m2 = rate; 3907518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 3917518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3927518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger *argvp = argv; 3937518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger *argcp = argc; 3947518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 3957518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 3967518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 3977518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerstatic int 3987518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemmingerhfsc_get_sc(int *argcp, char ***argvp, struct tc_service_curve *sc) 3997518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger{ 4007518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (hfsc_get_sc1(argcp, argvp, sc) < 0 && 4017518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger hfsc_get_sc2(argcp, argvp, sc) < 0) 4027518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 4037518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 4047518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger if (sc->m1 == 0 && sc->m2 == 0) { 4057518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger fprintf(stderr, "HFSC: Service Curve has two zero slopes\n"); 4067518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return -1; 4077518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger } 4087518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger 4097518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger return 0; 4107518df00e72235d3d1f9e355033cb6f147b32435net[shemminger]!shemminger} 411