class_obj.c revision d84430702496f617c01c5e2d27d0e82e02390bb7
1/*
2 * lib/route/class.c            Queueing Classes
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/**
13 * @ingroup class
14 * @defgroup class_obj Class Object
15 * @{
16 */
17
18#include <netlink-local.h>
19#include <netlink-tc.h>
20#include <netlink/netlink.h>
21#include <netlink/route/tc.h>
22#include <netlink/route/class.h>
23#include <netlink/route/class-modules.h>
24#include <netlink/route/qdisc.h>
25#include <netlink/route/classifier.h>
26#include <netlink/utils.h>
27
28static void class_free_data(struct nl_object *obj)
29{
30	struct rtnl_class *class = (struct rtnl_class *) obj;
31	struct rtnl_class_ops *cops;
32
33	tca_free_data((struct rtnl_tca *) class);
34
35	cops = rtnl_class_lookup_ops(class);
36	if (cops && cops->co_free_data)
37		cops->co_free_data(class);
38}
39
40static int class_clone(struct nl_object *_dst, struct nl_object *_src)
41{
42	struct rtnl_class *dst = nl_object_priv(_dst);
43	struct rtnl_class *src = nl_object_priv(_src);
44	struct rtnl_class_ops *cops;
45	int err;
46
47	err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
48	if (err < 0)
49		goto errout;
50
51	cops = rtnl_class_lookup_ops(src);
52	if (cops && cops->co_clone)
53		err = cops->co_clone(dst, src);
54errout:
55	return err;
56}
57
58static void class_dump_line(struct nl_object *obj, struct nl_dump_params *p)
59{
60	struct rtnl_class *class = (struct rtnl_class *) obj;
61	struct rtnl_class_ops *cops;
62
63	tca_dump_line((struct rtnl_tca *) class, "class", p);
64
65	cops = rtnl_class_lookup_ops(class);
66	if (cops && cops->co_dump[NL_DUMP_LINE])
67		cops->co_dump[NL_DUMP_LINE](class, p);
68	nl_dump(p, "\n");
69}
70
71static void class_dump_details(struct nl_object *obj, struct nl_dump_params *p)
72{
73	struct rtnl_class *class = (struct rtnl_class *) obj;
74	struct rtnl_class_ops *cops;
75
76	class_dump_line(obj, p);
77	tca_dump_details((struct rtnl_tca *) class, p);
78
79	if (class->c_info) {
80		char buf[32];
81		nl_dump(p, "child-qdisc %s ",
82			rtnl_tc_handle2str(class->c_info, buf, sizeof(buf)));
83	}
84
85	cops = rtnl_class_lookup_ops(class);
86	if (cops && cops->co_dump[NL_DUMP_DETAILS])
87		cops->co_dump[NL_DUMP_DETAILS](class, p);
88	else if (!class->c_info)
89		nl_dump(p, "noop (no leaf qdisc)");
90
91	nl_dump(p, "\n");
92}
93
94static void class_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
95{
96	struct rtnl_class *class = (struct rtnl_class *) obj;
97	struct rtnl_class_ops *cops;
98
99	class_dump_details(obj, p);
100	tca_dump_stats((struct rtnl_tca *) class, p);
101	nl_dump(p, "\n");
102
103	cops = rtnl_class_lookup_ops(class);
104	if (cops && cops->co_dump[NL_DUMP_STATS])
105		cops->co_dump[NL_DUMP_STATS](class, p);
106}
107
108/**
109 * @name Allocation/Freeing
110 * @{
111 */
112
113struct rtnl_class *rtnl_class_alloc(void)
114{
115	return (struct rtnl_class *) nl_object_alloc(&class_obj_ops);
116}
117
118void rtnl_class_put(struct rtnl_class *class)
119{
120	nl_object_put((struct nl_object *) class);
121}
122
123/** @} */
124
125/**
126 * @name Leaf Qdisc
127 * @{
128 */
129
130/**
131 * Lookup the leaf qdisc of a class
132 * @arg class		the parent class
133 * @arg cache		a qdisc cache including at laest all qdiscs of the
134 *                      interface the specified class is attached to
135 * @return The qdisc from the cache or NULL if the class has no leaf qdisc
136 */
137struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class,
138					 struct nl_cache *cache)
139{
140	struct rtnl_qdisc *leaf;
141
142	if (!class->c_info)
143		return NULL;
144
145	leaf = rtnl_qdisc_get_by_parent(cache, class->c_ifindex,
146					class->c_handle);
147	if (!leaf || leaf->q_handle != class->c_info)
148		return NULL;
149
150	return leaf;
151}
152
153/** @} */
154
155
156/**
157 * @name Iterators
158 * @{
159 */
160
161/**
162 * Call a callback for each child of a class
163 * @arg class		the parent class
164 * @arg cache		a class cache including all classes of the interface
165 *                      the specified class is attached to
166 * @arg cb              callback function
167 * @arg arg             argument to be passed to callback function
168 */
169void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache,
170			      void (*cb)(struct nl_object *, void *), void *arg)
171{
172	struct rtnl_class *filter;
173
174	filter = rtnl_class_alloc();
175	if (!filter)
176		return;
177
178	rtnl_class_set_parent(filter, class->c_handle);
179	rtnl_class_set_ifindex(filter, class->c_ifindex);
180	rtnl_class_set_kind(filter, class->c_kind);
181
182	nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
183	rtnl_class_put(filter);
184}
185
186/**
187 * Call a callback for each classifier attached to the class
188 * @arg class		the parent class
189 * @arg cache		a filter cache including at least all the filters
190 *                      attached to the specified class
191 * @arg cb              callback function
192 * @arg arg             argument to be passed to callback function
193 */
194void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache,
195			    void (*cb)(struct nl_object *, void *), void *arg)
196{
197	struct rtnl_cls *filter;
198
199	filter = rtnl_cls_alloc();
200	if (!filter)
201		return;
202
203	rtnl_cls_set_ifindex(filter, class->c_ifindex);
204	rtnl_cls_set_parent(filter, class->c_parent);
205
206	nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
207	rtnl_cls_put(filter);
208}
209
210/** @} */
211
212
213/**
214 * @name Attributes
215 * @{
216 */
217
218void rtnl_class_set_ifindex(struct rtnl_class *class, int ifindex)
219{
220	tca_set_ifindex((struct rtnl_tca *) class, ifindex);
221}
222
223int rtnl_class_get_ifindex(struct rtnl_class *class)
224{
225	return tca_get_ifindex((struct rtnl_tca *) class);
226}
227
228void rtnl_class_set_handle(struct rtnl_class *class, uint32_t handle)
229{
230	tca_set_handle((struct rtnl_tca *) class, handle);
231}
232
233uint32_t rtnl_class_get_handle(struct rtnl_class *class)
234{
235	return tca_get_handle((struct rtnl_tca *) class);
236}
237
238void rtnl_class_set_parent(struct rtnl_class *class, uint32_t parent)
239{
240	tca_set_parent((struct rtnl_tca *) class, parent);
241}
242
243uint32_t rtnl_class_get_parent(struct rtnl_class *class)
244{
245	return tca_get_parent((struct rtnl_tca *) class);
246}
247
248void rtnl_class_set_kind(struct rtnl_class *class, const char *name)
249{
250	tca_set_kind((struct rtnl_tca *) class, name);
251	class->c_ops = __rtnl_class_lookup_ops(name);
252}
253
254char *rtnl_class_get_kind(struct rtnl_class *class)
255{
256	return tca_get_kind((struct rtnl_tca *) class);
257}
258
259uint64_t rtnl_class_get_stat(struct rtnl_class *class,
260			     enum rtnl_tc_stats_id id)
261{
262	return tca_get_stat((struct rtnl_tca *) class, id);
263}
264
265/** @} */
266
267struct nl_object_ops class_obj_ops = {
268	.oo_name		= "route/class",
269	.oo_size		= sizeof(struct rtnl_class),
270	.oo_free_data         	= class_free_data,
271	.oo_clone		= class_clone,
272	.oo_dump = {
273	    [NL_DUMP_LINE]	= class_dump_line,
274	    [NL_DUMP_DETAILS]	= class_dump_details,
275	    [NL_DUMP_STATS]	= class_dump_stats,
276	},
277	.oo_compare		= tca_compare,
278	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
279};
280
281/** @} */
282