1 /* 2 * tc_stab.c "tc qdisc ... stab *". 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Jussi Kivilinna, <jussi.kivilinna (at) mbnet.fi> 10 * 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 #include <syslog.h> 17 #include <fcntl.h> 18 #include <math.h> 19 #include <sys/socket.h> 20 #include <sys/param.h> 21 #include <netinet/in.h> 22 #include <arpa/inet.h> 23 #include <string.h> 24 #include <malloc.h> 25 26 #include "utils.h" 27 #include "tc_util.h" 28 #include "tc_core.h" 29 #include "tc_common.h" 30 31 static void stab_help(void) 32 { 33 fprintf(stderr, 34 "Usage: ... stab [ mtu BYTES ] [ tsize SLOTS ] [ mpu BYTES ] \n" 35 " [ overhead BYTES ] [ linklayer TYPE ] ...\n" 36 " mtu : max packet size we create rate map for {2047}\n" 37 " tsize : how many slots should size table have {512}\n" 38 " mpu : minimum packet size used in rate computations\n" 39 " overhead : per-packet size overhead used in rate computations\n" 40 " linklayer : adapting to a linklayer e.g. atm\n" 41 "Example: ... stab overhead 20 linklayer atm\n"); 42 43 return; 44 } 45 46 int check_size_table_opts(struct tc_sizespec *s) 47 { 48 return s->linklayer >= LINKLAYER_ETHERNET || s->mpu != 0 || 49 s->overhead != 0; 50 } 51 52 int parse_size_table(int *argcp, char ***argvp, struct tc_sizespec *sp) 53 { 54 char **argv = *argvp; 55 int argc = *argcp; 56 struct tc_sizespec s; 57 58 memset(&s, 0, sizeof(s)); 59 60 NEXT_ARG(); 61 if (matches(*argv, "help") == 0) { 62 stab_help(); 63 return -1; 64 } 65 while (argc > 0) { 66 if (matches(*argv, "mtu") == 0) { 67 NEXT_ARG(); 68 if (s.mtu) 69 duparg("mtu", *argv); 70 if (get_u32(&s.mtu, *argv, 10)) 71 invarg("mtu", "invalid mtu"); 72 } else if (matches(*argv, "mpu") == 0) { 73 NEXT_ARG(); 74 if (s.mpu) 75 duparg("mpu", *argv); 76 if (get_u32(&s.mpu, *argv, 10)) 77 invarg("mpu", "invalid mpu"); 78 } else if (matches(*argv, "overhead") == 0) { 79 NEXT_ARG(); 80 if (s.overhead) 81 duparg("overhead", *argv); 82 if (get_integer(&s.overhead, *argv, 10)) 83 invarg("overhead", "invalid overhead"); 84 } else if (matches(*argv, "tsize") == 0) { 85 NEXT_ARG(); 86 if (s.tsize) 87 duparg("tsize", *argv); 88 if (get_u32(&s.tsize, *argv, 10)) 89 invarg("tsize", "invalid table size"); 90 } else if (matches(*argv, "linklayer") == 0) { 91 NEXT_ARG(); 92 if (s.linklayer != LINKLAYER_UNSPEC) 93 duparg("linklayer", *argv); 94 if (get_linklayer(&s.linklayer, *argv)) 95 invarg("linklayer", "invalid linklayer"); 96 } else 97 break; 98 argc--; argv++; 99 } 100 101 if (!check_size_table_opts(&s)) 102 return -1; 103 104 *sp = s; 105 *argvp = argv; 106 *argcp = argc; 107 return 0; 108 } 109 110 void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta) 111 { 112 struct rtattr *tb[TCA_STAB_MAX + 1]; 113 SPRINT_BUF(b1); 114 115 parse_rtattr_nested(tb, TCA_STAB_MAX, rta); 116 117 if (tb[TCA_STAB_BASE]) { 118 struct tc_sizespec s = {0}; 119 memcpy(&s, RTA_DATA(tb[TCA_STAB_BASE]), 120 MIN(RTA_PAYLOAD(tb[TCA_STAB_BASE]), sizeof(s))); 121 122 fprintf(fp, "%s", prefix); 123 if (s.linklayer) 124 fprintf(fp, "linklayer %s ", 125 sprint_linklayer(s.linklayer, b1)); 126 if (s.overhead) 127 fprintf(fp, "overhead %d ", s.overhead); 128 if (s.mpu) 129 fprintf(fp, "mpu %u ", s.mpu); 130 if (s.mtu) 131 fprintf(fp, "mtu %u ", s.mtu); 132 if (s.tsize) 133 fprintf(fp, "tsize %u ", s.tsize); 134 } 135 136 #if 0 137 if (tb[TCA_STAB_DATA]) { 138 unsigned i, j, dlen; 139 __u16 *data = RTA_DATA(tb[TCA_STAB_DATA]); 140 dlen = RTA_PAYLOAD(tb[TCA_STAB_DATA]) / sizeof(__u16); 141 142 fprintf(fp, "\n%sstab data:", prefix); 143 for (i = 0; i < dlen/12; i++) { 144 fprintf(fp, "\n%s %3u:", prefix, i * 12); 145 for (j = 0; i * 12 + j < dlen; j++) 146 fprintf(fp, " %05x", data[i * 12 + j]); 147 } 148 } 149 #endif 150 } 151