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