Line 0
Link Here
|
|
|
1 |
/* |
2 |
* q_esfq.c ESFQ. |
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: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
10 |
* |
11 |
* Changes: Alexander Atanasov, <alex@ssi.bg> |
12 |
* Added depth,limit,divisor,hash_kind options. |
13 |
*/ |
14 |
|
15 |
#include <stdio.h> |
16 |
#include <stdlib.h> |
17 |
#include <unistd.h> |
18 |
#include <syslog.h> |
19 |
#include <fcntl.h> |
20 |
#include <math.h> |
21 |
#include <sys/socket.h> |
22 |
#include <netinet/in.h> |
23 |
#include <arpa/inet.h> |
24 |
#include <string.h> |
25 |
|
26 |
#include "utils.h" |
27 |
#include "tc_util.h" |
28 |
|
29 |
static void explain(void) |
30 |
{ |
31 |
fprintf(stderr, "Usage: ... esfq [ perturb SECS ] [ quantum BYTES ] [ depth FLOWS ]\n\t[ divisor HASHBITS ] [ limit PKTS ] [ hash HASHTYPE]\n"); |
32 |
fprintf(stderr,"Where: \n"); |
33 |
fprintf(stderr,"HASHTYPE := { classic | src | dst }\n"); |
34 |
} |
35 |
|
36 |
#define usage() return(-1) |
37 |
|
38 |
static int esfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) |
39 |
{ |
40 |
int ok=0; |
41 |
struct tc_sfq_qopt opt; |
42 |
|
43 |
memset(&opt, 0, sizeof(opt)); |
44 |
|
45 |
opt.hash_kind= TCA_SFQ_HASH_CLASSIC; |
46 |
|
47 |
while (argc > 0) { |
48 |
if (strcmp(*argv, "quantum") == 0) { |
49 |
NEXT_ARG(); |
50 |
if (get_size(&opt.quantum, *argv)) { |
51 |
fprintf(stderr, "Illegal \"quantum\"\n"); |
52 |
return -1; |
53 |
} |
54 |
ok++; |
55 |
} else if (strcmp(*argv, "perturb") == 0) { |
56 |
NEXT_ARG(); |
57 |
if (get_integer(&opt.perturb_period, *argv, 0)) { |
58 |
fprintf(stderr, "Illegal \"perturb\"\n"); |
59 |
return -1; |
60 |
} |
61 |
ok++; |
62 |
} else if (strcmp(*argv, "depth") == 0) { |
63 |
NEXT_ARG(); |
64 |
if (get_integer(&opt.flows, *argv, 0)) { |
65 |
fprintf(stderr, "Illegal \"depth\"\n"); |
66 |
return -1; |
67 |
} |
68 |
ok++; |
69 |
} else if (strcmp(*argv, "divisor") == 0) { |
70 |
NEXT_ARG(); |
71 |
if (get_integer(&opt.divisor, *argv, 0)) { |
72 |
fprintf(stderr, "Illegal \"divisor\"\n"); |
73 |
return -1; |
74 |
} |
75 |
if(opt.divisor >= 15) { |
76 |
fprintf(stderr, "Illegal \"divisor\" must be < 15\n"); |
77 |
return -1; |
78 |
} |
79 |
opt.divisor=pow(2,opt.divisor); |
80 |
ok++; |
81 |
} else if (strcmp(*argv, "limit") == 0) { |
82 |
NEXT_ARG(); |
83 |
if (get_integer(&opt.limit, *argv, 0)) { |
84 |
fprintf(stderr, "Illegal \"limit\"\n"); |
85 |
return -1; |
86 |
} |
87 |
ok++; |
88 |
} else if (strcmp(*argv, "hash") == 0) { |
89 |
NEXT_ARG(); |
90 |
if(strcmp(*argv,"classic") == 0) { |
91 |
opt.hash_kind= TCA_SFQ_HASH_CLASSIC; |
92 |
} else |
93 |
if(strcmp(*argv,"dst") == 0) { |
94 |
opt.hash_kind= TCA_SFQ_HASH_DST; |
95 |
} else |
96 |
if(strcmp(*argv,"src") == 0) { |
97 |
opt.hash_kind= TCA_SFQ_HASH_SRC; |
98 |
} else { |
99 |
fprintf(stderr, "Illegal \"hash\"\n"); |
100 |
explain(); |
101 |
return -1; |
102 |
} |
103 |
ok++; |
104 |
} else if (strcmp(*argv, "help") == 0) { |
105 |
explain(); |
106 |
return -1; |
107 |
} else { |
108 |
fprintf(stderr, "What is \"%s\"?\n", *argv); |
109 |
explain(); |
110 |
return -1; |
111 |
} |
112 |
argc--; argv++; |
113 |
} |
114 |
|
115 |
if (ok) |
116 |
addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)); |
117 |
return 0; |
118 |
} |
119 |
|
120 |
static int esfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) |
121 |
{ |
122 |
struct tc_sfq_qopt *qopt; |
123 |
SPRINT_BUF(b1); |
124 |
|
125 |
if (opt == NULL) |
126 |
return 0; |
127 |
|
128 |
if (RTA_PAYLOAD(opt) < sizeof(*qopt)) |
129 |
return -1; |
130 |
qopt = RTA_DATA(opt); |
131 |
fprintf(f, "quantum %s ", sprint_size(qopt->quantum, b1)); |
132 |
if (show_details) { |
133 |
fprintf(f, "limit %up flows %u/%u ", |
134 |
qopt->limit, qopt->flows, qopt->divisor); |
135 |
} |
136 |
if (qopt->perturb_period) |
137 |
fprintf(f, "perturb %dsec ", qopt->perturb_period); |
138 |
|
139 |
fprintf(f,"hash: "); |
140 |
switch(qopt->hash_kind) |
141 |
{ |
142 |
case TCA_SFQ_HASH_CLASSIC: |
143 |
fprintf(f,"classic"); |
144 |
break; |
145 |
case TCA_SFQ_HASH_DST: |
146 |
fprintf(f,"dst"); |
147 |
break; |
148 |
case TCA_SFQ_HASH_SRC: |
149 |
fprintf(f,"src"); |
150 |
break; |
151 |
default: |
152 |
fprintf(f,"Unknown"); |
153 |
} |
154 |
return 0; |
155 |
} |
156 |
|
157 |
static int esfq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats) |
158 |
{ |
159 |
return 0; |
160 |
} |
161 |
|
162 |
|
163 |
struct qdisc_util esfq_qdisc_util = { |
164 |
.id = "esfq", |
165 |
.parse_qopt = esfq_parse_opt, |
166 |
.print_qopt = esfq_print_opt, |
167 |
.print_xstats = esfq_print_xstats, |
168 |
}; |