• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
nl_ovl_strategy2str(int type,char * buf,size_t len)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  */
nl_str2ovl_strategy(const char * name)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 
cbq_msg_parser(struct rtnl_tc * tc,void * data)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 
cbq_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)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 
cbq_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)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 
cbq_dump_stats(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)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 
cbq_init(void)192 static void __init cbq_init(void)
193 {
194 	rtnl_tc_register(&cbq_qdisc_ops);
195 	rtnl_tc_register(&cbq_class_ops);
196 }
197 
cbq_exit(void)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 /** @} */
205