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 static int act_parse_police(struct action_util
*a
, int *argc_p
,
29 char ***argv_p
, int tca_id
, struct nlmsghdr
*n
);
30 static int print_police(struct action_util
*a
, FILE *f
, struct rtattr
*tb
);
32 struct action_util police_action_util
= {
34 .parse_aopt
= act_parse_police
,
35 .print_aopt
= print_police
,
38 static void usage(void)
41 "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n"
42 " [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n"
43 " [ linklayer TYPE ] [ CONTROL ]\n"
44 "Where: CONTROL := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT]\n"
45 " Define how to handle packets which exceed (<EXCEEDACT>)\n"
46 " or conform (<NOTEXCEEDACT>) the configured bandwidth limit.\n"
47 " EXCEEDACT/NOTEXCEEDACT := { pipe | ok | reclassify | drop | continue |\n"
48 " goto chain <CHAIN_INDEX> }\n");
52 static int act_parse_police(struct action_util
*a
, int *argc_p
, char ***argv_p
,
53 int tca_id
, struct nlmsghdr
*n
)
56 char **argv
= *argv_p
;
59 struct tc_police p
= { .action
= TC_POLICE_RECLASSIFY
};
64 unsigned buffer
= 0, mtu
= 0, mpu
= 0;
65 unsigned short overhead
= 0;
66 unsigned int linklayer
= LINKLAYER_ETHERNET
; /* Assume ethernet */
67 int Rcell_log
= -1, Pcell_log
= -1;
69 __u64 rate64
= 0, prate64
= 0;
71 if (a
) /* new way of doing things */
79 if (matches(*argv
, "index") == 0) {
81 if (get_u32(&p
.index
, *argv
, 10))
82 invarg("index", *argv
);
83 } else if (matches(*argv
, "burst") == 0 ||
84 strcmp(*argv
, "buffer") == 0 ||
85 strcmp(*argv
, "maxburst") == 0) {
88 duparg("buffer/burst", *argv
);
89 if (get_size_and_cell(&buffer
, &Rcell_log
, *argv
) < 0)
90 invarg("buffer", *argv
);
91 } else if (strcmp(*argv
, "mtu") == 0 ||
92 strcmp(*argv
, "minburst") == 0) {
95 duparg("mtu/minburst", *argv
);
96 if (get_size_and_cell(&mtu
, &Pcell_log
, *argv
) < 0)
98 } else if (strcmp(*argv
, "mpu") == 0) {
101 duparg("mpu", *argv
);
102 if (get_size(&mpu
, *argv
))
103 invarg("mpu", *argv
);
104 } else if (strcmp(*argv
, "rate") == 0) {
107 duparg("rate", *argv
);
108 if (get_rate64(&rate64
, *argv
))
109 invarg("rate", *argv
);
110 } else if (strcmp(*argv
, "avrate") == 0) {
113 duparg("avrate", *argv
);
114 if (get_rate(&avrate
, *argv
))
115 invarg("avrate", *argv
);
116 } else if (matches(*argv
, "peakrate") == 0) {
119 duparg("peakrate", *argv
);
120 if (get_rate64(&prate64
, *argv
))
121 invarg("peakrate", *argv
);
122 } else if (matches(*argv
, "reclassify") == 0 ||
123 matches(*argv
, "drop") == 0 ||
124 matches(*argv
, "shot") == 0 ||
125 matches(*argv
, "continue") == 0 ||
126 matches(*argv
, "pass") == 0 ||
127 matches(*argv
, "ok") == 0 ||
128 matches(*argv
, "pipe") == 0 ||
129 matches(*argv
, "goto") == 0) {
130 if (!parse_action_control(&argc
, &argv
, &p
.action
, false))
133 } else if (strcmp(*argv
, "conform-exceed") == 0) {
135 if (!parse_action_control_slash(&argc
, &argv
, &p
.action
,
139 } else if (matches(*argv
, "overhead") == 0) {
141 if (get_u16(&overhead
, *argv
, 10))
142 invarg("overhead", *argv
);
143 } else if (matches(*argv
, "linklayer") == 0) {
145 if (get_linklayer(&linklayer
, *argv
))
146 invarg("linklayer", *argv
);
147 } else if (strcmp(*argv
, "help") == 0) {
160 if (rate64
&& avrate
)
163 /* Must at least do late binding, use TB or ewma policing */
164 if (!rate64
&& !avrate
&& !p
.index
) {
165 fprintf(stderr
, "\"rate\" or \"avrate\" MUST be specified.\n");
169 /* When the TB policer is used, burst is required */
170 if (rate64
&& !buffer
&& !avrate
) {
171 fprintf(stderr
, "\"burst\" requires \"rate\".\n");
177 fprintf(stderr
, "\"peakrate\" requires \"rate\".\n");
181 fprintf(stderr
, "\"mtu\" is required, if \"peakrate\" is requested.\n");
187 p
.rate
.rate
= (rate64
>= (1ULL << 32)) ? ~0U : rate64
;
189 p
.rate
.overhead
= overhead
;
190 if (tc_calc_rtable_64(&p
.rate
, rtab
, Rcell_log
, mtu
,
191 linklayer
, rate64
) < 0) {
192 fprintf(stderr
, "POLICE: failed to calculate rate table.\n");
195 p
.burst
= tc_calc_xmittime(rate64
, buffer
);
199 p
.peakrate
.rate
= (prate64
>= (1ULL << 32)) ? ~0U : prate64
;
200 p
.peakrate
.mpu
= mpu
;
201 p
.peakrate
.overhead
= overhead
;
202 if (tc_calc_rtable_64(&p
.peakrate
, ptab
, Pcell_log
, mtu
,
203 linklayer
, prate64
) < 0) {
204 fprintf(stderr
, "POLICE: failed to calculate peak rate table.\n");
209 tail
= addattr_nest(n
, MAX_MSG
, tca_id
);
210 addattr_l(n
, MAX_MSG
, TCA_POLICE_TBF
, &p
, sizeof(p
));
212 addattr_l(n
, MAX_MSG
, TCA_POLICE_RATE
, rtab
, 1024);
213 if (rate64
>= (1ULL << 32))
214 addattr64(n
, MAX_MSG
, TCA_POLICE_RATE64
, rate64
);
217 addattr_l(n
, MAX_MSG
, TCA_POLICE_PEAKRATE
, ptab
, 1024);
218 if (prate64
>= (1ULL << 32))
219 addattr64(n
, MAX_MSG
, TCA_POLICE_PEAKRATE64
, prate64
);
222 addattr32(n
, MAX_MSG
, TCA_POLICE_AVRATE
, avrate
);
224 addattr32(n
, MAX_MSG
, TCA_POLICE_RESULT
, presult
);
226 addattr_nest_end(n
, tail
);
234 int parse_police(int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
236 return act_parse_police(NULL
, argc_p
, argv_p
, tca_id
, n
);
239 static int print_police(struct action_util
*a
, FILE *f
, struct rtattr
*arg
)
244 struct rtattr
*tb
[TCA_POLICE_MAX
+1];
246 unsigned int linklayer
;
247 __u64 rate64
, prate64
;
252 parse_rtattr_nested(tb
, TCA_POLICE_MAX
, arg
);
254 if (tb
[TCA_POLICE_TBF
] == NULL
) {
255 fprintf(f
, "[NULL police tbf]");
258 #ifndef STOOPID_8BYTE
259 if (RTA_PAYLOAD(tb
[TCA_POLICE_TBF
]) < sizeof(*p
)) {
260 fprintf(f
, "[truncated police tbf]");
264 p
= RTA_DATA(tb
[TCA_POLICE_TBF
]);
266 rate64
= p
->rate
.rate
;
267 if (tb
[TCA_POLICE_RATE64
] &&
268 RTA_PAYLOAD(tb
[TCA_POLICE_RATE64
]) >= sizeof(rate64
))
269 rate64
= rta_getattr_u64(tb
[TCA_POLICE_RATE64
]);
271 fprintf(f
, " police 0x%x ", p
->index
);
272 fprintf(f
, "rate %s ", sprint_rate(rate64
, b1
));
273 buffer
= tc_calc_xmitsize(rate64
, p
->burst
);
274 fprintf(f
, "burst %s ", sprint_size(buffer
, b1
));
275 fprintf(f
, "mtu %s ", sprint_size(p
->mtu
, b1
));
277 fprintf(f
, "[%08x] ", p
->burst
);
279 prate64
= p
->peakrate
.rate
;
280 if (tb
[TCA_POLICE_PEAKRATE64
] &&
281 RTA_PAYLOAD(tb
[TCA_POLICE_PEAKRATE64
]) >= sizeof(prate64
))
282 prate64
= rta_getattr_u64(tb
[TCA_POLICE_PEAKRATE64
]);
285 fprintf(f
, "peakrate %s ", sprint_rate(prate64
, b1
));
287 if (tb
[TCA_POLICE_AVRATE
])
288 fprintf(f
, "avrate %s ",
289 sprint_rate(rta_getattr_u32(tb
[TCA_POLICE_AVRATE
]),
292 print_action_control(f
, "action ", p
->action
, "");
294 if (tb
[TCA_POLICE_RESULT
]) {
295 __u32 action
= rta_getattr_u32(tb
[TCA_POLICE_RESULT
]);
297 print_action_control(f
, "/", action
, " ");
301 fprintf(f
, "overhead %ub ", p
->rate
.overhead
);
302 linklayer
= (p
->rate
.linklayer
& TC_LINKLAYER_MASK
);
303 if (linklayer
> TC_LINKLAYER_ETHERNET
|| show_details
)
304 fprintf(f
, "linklayer %s ", sprint_linklayer(linklayer
, b2
));
305 fprintf(f
, "\n\tref %d bind %d", p
->refcnt
, p
->bindcnt
);
307 if (tb
[TCA_POLICE_TM
]) {
308 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_POLICE_TM
]);
319 int tc_print_police(FILE *f
, struct rtattr
*arg
)
321 return print_police(&police_action_util
, f
, arg
);