1 /* Copyright (C) 2013 Cisco Systems, Inc, 2013. 2 * 3 * This program is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU General Public License 5 * as published by the Free Software Foundation; either version 2 6 * of the License. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * Author: Vijay Subramanian <vijaynsu (at) cisco.com> 14 * Author: Mythili Prabhu <mysuryan (at) cisco.com> 15 * 16 */ 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <unistd.h> 21 #include <syslog.h> 22 #include <fcntl.h> 23 #include <sys/socket.h> 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <string.h> 27 #include <math.h> 28 29 #include "utils.h" 30 #include "tc_util.h" 31 32 static void explain(void) 33 { 34 fprintf(stderr, "Usage: ... pie [ limit PACKETS ][ target TIME us]\n"); 35 fprintf(stderr, " [ tupdate TIME us][ alpha ALPHA ]"); 36 fprintf(stderr, "[beta BETA ][bytemode | nobytemode][ecn | noecn ]\n"); 37 } 38 39 #define ALPHA_MAX 32 40 #define ALPHA_MIN 0 41 #define BETA_MAX 32 42 #define BETA_MIN 0 43 44 static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv, 45 struct nlmsghdr *n) 46 { 47 unsigned int limit = 0; 48 unsigned int target = 0; 49 unsigned int tupdate = 0; 50 unsigned int alpha = 0; 51 unsigned int beta = 0; 52 int ecn = -1; 53 int bytemode = -1; 54 struct rtattr *tail; 55 56 while (argc > 0) { 57 if (strcmp(*argv, "limit") == 0) { 58 NEXT_ARG(); 59 if (get_unsigned(&limit, *argv, 0)) { 60 fprintf(stderr, "Illegal \"limit\"\n"); 61 return -1; 62 } 63 } else if (strcmp(*argv, "target") == 0) { 64 NEXT_ARG(); 65 if (get_time(&target, *argv)) { 66 fprintf(stderr, "Illegal \"target\"\n"); 67 return -1; 68 } 69 } else if (strcmp(*argv, "tupdate") == 0) { 70 NEXT_ARG(); 71 if (get_time(&tupdate, *argv)) { 72 fprintf(stderr, "Illegal \"tupdate\"\n"); 73 return -1; 74 } 75 } else if (strcmp(*argv, "alpha") == 0) { 76 NEXT_ARG(); 77 if (get_unsigned(&alpha, *argv, 0) || 78 (alpha > ALPHA_MAX) || (alpha < ALPHA_MIN)) { 79 fprintf(stderr, "Illegal \"alpha\"\n"); 80 return -1; 81 } 82 } else if (strcmp(*argv, "beta") == 0) { 83 NEXT_ARG(); 84 if (get_unsigned(&beta, *argv, 0) || 85 (beta > BETA_MAX) || (beta < BETA_MIN)) { 86 fprintf(stderr, "Illegal \"beta\"\n"); 87 return -1; 88 } 89 } else if (strcmp(*argv, "ecn") == 0) { 90 ecn = 1; 91 } else if (strcmp(*argv, "noecn") == 0) { 92 ecn = 0; 93 } else if (strcmp(*argv, "bytemode") == 0) { 94 bytemode = 1; 95 } else if (strcmp(*argv, "nobytemode") == 0) { 96 bytemode = 0; 97 } else if (strcmp(*argv, "help") == 0) { 98 explain(); 99 return -1; 100 } else { 101 fprintf(stderr, "What is \"%s\"?\n", *argv); 102 explain(); 103 return -1; 104 } 105 argc--; 106 argv++; 107 } 108 109 tail = NLMSG_TAIL(n); 110 addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); 111 if (limit) 112 addattr_l(n, 1024, TCA_PIE_LIMIT, &limit, sizeof(limit)); 113 if (tupdate) 114 addattr_l(n, 1024, TCA_PIE_TUPDATE, &tupdate, sizeof(tupdate)); 115 if (target) 116 addattr_l(n, 1024, TCA_PIE_TARGET, &target, sizeof(target)); 117 if (alpha) 118 addattr_l(n, 1024, TCA_PIE_ALPHA, &alpha, sizeof(alpha)); 119 if (beta) 120 addattr_l(n, 1024, TCA_PIE_BETA, &beta, sizeof(beta)); 121 if (ecn != -1) 122 addattr_l(n, 1024, TCA_PIE_ECN, &ecn, sizeof(ecn)); 123 if (bytemode != -1) 124 addattr_l(n, 1024, TCA_PIE_BYTEMODE, &bytemode, 125 sizeof(bytemode)); 126 127 tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; 128 return 0; 129 } 130 131 static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) 132 { 133 struct rtattr *tb[TCA_PIE_MAX + 1]; 134 unsigned int limit; 135 unsigned int tupdate; 136 unsigned int target; 137 unsigned int alpha; 138 unsigned int beta; 139 unsigned ecn; 140 unsigned bytemode; 141 SPRINT_BUF(b1); 142 143 if (opt == NULL) 144 return 0; 145 146 parse_rtattr_nested(tb, TCA_PIE_MAX, opt); 147 148 if (tb[TCA_PIE_LIMIT] && 149 RTA_PAYLOAD(tb[TCA_PIE_LIMIT]) >= sizeof(__u32)) { 150 limit = rta_getattr_u32(tb[TCA_PIE_LIMIT]); 151 fprintf(f, "limit %up ", limit); 152 } 153 if (tb[TCA_PIE_TARGET] && 154 RTA_PAYLOAD(tb[TCA_PIE_TARGET]) >= sizeof(__u32)) { 155 target = rta_getattr_u32(tb[TCA_PIE_TARGET]); 156 fprintf(f, "target %s ", sprint_time(target, b1)); 157 } 158 if (tb[TCA_PIE_TUPDATE] && 159 RTA_PAYLOAD(tb[TCA_PIE_TUPDATE]) >= sizeof(__u32)) { 160 tupdate = rta_getattr_u32(tb[TCA_PIE_TUPDATE]); 161 fprintf(f, "tupdate %s ", sprint_time(tupdate, b1)); 162 } 163 if (tb[TCA_PIE_ALPHA] && 164 RTA_PAYLOAD(tb[TCA_PIE_ALPHA]) >= sizeof(__u32)) { 165 alpha = rta_getattr_u32(tb[TCA_PIE_ALPHA]); 166 fprintf(f, "alpha %u ", alpha); 167 } 168 if (tb[TCA_PIE_BETA] && 169 RTA_PAYLOAD(tb[TCA_PIE_BETA]) >= sizeof(__u32)) { 170 beta = rta_getattr_u32(tb[TCA_PIE_BETA]); 171 fprintf(f, "beta %u ", beta); 172 } 173 174 if (tb[TCA_PIE_ECN] && RTA_PAYLOAD(tb[TCA_PIE_ECN]) >= sizeof(__u32)) { 175 ecn = rta_getattr_u32(tb[TCA_PIE_ECN]); 176 if (ecn) 177 fprintf(f, "ecn "); 178 } 179 180 if (tb[TCA_PIE_BYTEMODE] && 181 RTA_PAYLOAD(tb[TCA_PIE_BYTEMODE]) >= sizeof(__u32)) { 182 bytemode = rta_getattr_u32(tb[TCA_PIE_BYTEMODE]); 183 if (bytemode) 184 fprintf(f, "bytemode "); 185 } 186 187 return 0; 188 } 189 190 static int pie_print_xstats(struct qdisc_util *qu, FILE *f, 191 struct rtattr *xstats) 192 { 193 struct tc_pie_xstats *st; 194 195 if (xstats == NULL) 196 return 0; 197 198 if (RTA_PAYLOAD(xstats) < sizeof(*st)) 199 return -1; 200 201 st = RTA_DATA(xstats); 202 /*prob is returned as a fracion of maximum integer value */ 203 fprintf(f, "prob %f delay %uus avg_dq_rate %u\n", 204 (double)st->prob / (double)0xffffffff, st->delay, 205 st->avg_dq_rate); 206 fprintf(f, "pkts_in %u overlimit %u dropped %u maxq %u ecn_mark %u\n", 207 st->packets_in, st->overlimit, st->dropped, st->maxq, 208 st->ecn_mark); 209 return 0; 210 211 } 212 213 struct qdisc_util pie_qdisc_util = { 214 .id = "pie", 215 .parse_qopt = pie_parse_opt, 216 .print_qopt = pie_print_opt, 217 .print_xstats = pie_print_xstats, 218 }; 219