2 * m_police.c Parse/print policing module options.
4 * This program is free software; you can u32istribute 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.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 * FIXES: 19990619 - J Hadi Salim (hadi@cyberus.ca)
11 * simple addattr packaging fix.
12 * 2002: J Hadi Salim - Add tc action extensions syntax
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
28 struct action_util police_action_util
= {
30 .parse_aopt
= act_parse_police
,
31 .print_aopt
= print_police
,
34 static void usage(void)
36 fprintf(stderr
, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n");
37 fprintf(stderr
, " [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n");
38 fprintf(stderr
, " [ linklayer TYPE ] [ CONTROL ]\n");
40 fprintf(stderr
, "Where: CONTROL := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT]\n");
41 fprintf(stderr
, " Define how to handle packets which exceed (<EXCEEDACT>)\n");
42 fprintf(stderr
, " or conform (<NOTEXCEEDACT>) the configured bandwidth limit.\n");
43 fprintf(stderr
, " EXCEEDACT/NOTEXCEEDACT := { pipe | ok | reclassify | drop | continue |\n");
44 fprintf(stderr
, " goto chain <CHAIN_INDEX> }\n");
48 static void explain1(char *arg
)
50 fprintf(stderr
, "Illegal \"%s\"\n", arg
);
53 int act_parse_police(struct action_util
*a
, int *argc_p
, char ***argv_p
,
54 int tca_id
, struct nlmsghdr
*n
)
57 char **argv
= *argv_p
;
60 struct tc_police p
= { .action
= TC_POLICE_RECLASSIFY
};
65 unsigned buffer
= 0, mtu
= 0, mpu
= 0;
66 unsigned short overhead
= 0;
67 unsigned int linklayer
= LINKLAYER_ETHERNET
; /* Assume ethernet */
68 int Rcell_log
= -1, Pcell_log
= -1;
71 if (a
) /* new way of doing things */
79 if (matches(*argv
, "index") == 0) {
81 if (get_u32(&p
.index
, *argv
, 10)) {
82 fprintf(stderr
, "Illegal \"index\"\n");
85 } else if (matches(*argv
, "burst") == 0 ||
86 strcmp(*argv
, "buffer") == 0 ||
87 strcmp(*argv
, "maxburst") == 0) {
90 fprintf(stderr
, "Double \"buffer/burst\" spec\n");
93 if (get_size_and_cell(&buffer
, &Rcell_log
, *argv
) < 0) {
97 } else if (strcmp(*argv
, "mtu") == 0 ||
98 strcmp(*argv
, "minburst") == 0) {
101 fprintf(stderr
, "Double \"mtu/minburst\" spec\n");
104 if (get_size_and_cell(&mtu
, &Pcell_log
, *argv
) < 0) {
108 } else if (strcmp(*argv
, "mpu") == 0) {
111 fprintf(stderr
, "Double \"mpu\" spec\n");
114 if (get_size(&mpu
, *argv
)) {
118 } else if (strcmp(*argv
, "rate") == 0) {
121 fprintf(stderr
, "Double \"rate\" spec\n");
124 if (get_rate(&p
.rate
.rate
, *argv
)) {
128 } else if (strcmp(*argv
, "avrate") == 0) {
131 fprintf(stderr
, "Double \"avrate\" spec\n");
134 if (get_rate(&avrate
, *argv
)) {
138 } else if (matches(*argv
, "peakrate") == 0) {
140 if (p
.peakrate
.rate
) {
141 fprintf(stderr
, "Double \"peakrate\" spec\n");
144 if (get_rate(&p
.peakrate
.rate
, *argv
)) {
145 explain1("peakrate");
148 } else if (matches(*argv
, "reclassify") == 0 ||
149 matches(*argv
, "drop") == 0 ||
150 matches(*argv
, "shot") == 0 ||
151 matches(*argv
, "continue") == 0 ||
152 matches(*argv
, "pass") == 0 ||
153 matches(*argv
, "ok") == 0 ||
154 matches(*argv
, "pipe") == 0 ||
155 matches(*argv
, "goto") == 0) {
156 if (!parse_action_control(&argc
, &argv
, &p
.action
, false))
159 } else if (strcmp(*argv
, "conform-exceed") == 0) {
161 if (!parse_action_control_slash(&argc
, &argv
, &p
.action
,
165 } else if (matches(*argv
, "overhead") == 0) {
167 if (get_u16(&overhead
, *argv
, 10)) {
168 explain1("overhead"); return -1;
170 } else if (matches(*argv
, "linklayer") == 0) {
172 if (get_linklayer(&linklayer
, *argv
)) {
173 explain1("linklayer"); return -1;
175 } else if (strcmp(*argv
, "help") == 0) {
188 if (p
.rate
.rate
&& avrate
)
191 /* Must at least do late binding, use TB or ewma policing */
192 if (!p
.rate
.rate
&& !avrate
&& !p
.index
) {
193 fprintf(stderr
, "\"rate\" or \"avrate\" MUST be specified.\n");
197 /* When the TB policer is used, burst is required */
198 if (p
.rate
.rate
&& !buffer
&& !avrate
) {
199 fprintf(stderr
, "\"burst\" requires \"rate\".\n");
203 if (p
.peakrate
.rate
) {
205 fprintf(stderr
, "\"peakrate\" requires \"rate\".\n");
209 fprintf(stderr
, "\"mtu\" is required, if \"peakrate\" is requested.\n");
216 p
.rate
.overhead
= overhead
;
217 if (tc_calc_rtable(&p
.rate
, rtab
, Rcell_log
, mtu
,
219 fprintf(stderr
, "POLICE: failed to calculate rate table.\n");
222 p
.burst
= tc_calc_xmittime(p
.rate
.rate
, buffer
);
225 if (p
.peakrate
.rate
) {
226 p
.peakrate
.mpu
= mpu
;
227 p
.peakrate
.overhead
= overhead
;
228 if (tc_calc_rtable(&p
.peakrate
, ptab
, Pcell_log
, mtu
,
230 fprintf(stderr
, "POLICE: failed to calculate peak rate table.\n");
235 tail
= addattr_nest(n
, MAX_MSG
, tca_id
);
236 addattr_l(n
, MAX_MSG
, TCA_POLICE_TBF
, &p
, sizeof(p
));
238 addattr_l(n
, MAX_MSG
, TCA_POLICE_RATE
, rtab
, 1024);
240 addattr_l(n
, MAX_MSG
, TCA_POLICE_PEAKRATE
, ptab
, 1024);
242 addattr32(n
, MAX_MSG
, TCA_POLICE_AVRATE
, avrate
);
244 addattr32(n
, MAX_MSG
, TCA_POLICE_RESULT
, presult
);
246 addattr_nest_end(n
, tail
);
254 int parse_police(int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
256 return act_parse_police(NULL
, argc_p
, argv_p
, tca_id
, n
);
259 int print_police(struct action_util
*a
, FILE *f
, struct rtattr
*arg
)
264 struct rtattr
*tb
[TCA_POLICE_MAX
+1];
266 unsigned int linklayer
;
271 parse_rtattr_nested(tb
, TCA_POLICE_MAX
, arg
);
273 if (tb
[TCA_POLICE_TBF
] == NULL
) {
274 fprintf(f
, "[NULL police tbf]");
277 #ifndef STOOPID_8BYTE
278 if (RTA_PAYLOAD(tb
[TCA_POLICE_TBF
]) < sizeof(*p
)) {
279 fprintf(f
, "[truncated police tbf]");
283 p
= RTA_DATA(tb
[TCA_POLICE_TBF
]);
285 fprintf(f
, " police 0x%x ", p
->index
);
286 fprintf(f
, "rate %s ", sprint_rate(p
->rate
.rate
, b1
));
287 buffer
= tc_calc_xmitsize(p
->rate
.rate
, p
->burst
);
288 fprintf(f
, "burst %s ", sprint_size(buffer
, b1
));
289 fprintf(f
, "mtu %s ", sprint_size(p
->mtu
, b1
));
291 fprintf(f
, "[%08x] ", p
->burst
);
293 if (p
->peakrate
.rate
)
294 fprintf(f
, "peakrate %s ", sprint_rate(p
->peakrate
.rate
, b1
));
296 if (tb
[TCA_POLICE_AVRATE
])
297 fprintf(f
, "avrate %s ",
298 sprint_rate(rta_getattr_u32(tb
[TCA_POLICE_AVRATE
]),
301 print_action_control(f
, "action ", p
->action
, "");
303 if (tb
[TCA_POLICE_RESULT
]) {
304 __u32 action
= rta_getattr_u32(tb
[TCA_POLICE_RESULT
]);
306 print_action_control(f
, "/", action
, " ");
310 fprintf(f
, "overhead %ub ", p
->rate
.overhead
);
311 linklayer
= (p
->rate
.linklayer
& TC_LINKLAYER_MASK
);
312 if (linklayer
> TC_LINKLAYER_ETHERNET
|| show_details
)
313 fprintf(f
, "linklayer %s ", sprint_linklayer(linklayer
, b2
));
314 fprintf(f
, "\n\tref %d bind %d", p
->refcnt
, p
->bindcnt
);
316 if (tb
[TCA_POLICE_TM
]) {
317 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_POLICE_TM
]);
328 int tc_print_police(FILE *f
, struct rtattr
*arg
)
330 return print_police(&police_action_util
, f
, arg
);