tc_util.c revision 63e989f5e043a3a45857fe4ba083c49050eb3300
15f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/* 25f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * tc_util.c Misc TC utility functions. 35f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 45f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * This program is free software; you can redistribute it and/or 55f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * modify it under the terms of the GNU General Public License 65f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * as published by the Free Software Foundation; either version 75f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 2 of the License, or (at your option) any later version. 85f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 95f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * 115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */ 125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <stdio.h> 145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <stdlib.h> 155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <unistd.h> 165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <syslog.h> 175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <fcntl.h> 185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <sys/socket.h> 195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <netinet/in.h> 205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <arpa/inet.h> 215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <string.h> 225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <math.h> 235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include "utils.h" 255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include "tc_util.h" 265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesint get_qdisc_handle(__u32 *h, const char *str) 285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{ 295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes __u32 maj; 305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes char *p; 315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj = TC_H_UNSPEC; 335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (strcmp(str, "none") == 0) 345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes goto ok; 355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj = strtoul(str, &p, 16); 365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (p == str) 375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return -1; 385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj <<= 16; 395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (*p != ':' && *p!=0) 405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return -1; 415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesok: 425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *h = maj; 435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return 0; 445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes} 455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesint get_tc_classid(__u32 *h, const char *str) 475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{ 485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes __u32 maj, min; 495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes char *p; 505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj = TC_H_ROOT; 525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (strcmp(str, "root") == 0) 535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes goto ok; 545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj = TC_H_UNSPEC; 555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (strcmp(str, "none") == 0) 565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes goto ok; 575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj = strtoul(str, &p, 16); 585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (p == str) { 595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj = 0; 605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (*p != ':') 615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return -1; 625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } 635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (*p == ':') { 645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj <<= 16; 655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes str = p+1; 665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes min = strtoul(str, &p, 16); 675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (*p != 0) 685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return -1; 695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes maj |= min; 705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes } else if (*p != 0) 715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return -1; 725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesok: 745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *h = maj; 755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return 0; 765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes} 775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesint print_tc_classid(char *buf, int len, __u32 h) 795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{ 805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (h == TC_H_ROOT) 815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes sprintf(buf, "root"); 825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes else if (h == TC_H_UNSPEC) 835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes snprintf(buf, len, "none"); 845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes else if (TC_H_MAJ(h) == 0) 855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes snprintf(buf, len, ":%x", TC_H_MIN(h)); 865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes else if (TC_H_MIN(h) == 0) 875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16); 885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes else 895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes snprintf(buf, len, "%x:%x", TC_H_MAJ(h)>>16, TC_H_MIN(h)); 905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes return 0; 915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes} 925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes 935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hugheschar * sprint_tc_classid(__u32 h, char *buf) 945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{ 955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes if (print_tc_classid(buf, SPRINT_BSIZE-1, h)) 965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes strcpy(buf, "???"); 97 return buf; 98} 99 100/* 101 * NB: rates are scaled differently depending on bits or bytes. 102 * if bits are requested then k == 1000 103 * for bytes k = 1024 104 */ 105int get_rate(unsigned *rate, const char *str) 106{ 107 char *p; 108 double bps = strtod(str, &p); 109 110 if (p == str) 111 return -1; 112 113 if (*p == 0 || strcasecmp(p, "bit") == 0) 114 bps /= 8; 115 else if (strcasecmp(p, "kbit") == 0) 116 bps = (bps * 1000.) / 8; 117 else if (strcasecmp(p, "mbit") == 0) 118 bps = (bps * 1000000.)/8; 119 else if (strcasecmp(p, "gbit") == 0) 120 bps = (bps * 1000000000.)/8; 121 else if (strcasecmp(p, "kibit") == 0) 122 bps *= 1024 / 8; 123 else if (strcasecmp(p, "mibit") == 0) 124 bps *= 1024*1024/8; 125 else if (strcasecmp(p, "gibit") == 0) 126 bps *= 1024*1024*1024/8; 127 else if (strcasecmp(p, "kbps") == 0) 128 bps *= 1024; 129 else if (strcasecmp(p, "mbps") == 0) 130 bps *= 1024*1024; 131 else if (strcasecmp(p, "gbps") == 0) 132 bps *= 1024*1024*1024; 133 else if (strcasecmp(p, "bps") != 0) 134 return -1; 135 136 *rate = bps; 137 return 0; 138} 139 140int get_rate_and_cell(unsigned *rate, int *cell_log, char *str) 141{ 142 char * slash = strchr(str, '/'); 143 144 if (slash) 145 *slash = 0; 146 147 if (get_rate(rate, str)) 148 return -1; 149 150 if (slash) { 151 int cell; 152 int i; 153 154 if (get_integer(&cell, slash+1, 0)) 155 return -1; 156 *slash = '/'; 157 158 for (i=0; i<32; i++) { 159 if ((1<<i) == cell) { 160 *cell_log = i; 161 return 0; 162 } 163 } 164 return -1; 165 } 166 return 0; 167} 168 169 170int print_rate(char *buf, int len, __u32 rate) 171{ 172 double tmp = (double)rate*8; 173 174 if (tmp >= 999999 && fabs(1000000.*rint(tmp/1000000.) - tmp) < 1000) 175 snprintf(buf, len, "%gmbit", rint(tmp/1000000.)); 176 else if (tmp >= 990 && fabs(1000.*rint(tmp/1000.) - tmp) < 10) 177 snprintf(buf, len, "%gkbit", rint(tmp/1000.)); 178 else 179 snprintf(buf, len, "%ubit", rate); 180 return 0; 181} 182 183char * sprint_rate(__u32 rate, char *buf) 184{ 185 if (print_rate(buf, SPRINT_BSIZE-1, rate)) 186 strcpy(buf, "???"); 187 return buf; 188} 189 190int get_usecs(unsigned *usecs, const char *str) 191{ 192 double t; 193 char *p; 194 195 t = strtod(str, &p); 196 if (p == str) 197 return -1; 198 199 if (*p) { 200 if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 || 201 strcasecmp(p, "secs")==0) 202 t *= 1000000; 203 else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 || 204 strcasecmp(p, "msecs") == 0) 205 t *= 1000; 206 else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 || 207 strcasecmp(p, "usecs") == 0) 208 t *= 1; 209 else 210 return -1; 211 } 212 213 *usecs = t; 214 return 0; 215} 216 217 218int print_usecs(char *buf, int len, __u32 usec) 219{ 220 double tmp = usec; 221 222 if (tmp >= 1000000) 223 snprintf(buf, len, "%.1fs", tmp/1000000); 224 else if (tmp >= 1000) 225 snprintf(buf, len, "%.1fms", tmp/1000); 226 else 227 snprintf(buf, len, "%uus", usec); 228 return 0; 229} 230 231char * sprint_usecs(__u32 usecs, char *buf) 232{ 233 if (print_usecs(buf, SPRINT_BSIZE-1, usecs)) 234 strcpy(buf, "???"); 235 return buf; 236} 237 238int get_size(unsigned *size, const char *str) 239{ 240 double sz; 241 char *p; 242 243 sz = strtod(str, &p); 244 if (p == str) 245 return -1; 246 247 if (*p) { 248 if (strcasecmp(p, "kb") == 0 || strcasecmp(p, "k")==0) 249 sz *= 1024; 250 else if (strcasecmp(p, "gb") == 0 || strcasecmp(p, "g")==0) 251 sz *= 1024*1024*1024; 252 else if (strcasecmp(p, "gbit") == 0) 253 sz *= 1024*1024*1024/8; 254 else if (strcasecmp(p, "mb") == 0 || strcasecmp(p, "m")==0) 255 sz *= 1024*1024; 256 else if (strcasecmp(p, "mbit") == 0) 257 sz *= 1024*1024/8; 258 else if (strcasecmp(p, "kbit") == 0) 259 sz *= 1024/8; 260 else if (strcasecmp(p, "b") != 0) 261 return -1; 262 } 263 264 *size = sz; 265 return 0; 266} 267 268int get_size_and_cell(unsigned *size, int *cell_log, char *str) 269{ 270 char * slash = strchr(str, '/'); 271 272 if (slash) 273 *slash = 0; 274 275 if (get_size(size, str)) 276 return -1; 277 278 if (slash) { 279 int cell; 280 int i; 281 282 if (get_integer(&cell, slash+1, 0)) 283 return -1; 284 *slash = '/'; 285 286 for (i=0; i<32; i++) { 287 if ((1<<i) == cell) { 288 *cell_log = i; 289 return 0; 290 } 291 } 292 return -1; 293 } 294 return 0; 295} 296 297int print_size(char *buf, int len, __u32 sz) 298{ 299 double tmp = sz; 300 301 if (sz >= 1024*1024 && fabs(1024*1024*rint(tmp/(1024*1024)) - sz) < 1024) 302 snprintf(buf, len, "%gMb", rint(tmp/(1024*1024))); 303 else if (sz >= 1024 && fabs(1024*rint(tmp/1024) - sz) < 16) 304 snprintf(buf, len, "%gKb", rint(tmp/1024)); 305 else 306 snprintf(buf, len, "%ub", sz); 307 return 0; 308} 309 310char * sprint_size(__u32 size, char *buf) 311{ 312 if (print_size(buf, SPRINT_BSIZE-1, size)) 313 strcpy(buf, "???"); 314 return buf; 315} 316 317static double percent_scale = (double)(1ull << 32) / 100.; 318 319int get_percent(__u32 *percent, const char *str) 320{ 321 char *p; 322 double per = strtod(str, &p); 323 324 if (per > 100.) 325 return -1; 326 if (*p && strcmp(p, "%")) 327 return -1; 328 329 *percent = per * percent_scale; 330 return 0; 331} 332 333int print_percent(char *buf, int len, __u32 per) 334{ 335 snprintf(buf, len, "%g%%", (double) per / percent_scale); 336 return 0; 337} 338 339char * sprint_percent(__u32 per, char *buf) 340{ 341 if (print_percent(buf, SPRINT_BSIZE-1, per)) 342 strcpy(buf, "???"); 343 return buf; 344} 345 346int print_qdisc_handle(char *buf, int len, __u32 h) 347{ 348 snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16); 349 return 0; 350} 351 352char * sprint_qdisc_handle(__u32 h, char *buf) 353{ 354 if (print_qdisc_handle(buf, SPRINT_BSIZE-1, h)) 355 strcpy(buf, "???"); 356 return buf; 357} 358 359 360