libnl  3.2.24-rc1
cbq.c
1 /*
2  * lib/route/qdisc/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-2011 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 #include <netlink-private/netlink.h>
13 #include <netlink-private/tc.h>
14 #include <netlink/netlink.h>
15 #include <netlink/utils.h>
16 #include <netlink-private/route/tc-api.h>
17 #include <netlink/route/qdisc.h>
18 #include <netlink/route/class.h>
19 #include <netlink/route/link.h>
20 #include <netlink/route/qdisc/cbq.h>
21 #include <netlink/route/cls/police.h>
22 
23 /**
24  * @ingroup qdisc
25  * @ingroup class
26  * @defgroup qdisc_cbq Class Based Queueing (CBQ)
27  * @{
28  */
29 
30 static const struct trans_tbl ovl_strategies[] = {
31  __ADD(TC_CBQ_OVL_CLASSIC,classic)
32  __ADD(TC_CBQ_OVL_DELAY,delay)
33  __ADD(TC_CBQ_OVL_LOWPRIO,lowprio)
34  __ADD(TC_CBQ_OVL_DROP,drop)
35  __ADD(TC_CBQ_OVL_RCLASSIC,rclassic)
36 };
37 
38 /**
39  * Convert a CBQ OVL strategy to a character string
40  * @arg type CBQ OVL strategy
41  * @arg buf destination buffer
42  * @arg len length of destination buffer
43  *
44  * Converts a CBQ OVL strategy to a character string and stores in the
45  * provided buffer. Returns the destination buffer or the type
46  * encoded in hex if no match was found.
47  */
48 char *nl_ovl_strategy2str(int type, char *buf, size_t len)
49 {
50  return __type2str(type, buf, len, ovl_strategies,
51  ARRAY_SIZE(ovl_strategies));
52 }
53 
54 /**
55  * Convert a string to a CBQ OVL strategy
56  * @arg name CBQ OVL stragegy name
57  *
58  * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy
59  * type. Returns the type or -1 if none was found.
60  */
61 int nl_str2ovl_strategy(const char *name)
62 {
63  return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies));
64 }
65 
66 static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
67  [TCA_CBQ_LSSOPT] = { .minlen = sizeof(struct tc_cbq_lssopt) },
68  [TCA_CBQ_RATE] = { .minlen = sizeof(struct tc_ratespec) },
69  [TCA_CBQ_WRROPT] = { .minlen = sizeof(struct tc_cbq_wrropt) },
70  [TCA_CBQ_OVL_STRATEGY] = { .minlen = sizeof(struct tc_cbq_ovl) },
71  [TCA_CBQ_FOPT] = { .minlen = sizeof(struct tc_cbq_fopt) },
72  [TCA_CBQ_POLICE] = { .minlen = sizeof(struct tc_cbq_police) },
73 };
74 
75 static int cbq_msg_parser(struct rtnl_tc *tc, void *data)
76 {
77  struct nlattr *tb[TCA_CBQ_MAX + 1];
78  struct rtnl_cbq *cbq = data;
79  int err;
80 
81  err = tca_parse(tb, TCA_CBQ_MAX, tc, cbq_policy);
82  if (err < 0)
83  return err;
84 
85  nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
86  nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
87  nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
88  nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt));
89  nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY],
90  sizeof(cbq->cbq_ovl));
91  nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE],
92  sizeof(cbq->cbq_police));
93 
94  return 0;
95 }
96 
97 static void cbq_dump_line(struct rtnl_tc *tc, void *data,
98  struct nl_dump_params *p)
99 {
100  struct rtnl_cbq *cbq = data;
101  double r, rbit;
102  char *ru, *rubit;
103 
104  if (!cbq)
105  return;
106 
107  r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru);
108  rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit);
109 
110  nl_dump(p, " rate %.2f%s/s (%.0f%s) prio %u",
111  r, ru, rbit, rubit, cbq->cbq_wrr.priority);
112 }
113 
114 static void cbq_dump_details(struct rtnl_tc *tc, void *data,
115  struct nl_dump_params *p)
116 {
117  struct rtnl_cbq *cbq = data;
118  char *unit, buf[32];
119  double w;
120  uint32_t el;
121 
122  if (!cbq)
123  return;
124 
125  w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit);
126 
127  nl_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n",
128  cbq->cbq_lss.avpkt,
129  cbq->cbq_rate.mpu,
130  1 << cbq->cbq_rate.cell_log,
131  cbq->cbq_wrr.allot, w, unit);
132 
133  el = cbq->cbq_lss.ewma_log;
134  nl_dump_line(p, " minidle %uus maxidle %uus offtime "
135  "%uus level %u ewma_log %u\n",
136  nl_ticks2us(cbq->cbq_lss.minidle >> el),
137  nl_ticks2us(cbq->cbq_lss.maxidle >> el),
138  nl_ticks2us(cbq->cbq_lss.offtime >> el),
139  cbq->cbq_lss.level,
140  cbq->cbq_lss.ewma_log);
141 
142  nl_dump_line(p, " penalty %uus strategy %s ",
143  nl_ticks2us(cbq->cbq_ovl.penalty),
144  nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf)));
145 
146  nl_dump(p, "split %s defmap 0x%08x ",
147  rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)),
148  cbq->cbq_fopt.defmap);
149 
150  nl_dump(p, "police %s",
151  nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
152 }
153 
154 static void cbq_dump_stats(struct rtnl_tc *tc, void *data,
155  struct nl_dump_params *p)
156 {
157  struct tc_cbq_xstats *x;
158 
159  if (!(x = tca_xstats(tc)))
160  return;
161 
162  nl_dump_line(p, " borrows overact "
163  " avgidle undertime\n");
164  nl_dump_line(p, " %10u %10u %10u %10u\n",
165  x->borrows, x->overactions, x->avgidle, x->undertime);
166 }
167 
168 static struct rtnl_tc_ops cbq_qdisc_ops = {
169  .to_kind = "cbq",
170  .to_type = RTNL_TC_TYPE_QDISC,
171  .to_size = sizeof(struct rtnl_cbq),
172  .to_msg_parser = cbq_msg_parser,
173  .to_dump = {
174  [NL_DUMP_LINE] = cbq_dump_line,
175  [NL_DUMP_DETAILS] = cbq_dump_details,
176  [NL_DUMP_STATS] = cbq_dump_stats,
177  },
178 };
179 
180 static struct rtnl_tc_ops cbq_class_ops = {
181  .to_kind = "cbq",
182  .to_type = RTNL_TC_TYPE_CLASS,
183  .to_size = sizeof(struct rtnl_cbq),
184  .to_msg_parser = cbq_msg_parser,
185  .to_dump = {
186  [NL_DUMP_LINE] = cbq_dump_line,
187  [NL_DUMP_DETAILS] = cbq_dump_details,
188  [NL_DUMP_STATS] = cbq_dump_stats,
189  },
190 };
191 
192 static void __init cbq_init(void)
193 {
194  rtnl_tc_register(&cbq_qdisc_ops);
195  rtnl_tc_register(&cbq_class_ops);
196 }
197 
198 static void __exit cbq_exit(void)
199 {
200  rtnl_tc_unregister(&cbq_qdisc_ops);
201  rtnl_tc_unregister(&cbq_class_ops);
202 }
203 
204 /** @} */