libnl  1.1.4
cbq.c
1 /*
2  * lib/route/sch/cbq.c Class Based Queueing
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 #include <netlink-local.h>
13 #include <netlink-tc.h>
14 #include <netlink/netlink.h>
15 #include <netlink/utils.h>
16 #include <netlink/route/qdisc.h>
17 #include <netlink/route/qdisc-modules.h>
18 #include <netlink/route/class.h>
19 #include <netlink/route/class-modules.h>
20 #include <netlink/route/link.h>
21 #include <netlink/route/sch/cbq.h>
22 #include <netlink/route/cls/police.h>
23 
24 /**
25  * @ingroup qdisc_api
26  * @ingroup class_api
27  * @defgroup cbq Class Based Queueing (CBQ)
28  * @{
29  */
30 
31 static struct trans_tbl ovl_strategies[] = {
32  __ADD(TC_CBQ_OVL_CLASSIC,classic)
33  __ADD(TC_CBQ_OVL_DELAY,delay)
34  __ADD(TC_CBQ_OVL_LOWPRIO,lowprio)
35  __ADD(TC_CBQ_OVL_DROP,drop)
36  __ADD(TC_CBQ_OVL_RCLASSIC,rclassic)
37 };
38 
39 /**
40  * Convert a CBQ OVL strategy to a character string
41  * @arg type CBQ OVL strategy
42  * @arg buf destination buffer
43  * @arg len length of destination buffer
44  *
45  * Converts a CBQ OVL strategy to a character string and stores in the
46  * provided buffer. Returns the destination buffer or the type
47  * encoded in hex if no match was found.
48  */
49 char *nl_ovl_strategy2str(int type, char *buf, size_t len)
50 {
51  return __type2str(type, buf, len, ovl_strategies,
52  ARRAY_SIZE(ovl_strategies));
53 }
54 
55 /**
56  * Convert a string to a CBQ OVL strategy
57  * @arg name CBQ OVL stragegy name
58  *
59  * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy
60  * type. Returns the type or -1 if none was found.
61  */
62 int nl_str2ovl_strategy(const char *name)
63 {
64  return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies));
65 }
66 
67 static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
68  [TCA_CBQ_LSSOPT] = { .minlen = sizeof(struct tc_cbq_lssopt) },
69  [TCA_CBQ_RATE] = { .minlen = sizeof(struct tc_ratespec) },
70  [TCA_CBQ_WRROPT] = { .minlen = sizeof(struct tc_cbq_wrropt) },
71  [TCA_CBQ_OVL_STRATEGY] = { .minlen = sizeof(struct tc_cbq_ovl) },
72  [TCA_CBQ_FOPT] = { .minlen = sizeof(struct tc_cbq_fopt) },
73  [TCA_CBQ_POLICE] = { .minlen = sizeof(struct tc_cbq_police) },
74 };
75 
76 static inline struct rtnl_cbq *cbq_qdisc(struct rtnl_tca *tca)
77 {
78  return (struct rtnl_cbq *) tca->tc_subdata;
79 }
80 
81 static inline struct rtnl_cbq *cbq_alloc(struct rtnl_tca *tca)
82 {
83  if (!tca->tc_subdata)
84  tca->tc_subdata = calloc(1, sizeof(struct rtnl_qdisc));
85 
86  return cbq_qdisc(tca);
87 }
88 
89 
90 static int cbq_msg_parser(struct rtnl_tca *tca)
91 {
92  struct nlattr *tb[TCA_CBQ_MAX + 1];
93  struct rtnl_cbq *cbq;
94  int err;
95 
96  err = tca_parse(tb, TCA_CBQ_MAX, tca, cbq_policy);
97  if (err < 0)
98  return err;
99 
100  cbq = cbq_alloc(tca);
101  if (!cbq)
102  return nl_errno(ENOMEM);
103 
104  nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
105  nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
106  nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
107  nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt));
108  nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY],
109  sizeof(cbq->cbq_ovl));
110  nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE],
111  sizeof(cbq->cbq_police));
112 
113  return 0;
114 }
115 
116 static int cbq_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
117 {
118  return cbq_msg_parser((struct rtnl_tca *) qdisc);
119 }
120 
121 static int cbq_class_msg_parser(struct rtnl_class *class)
122 {
123  return cbq_msg_parser((struct rtnl_tca *) class);
124 }
125 
126 static void cbq_qdisc_free_data(struct rtnl_qdisc *qdisc)
127 {
128  free(qdisc->q_subdata);
129 }
130 
131 static int cbq_clone(struct rtnl_tca *_dst, struct rtnl_tca *_src)
132 {
133  struct rtnl_cbq *src = cbq_qdisc(_src);
134 
135  if (src && !cbq_alloc(_dst))
136  return nl_errno(ENOMEM);
137  else
138  return 0;
139 }
140 
141 static int cbq_qdisc_clone(struct rtnl_qdisc *dst, struct rtnl_qdisc *src)
142 {
143  return cbq_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
144 }
145 
146 static void cbq_class_free_data(struct rtnl_class *class)
147 {
148  free(class->c_subdata);
149 }
150 
151 static int cbq_class_clone(struct rtnl_class *dst, struct rtnl_class *src)
152 {
153  return cbq_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
154 }
155 
156 static int cbq_dump_brief(struct rtnl_tca *tca, struct nl_dump_params *p,
157  int line)
158 {
159  struct rtnl_cbq *cbq;
160  double r, rbit;
161  char *ru, *rubit;
162 
163  cbq = cbq_qdisc(tca);
164  if (!cbq)
165  goto ignore;
166 
167  r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru);
168  rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit);
169 
170  dp_dump(p, " rate %.2f%s/s (%.0f%s) prio %u",
171  r, ru, rbit, rubit, cbq->cbq_wrr.priority);
172 
173 ignore:
174  return line;
175 }
176 
177 static int cbq_qdisc_dump_brief(struct rtnl_qdisc *qdisc,
178  struct nl_dump_params *p, int line)
179 {
180  return cbq_dump_brief((struct rtnl_tca *) qdisc, p, line);
181 }
182 
183 static int cbq_class_dump_brief(struct rtnl_class *class,
184  struct nl_dump_params *p, int line)
185 {
186  return cbq_dump_brief((struct rtnl_tca *) class, p, line);
187 }
188 
189 static int cbq_dump_full(struct rtnl_tca *tca, struct nl_dump_params *p,
190  int line)
191 {
192  struct rtnl_cbq *cbq;
193  char *unit, buf[32];
194  double w;
195  uint32_t el;
196 
197  cbq = cbq_qdisc(tca);
198  if (!cbq)
199  goto ignore;
200 
201  w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit);
202 
203  dp_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n",
204  cbq->cbq_lss.avpkt,
205  cbq->cbq_rate.mpu,
206  1 << cbq->cbq_rate.cell_log,
207  cbq->cbq_wrr.allot, w, unit);
208 
209  el = cbq->cbq_lss.ewma_log;
210  dp_dump_line(p, line++, " minidle %uus maxidle %uus offtime "
211  "%uus level %u ewma_log %u\n",
212  nl_ticks2us(cbq->cbq_lss.minidle >> el),
213  nl_ticks2us(cbq->cbq_lss.maxidle >> el),
214  nl_ticks2us(cbq->cbq_lss.offtime >> el),
215  cbq->cbq_lss.level,
216  cbq->cbq_lss.ewma_log);
217 
218  dp_dump_line(p, line++, " penalty %uus strategy %s ",
219  nl_ticks2us(cbq->cbq_ovl.penalty),
220  nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf)));
221 
222  dp_dump(p, "split %s defmap 0x%08x ",
223  rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)),
224  cbq->cbq_fopt.defmap);
225 
226  dp_dump(p, "police %s",
227  nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
228 
229 ignore:
230  return line;
231 }
232 
233 static int cbq_qdisc_dump_full(struct rtnl_qdisc *qdisc,
234  struct nl_dump_params *p, int line)
235 {
236  return cbq_dump_full((struct rtnl_tca *) qdisc, p, line);
237 }
238 
239 static int cbq_class_dump_full(struct rtnl_class *class,
240  struct nl_dump_params *p, int line)
241 {
242  return cbq_dump_full((struct rtnl_tca *) class, p, line);
243 }
244 
245 static int cbq_dump_with_stats(struct rtnl_tca *tca, struct nl_dump_params *p,
246  int line)
247 {
248  struct tc_cbq_xstats *x = tca_xstats(tca);
249 
250  if (!x)
251  goto ignore;
252 
253  dp_dump_line(p, line++, " borrows overact "
254  " avgidle undertime\n");
255  dp_dump_line(p, line++, " %10u %10u %10u %10u\n",
256  x->borrows, x->overactions, x->avgidle, x->undertime);
257 
258 ignore:
259  return line;
260 }
261 
262 static int cbq_qdisc_dump_with_stats(struct rtnl_qdisc *qdisc,
263  struct nl_dump_params *p, int line)
264 {
265  return cbq_dump_with_stats((struct rtnl_tca *) qdisc, p, line);
266 }
267 
268 static int cbq_class_dump_with_stats(struct rtnl_class *class,
269  struct nl_dump_params *p, int line)
270 {
271  return cbq_dump_with_stats((struct rtnl_tca *) class, p, line);
272 }
273 
274 static struct rtnl_qdisc_ops cbq_qdisc_ops = {
275  .qo_kind = "cbq",
276  .qo_msg_parser = cbq_qdisc_msg_parser,
277  .qo_free_data = cbq_qdisc_free_data,
278  .qo_clone = cbq_qdisc_clone,
279  .qo_dump[NL_DUMP_BRIEF] = cbq_qdisc_dump_brief,
280  .qo_dump[NL_DUMP_FULL] = cbq_qdisc_dump_full,
281  .qo_dump[NL_DUMP_STATS] = cbq_qdisc_dump_with_stats,
282 };
283 
284 static struct rtnl_class_ops cbq_class_ops = {
285  .co_kind = "cbq",
286  .co_msg_parser = cbq_class_msg_parser,
287  .co_free_data = cbq_class_free_data,
288  .co_clone = cbq_class_clone,
289  .co_dump[NL_DUMP_BRIEF] = cbq_class_dump_brief,
290  .co_dump[NL_DUMP_FULL] = cbq_class_dump_full,
291  .co_dump[NL_DUMP_STATS] = cbq_class_dump_with_stats,
292 };
293 
294 static void __init cbq_init(void)
295 {
296  rtnl_qdisc_register(&cbq_qdisc_ops);
297  rtnl_class_register(&cbq_class_ops);
298 }
299 
300 static void __exit cbq_exit(void)
301 {
302  rtnl_qdisc_unregister(&cbq_qdisc_ops);
303  rtnl_class_unregister(&cbq_class_ops);
304 }
305 
306 /** @} */
Dump object in a brief one-liner.
Definition: types.h:22
char qo_kind[32]
Kind/Name of Qdisc.
Definition: qdisc-modules.h:30
int rtnl_class_register(struct rtnl_class_ops *cops)
Register a class module.
Definition: class_api.c:37
Class operations.
Definition: class-modules.h:25
attribute validation policy
Definition: attr.h:73
double nl_cancel_down_bits(unsigned long long l, char **unit)
Cancel down a bit counter.
Definition: utils.c:220
int rtnl_qdisc_unregister(struct rtnl_qdisc_ops *qops)
Unregister a qdisc module.
Definition: qdisc_api.c:61
int nla_memcpy(void *dest, struct nlattr *src, int count)
Copy a netlink attribute into another memory area.
Definition: attr.c:382
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
Definition: tc.c:493
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
Definition: utils.c:189
int rtnl_class_unregister(struct rtnl_class_ops *cops)
Unregister a class module.
Definition: class_api.c:58
uint32_t nl_ticks2us(uint32_t ticks)
Convert ticks to micro seconds.
Definition: utils.c:450
int nl_str2ovl_strategy(const char *name)
Convert a string to a CBQ OVL strategy.
Definition: cbq.c:62
uint16_t minlen
Minimal length of payload required to be available.
Definition: attr.h:78
int rtnl_qdisc_register(struct rtnl_qdisc_ops *qops)
Register a qdisc module.
Definition: qdisc_api.c:40
Dumping parameters.
Definition: types.h:36
Dump all attributes but no statistics.
Definition: types.h:23
Dump all attributes including statistics.
Definition: types.h:24
char * nl_ovl_strategy2str(int type, char *buf, size_t len)
Convert a CBQ OVL strategy to a character string.
Definition: cbq.c:49
Qdisc Operations.
Definition: qdisc-modules.h:25
char co_kind[32]
Kind/Name of class.
Definition: class-modules.h:30