libnl 1.1
lib/route/class_obj.c
00001 /*
00002  * lib/route/class.c            Queueing Classes
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup class
00014  * @defgroup class_obj Class Object
00015  * @{
00016  */
00017 
00018 #include <netlink-local.h>
00019 #include <netlink-tc.h>
00020 #include <netlink/netlink.h>
00021 #include <netlink/route/tc.h>
00022 #include <netlink/route/class.h>
00023 #include <netlink/route/class-modules.h>
00024 #include <netlink/route/qdisc.h>
00025 #include <netlink/route/classifier.h>
00026 #include <netlink/utils.h>
00027 
00028 static void class_free_data(struct nl_object *obj)
00029 {
00030         struct rtnl_class *class = (struct rtnl_class *) obj;
00031         struct rtnl_class_ops *cops;
00032         
00033         tca_free_data((struct rtnl_tca *) class);
00034 
00035         cops = rtnl_class_lookup_ops(class);
00036         if (cops && cops->co_free_data)
00037                 cops->co_free_data(class);
00038 }
00039 
00040 static int class_clone(struct nl_object *_dst, struct nl_object *_src)
00041 {
00042         struct rtnl_class *dst = nl_object_priv(_dst);
00043         struct rtnl_class *src = nl_object_priv(_src);
00044         struct rtnl_class_ops *cops;
00045         int err;
00046 
00047         err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
00048         if (err < 0)
00049                 goto errout;
00050 
00051         cops = rtnl_class_lookup_ops(src);
00052         if (cops && cops->co_clone)
00053                 err = cops->co_clone(dst, src);
00054 errout:
00055         return err;
00056 }
00057 
00058 static int class_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00059 {
00060         struct rtnl_class *class = (struct rtnl_class *) obj;
00061         struct rtnl_class_ops *cops;
00062 
00063         int line = tca_dump_brief((struct rtnl_tca *) class, "class", p, 0);
00064 
00065         cops = rtnl_class_lookup_ops(class);
00066         if (cops && cops->co_dump[NL_DUMP_BRIEF])
00067                 line = cops->co_dump[NL_DUMP_BRIEF](class, p, line);
00068         dp_dump(p, "\n");
00069 
00070         return line;
00071 }
00072 
00073 static int class_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00074 {
00075         struct rtnl_class *class = (struct rtnl_class *) obj;
00076         struct rtnl_class_ops *cops;
00077         int line;
00078 
00079         line = class_dump_brief(obj, p);
00080         line = tca_dump_full((struct rtnl_tca *) class, p, line);
00081         
00082         if (class->c_info) {
00083                 char buf[32];
00084                 dp_dump(p, "child-qdisc %s ",
00085                         rtnl_tc_handle2str(class->c_info, buf, sizeof(buf)));
00086         }
00087 
00088         cops = rtnl_class_lookup_ops(class);
00089         if (cops && cops->co_dump[NL_DUMP_FULL])
00090                 line = cops->co_dump[NL_DUMP_FULL](class, p, line);
00091         else if (!class->c_info)
00092                 dp_dump(p, "noop (no leaf qdisc)");
00093 
00094         dp_dump(p, "\n");
00095 
00096         return line;
00097 }
00098 
00099 static int class_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00100 {
00101         struct rtnl_class *class = (struct rtnl_class *) obj;
00102         struct rtnl_class_ops *cops;
00103         int line;
00104 
00105         line = class_dump_full(obj, p);
00106         line = tca_dump_stats((struct rtnl_tca *) class, p, line);
00107         dp_dump(p, "\n");
00108 
00109         cops = rtnl_class_lookup_ops(class);
00110         if (cops && cops->co_dump[NL_DUMP_STATS])
00111                 line = cops->co_dump[NL_DUMP_STATS](class, p, line);
00112 
00113         return line;
00114 }
00115 
00116 /**
00117  * @name Allocation/Freeing
00118  * @{
00119  */
00120 
00121 struct rtnl_class *rtnl_class_alloc(void)
00122 {
00123         return (struct rtnl_class *) nl_object_alloc(&class_obj_ops);
00124 }
00125 
00126 void rtnl_class_put(struct rtnl_class *class)
00127 {
00128         nl_object_put((struct nl_object *) class);
00129 }
00130 
00131 /** @} */
00132 
00133 /**
00134  * @name Leaf Qdisc
00135  * @{
00136  */
00137 
00138 /**
00139  * Lookup the leaf qdisc of a class
00140  * @arg class           the parent class
00141  * @arg cache           a qdisc cache including at laest all qdiscs of the
00142  *                      interface the specified class is attached to
00143  * @return The qdisc from the cache or NULL if the class has no leaf qdisc
00144  */
00145 struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class,
00146                                          struct nl_cache *cache)
00147 {
00148         struct rtnl_qdisc *leaf;
00149 
00150         if (!class->c_info)
00151                 return NULL;
00152 
00153         leaf = rtnl_qdisc_get_by_parent(cache, class->c_ifindex,
00154                                         class->c_handle);
00155         if (!leaf || leaf->q_handle != class->c_info)
00156                 return NULL;
00157 
00158         return leaf;
00159 }
00160 
00161 /** @} */
00162 
00163 
00164 /**
00165  * @name Iterators
00166  * @{
00167  */
00168 
00169 /**
00170  * Call a callback for each child of a class
00171  * @arg class           the parent class
00172  * @arg cache           a class cache including all classes of the interface
00173  *                      the specified class is attached to
00174  * @arg cb              callback function
00175  * @arg arg             argument to be passed to callback function
00176  */
00177 void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache,
00178                               void (*cb)(struct nl_object *, void *), void *arg)
00179 {
00180         struct rtnl_class *filter;
00181         
00182         filter = rtnl_class_alloc();
00183         if (!filter)
00184                 return;
00185 
00186         rtnl_class_set_parent(filter, class->c_handle);
00187         rtnl_class_set_ifindex(filter, class->c_ifindex);
00188         rtnl_class_set_kind(filter, class->c_kind);
00189 
00190         nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
00191         rtnl_class_put(filter);
00192 }
00193 
00194 /**
00195  * Call a callback for each classifier attached to the class
00196  * @arg class           the parent class
00197  * @arg cache           a filter cache including at least all the filters
00198  *                      attached to the specified class
00199  * @arg cb              callback function
00200  * @arg arg             argument to be passed to callback function
00201  */
00202 void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache,
00203                             void (*cb)(struct nl_object *, void *), void *arg)
00204 {
00205         struct rtnl_cls *filter;
00206 
00207         filter = rtnl_cls_alloc();
00208         if (!filter)
00209                 return;
00210 
00211         rtnl_cls_set_ifindex(filter, class->c_ifindex);
00212         rtnl_cls_set_parent(filter, class->c_parent);
00213 
00214         nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
00215         rtnl_cls_put(filter);
00216 }
00217 
00218 /** @} */
00219 
00220 
00221 /**
00222  * @name Attributes
00223  * @{
00224  */
00225 
00226 void rtnl_class_set_ifindex(struct rtnl_class *class, int ifindex)
00227 {
00228         tca_set_ifindex((struct rtnl_tca *) class, ifindex);
00229 }
00230 
00231 int rtnl_class_get_ifindex(struct rtnl_class *class)
00232 {
00233         return tca_get_ifindex((struct rtnl_tca *) class);
00234 }
00235 
00236 void rtnl_class_set_handle(struct rtnl_class *class, uint32_t handle)
00237 {
00238         tca_set_handle((struct rtnl_tca *) class, handle);
00239 }
00240 
00241 uint32_t rtnl_class_get_handle(struct rtnl_class *class)
00242 {
00243         return tca_get_handle((struct rtnl_tca *) class);
00244 }
00245 
00246 void rtnl_class_set_parent(struct rtnl_class *class, uint32_t parent)
00247 {
00248         tca_set_parent((struct rtnl_tca *) class, parent);
00249 }
00250 
00251 uint32_t rtnl_class_get_parent(struct rtnl_class *class)
00252 {
00253         return tca_get_parent((struct rtnl_tca *) class);
00254 }
00255 
00256 void rtnl_class_set_kind(struct rtnl_class *class, const char *name)
00257 {
00258         tca_set_kind((struct rtnl_tca *) class, name);
00259         class->c_ops = __rtnl_class_lookup_ops(name);
00260 }
00261 
00262 char *rtnl_class_get_kind(struct rtnl_class *class)
00263 {
00264         return tca_get_kind((struct rtnl_tca *) class);
00265 }
00266 
00267 uint64_t rtnl_class_get_stat(struct rtnl_class *class,
00268                              enum rtnl_tc_stats_id id)
00269 {
00270         return tca_get_stat((struct rtnl_tca *) class, id);
00271 }
00272 
00273 /** @} */
00274 
00275 struct nl_object_ops class_obj_ops = {
00276         .oo_name                = "route/class",
00277         .oo_size                = sizeof(struct rtnl_class),
00278         .oo_free_data           = class_free_data,
00279         .oo_clone               = class_clone,
00280         .oo_dump[NL_DUMP_BRIEF] = class_dump_brief,
00281         .oo_dump[NL_DUMP_FULL]  = class_dump_full,
00282         .oo_dump[NL_DUMP_STATS] = class_dump_stats,
00283         .oo_compare             = tca_compare,
00284         .oo_id_attrs            = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
00285 };
00286 
00287 /** @} */