Home | History | Annotate | Download | only in route
      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 (at) 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 
     28 static 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 
     40 static 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);
     54 errout:
     55 	return err;
     56 }
     57 
     58 static 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 
     71 static 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 
     94 static 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 
    113 struct rtnl_class *rtnl_class_alloc(void)
    114 {
    115 	return (struct rtnl_class *) nl_object_alloc(&class_obj_ops);
    116 }
    117 
    118 void 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  */
    137 struct 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  */
    169 void 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  */
    194 void 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 
    218 void rtnl_class_set_ifindex(struct rtnl_class *class, int ifindex)
    219 {
    220 	tca_set_ifindex((struct rtnl_tca *) class, ifindex);
    221 }
    222 
    223 int rtnl_class_get_ifindex(struct rtnl_class *class)
    224 {
    225 	return tca_get_ifindex((struct rtnl_tca *) class);
    226 }
    227 
    228 void rtnl_class_set_handle(struct rtnl_class *class, uint32_t handle)
    229 {
    230 	tca_set_handle((struct rtnl_tca *) class, handle);
    231 }
    232 
    233 uint32_t rtnl_class_get_handle(struct rtnl_class *class)
    234 {
    235 	return tca_get_handle((struct rtnl_tca *) class);
    236 }
    237 
    238 void rtnl_class_set_parent(struct rtnl_class *class, uint32_t parent)
    239 {
    240 	tca_set_parent((struct rtnl_tca *) class, parent);
    241 }
    242 
    243 uint32_t rtnl_class_get_parent(struct rtnl_class *class)
    244 {
    245 	return tca_get_parent((struct rtnl_tca *) class);
    246 }
    247 
    248 void 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 
    254 char *rtnl_class_get_kind(struct rtnl_class *class)
    255 {
    256 	return tca_get_kind((struct rtnl_tca *) class);
    257 }
    258 
    259 uint64_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 
    267 struct 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