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