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
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
29 struct action_util police_action_util
= {
31 .parse_aopt
= act_parse_police
,
32 .print_aopt
= print_police
,
35 static void explain(void)
37 fprintf(stderr
, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n");
38 fprintf(stderr
, " [ peakrate BPS ] [ avrate BPS ] [ overhead OVERHEAD ] [ atm ]\n");
39 fprintf(stderr
, " [ ACTIONTERM ]\n");
40 fprintf(stderr
, "Old Syntax ACTIONTERM := action <EXCEEDACT>[/NOTEXCEEDACT] \n");
41 fprintf(stderr
, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n");
42 fprintf(stderr
, "Where: *EXCEEDACT := pipe | ok | reclassify | drop | continue \n");
43 fprintf(stderr
, "Where: pipe is only valid for new syntax \n");
46 static void explain1(char *arg
)
48 fprintf(stderr
, "Illegal \"%s\"\n", arg
);
51 #define usage() return(-1)
54 char *police_action_n2a(int action
, char *buf
, int len
)
66 case TC_POLICE_RECLASSIFY
:
71 snprintf(buf
, len
, "%d", action
);
76 int police_action_a2n(char *arg
, int *result
)
80 if (matches(arg
, "continue") == 0)
82 else if (matches(arg
, "drop") == 0)
84 else if (matches(arg
, "shot") == 0)
86 else if (matches(arg
, "pass") == 0)
88 else if (strcmp(arg
, "ok") == 0)
90 else if (matches(arg
, "reclassify") == 0)
91 res
= TC_POLICE_RECLASSIFY
;
92 else if (matches(arg
, "pipe") == 0)
96 if (sscanf(arg
, "%d%c", &res
, &dummy
) != 1)
104 int get_police_result(int *action
, int *result
, char *arg
)
106 char *p
= strchr(arg
, '/');
111 if (police_action_a2n(arg
, action
)) {
119 if (police_action_a2n(p
+1, result
))
126 int act_parse_police(struct action_util
*a
,int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
129 char **argv
= *argv_p
;
137 unsigned buffer
=0, mtu
=0;
141 int Rcell_log
=-1, Pcell_log
= -1;
144 memset(&p
, 0, sizeof(p
));
145 p
.action
= TC_POLICE_RECLASSIFY
;
147 if (a
) /* new way of doing things */
155 if (matches(*argv
, "index") == 0) {
157 if (get_u32(&p
.index
, *argv
, 10)) {
158 fprintf(stderr
, "Illegal \"index\"\n");
161 } else if (matches(*argv
, "burst") == 0 ||
162 strcmp(*argv
, "buffer") == 0 ||
163 strcmp(*argv
, "maxburst") == 0) {
166 fprintf(stderr
, "Double \"buffer/burst\" spec\n");
169 if (get_size_and_cell(&buffer
, &Rcell_log
, *argv
) < 0) {
173 } else if (strcmp(*argv
, "mtu") == 0 ||
174 strcmp(*argv
, "minburst") == 0) {
177 fprintf(stderr
, "Double \"mtu/minburst\" spec\n");
180 if (get_size_and_cell(&mtu
, &Pcell_log
, *argv
) < 0) {
184 } else if (strcmp(*argv
, "mpu") == 0) {
187 fprintf(stderr
, "Double \"mpu\" spec\n");
190 if (get_u8(&mpu
, *argv
, 10)) {
194 } else if (strcmp(*argv
, "rate") == 0) {
197 fprintf(stderr
, "Double \"rate\" spec\n");
200 if (get_rate(&p
.rate
.rate
, *argv
)) {
204 } else if (strcmp(*argv
, "overhead") == 0) {
207 fprintf(stderr
, "Double \"overhead\" spec\n");
210 if (get_s8(&overhead
, *argv
, 10)) {
211 explain1("overhead");
214 } else if (strcmp(*argv
, "atm") == 0) {
216 } else if (strcmp(*argv
, "avrate") == 0) {
219 fprintf(stderr
, "Double \"avrate\" spec\n");
222 if (get_rate(&avrate
, *argv
)) {
226 } else if (matches(*argv
, "peakrate") == 0) {
228 if (p
.peakrate
.rate
) {
229 fprintf(stderr
, "Double \"peakrate\" spec\n");
232 if (get_rate(&p
.peakrate
.rate
, *argv
)) {
233 explain1("peakrate");
236 } else if (matches(*argv
, "reclassify") == 0) {
237 p
.action
= TC_POLICE_RECLASSIFY
;
238 } else if (matches(*argv
, "drop") == 0 ||
239 matches(*argv
, "shot") == 0) {
240 p
.action
= TC_POLICE_SHOT
;
241 } else if (matches(*argv
, "continue") == 0) {
242 p
.action
= TC_POLICE_UNSPEC
;
243 } else if (matches(*argv
, "pass") == 0) {
244 p
.action
= TC_POLICE_OK
;
245 } else if (matches(*argv
, "pipe") == 0) {
246 p
.action
= TC_POLICE_PIPE
;
247 } else if (strcmp(*argv
, "conform-exceed") == 0) {
249 if (get_police_result(&p
.action
, &presult
, *argv
)) {
250 fprintf(stderr
, "Illegal \"action\"\n");
253 } else if (strcmp(*argv
, "help") == 0) {
266 if (p
.rate
.rate
&& !buffer
) {
267 fprintf(stderr
, "\"burst\" requires \"rate\".\n");
270 if (p
.peakrate
.rate
) {
272 fprintf(stderr
, "\"peakrate\" requires \"rate\".\n");
276 fprintf(stderr
, "\"mtu\" is required, if \"peakrate\" is requested.\n");
282 tc_calc_ratespec(&p
.rate
, rtab
, p
.rate
.rate
, Rcell_log
, mtu
, mpu
, atm
, overhead
);
283 p
.burst
= tc_calc_xmittime(p
.rate
.rate
, buffer
);
286 if (p
.peakrate
.rate
) {
287 tc_calc_ratespec(&p
.peakrate
, ptab
, p
.peakrate
.rate
, Pcell_log
, mtu
, mpu
, atm
, overhead
);
290 tail
= NLMSG_TAIL(n
);
291 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
292 addattr_l(n
, MAX_MSG
, TCA_POLICE_TBF
, &p
, sizeof(p
));
294 addattr_l(n
, MAX_MSG
, TCA_POLICE_RATE
, rtab
, 1024);
296 addattr_l(n
, MAX_MSG
, TCA_POLICE_PEAKRATE
, ptab
, 1024);
298 addattr32(n
, MAX_MSG
, TCA_POLICE_AVRATE
, avrate
);
300 addattr32(n
, MAX_MSG
, TCA_POLICE_RESULT
, presult
);
302 tail
->rta_len
= (void *) NLMSG_TAIL(n
) - (void *) tail
;
310 int parse_police(int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
312 return act_parse_police(NULL
,argc_p
,argv_p
,tca_id
,n
);
316 print_police(struct action_util
*a
, FILE *f
, struct rtattr
*arg
)
320 struct rtattr
*tb
[TCA_POLICE_MAX
+1];
326 parse_rtattr_nested(tb
, TCA_POLICE_MAX
, arg
);
328 if (tb
[TCA_POLICE_TBF
] == NULL
) {
329 fprintf(f
, "[NULL police tbf]");
332 #ifndef STOOPID_8BYTE
333 if (RTA_PAYLOAD(tb
[TCA_POLICE_TBF
]) < sizeof(*p
)) {
334 fprintf(f
, "[truncated police tbf]");
338 p
= RTA_DATA(tb
[TCA_POLICE_TBF
]);
340 fprintf(f
, " police 0x%x ", p
->index
);
341 fprintf(f
, "rate %s ", sprint_rate(p
->rate
.rate
, b1
));
342 buffer
= ((double)p
->rate
.rate
*tc_core_tick2usec(p
->burst
))/1000000;
343 fprintf(f
, "burst %s ", sprint_size(buffer
, b1
));
344 fprintf(f
, "mtu %s ", sprint_size(p
->mtu
, b1
));
346 fprintf(f
, "[%08x] ", p
->burst
);
347 if (p
->peakrate
.rate
)
348 fprintf(f
, "peakrate %s ", sprint_rate(p
->peakrate
.rate
, b1
));
349 if (tb
[TCA_POLICE_AVRATE
])
350 fprintf(f
, "avrate %s ", sprint_rate(*(__u32
*)RTA_DATA(tb
[TCA_POLICE_AVRATE
]), b1
));
351 fprintf(f
, "action %s", police_action_n2a(p
->action
, b1
, sizeof(b1
)));
352 if (tb
[TCA_POLICE_RESULT
]) {
353 fprintf(f
, "/%s ", police_action_n2a(*(int*)RTA_DATA(tb
[TCA_POLICE_RESULT
]), b1
, sizeof(b1
)));
356 fprintf(f
, "\nref %d bind %d\n",p
->refcnt
, p
->bindcnt
);
362 tc_print_police(FILE *f
, struct rtattr
*arg
) {
363 return print_police(&police_action_util
,f
,arg
);