libnl 2.0
|
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 void class_dump_line(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 tca_dump_line((struct rtnl_tca *) class, "class", p); 00064 00065 cops = rtnl_class_lookup_ops(class); 00066 if (cops && cops->co_dump[NL_DUMP_LINE]) 00067 cops->co_dump[NL_DUMP_LINE](class, p); 00068 nl_dump(p, "\n"); 00069 } 00070 00071 static void class_dump_details(struct nl_object *obj, struct nl_dump_params *p) 00072 { 00073 struct rtnl_class *class = (struct rtnl_class *) obj; 00074 struct rtnl_class_ops *cops; 00075 00076 class_dump_line(obj, p); 00077 tca_dump_details((struct rtnl_tca *) class, p); 00078 00079 if (class->c_info) { 00080 char buf[32]; 00081 nl_dump(p, "child-qdisc %s ", 00082 rtnl_tc_handle2str(class->c_info, buf, sizeof(buf))); 00083 } 00084 00085 cops = rtnl_class_lookup_ops(class); 00086 if (cops && cops->co_dump[NL_DUMP_DETAILS]) 00087 cops->co_dump[NL_DUMP_DETAILS](class, p); 00088 else if (!class->c_info) 00089 nl_dump(p, "noop (no leaf qdisc)"); 00090 00091 nl_dump(p, "\n"); 00092 } 00093 00094 static void class_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 00095 { 00096 struct rtnl_class *class = (struct rtnl_class *) obj; 00097 struct rtnl_class_ops *cops; 00098 00099 class_dump_details(obj, p); 00100 tca_dump_stats((struct rtnl_tca *) class, p); 00101 nl_dump(p, "\n"); 00102 00103 cops = rtnl_class_lookup_ops(class); 00104 if (cops && cops->co_dump[NL_DUMP_STATS]) 00105 cops->co_dump[NL_DUMP_STATS](class, p); 00106 } 00107 00108 /** 00109 * @name Allocation/Freeing 00110 * @{ 00111 */ 00112 00113 struct rtnl_class *rtnl_class_alloc(void) 00114 { 00115 return (struct rtnl_class *) nl_object_alloc(&class_obj_ops); 00116 } 00117 00118 void rtnl_class_put(struct rtnl_class *class) 00119 { 00120 nl_object_put((struct nl_object *) class); 00121 } 00122 00123 /** @} */ 00124 00125 /** 00126 * @name Leaf Qdisc 00127 * @{ 00128 */ 00129 00130 /** 00131 * Lookup the leaf qdisc of a class 00132 * @arg class the parent class 00133 * @arg cache a qdisc cache including at laest all qdiscs of the 00134 * interface the specified class is attached to 00135 * @return The qdisc from the cache or NULL if the class has no leaf qdisc 00136 */ 00137 struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class, 00138 struct nl_cache *cache) 00139 { 00140 struct rtnl_qdisc *leaf; 00141 00142 if (!class->c_info) 00143 return NULL; 00144 00145 leaf = rtnl_qdisc_get_by_parent(cache, class->c_ifindex, 00146 class->c_handle); 00147 if (!leaf || leaf->q_handle != class->c_info) 00148 return NULL; 00149 00150 return leaf; 00151 } 00152 00153 /** @} */ 00154 00155 00156 /** 00157 * @name Iterators 00158 * @{ 00159 */ 00160 00161 /** 00162 * Call a callback for each child of a class 00163 * @arg class the parent class 00164 * @arg cache a class cache including all classes of the interface 00165 * the specified class is attached to 00166 * @arg cb callback function 00167 * @arg arg argument to be passed to callback function 00168 */ 00169 void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache, 00170 void (*cb)(struct nl_object *, void *), void *arg) 00171 { 00172 struct rtnl_class *filter; 00173 00174 filter = rtnl_class_alloc(); 00175 if (!filter) 00176 return; 00177 00178 rtnl_class_set_parent(filter, class->c_handle); 00179 rtnl_class_set_ifindex(filter, class->c_ifindex); 00180 rtnl_class_set_kind(filter, class->c_kind); 00181 00182 nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); 00183 rtnl_class_put(filter); 00184 } 00185 00186 /** 00187 * Call a callback for each classifier attached to the class 00188 * @arg class the parent class 00189 * @arg cache a filter cache including at least all the filters 00190 * attached to the specified class 00191 * @arg cb callback function 00192 * @arg arg argument to be passed to callback function 00193 */ 00194 void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache, 00195 void (*cb)(struct nl_object *, void *), void *arg) 00196 { 00197 struct rtnl_cls *filter; 00198 00199 filter = rtnl_cls_alloc(); 00200 if (!filter) 00201 return; 00202 00203 rtnl_cls_set_ifindex(filter, class->c_ifindex); 00204 rtnl_cls_set_parent(filter, class->c_parent); 00205 00206 nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); 00207 rtnl_cls_put(filter); 00208 } 00209 00210 /** @} */ 00211 00212 00213 /** 00214 * @name Attributes 00215 * @{ 00216 */ 00217 00218 void rtnl_class_set_ifindex(struct rtnl_class *class, int ifindex) 00219 { 00220 tca_set_ifindex((struct rtnl_tca *) class, ifindex); 00221 } 00222 00223 int rtnl_class_get_ifindex(struct rtnl_class *class) 00224 { 00225 return tca_get_ifindex((struct rtnl_tca *) class); 00226 } 00227 00228 void rtnl_class_set_handle(struct rtnl_class *class, uint32_t handle) 00229 { 00230 tca_set_handle((struct rtnl_tca *) class, handle); 00231 } 00232 00233 uint32_t rtnl_class_get_handle(struct rtnl_class *class) 00234 { 00235 return tca_get_handle((struct rtnl_tca *) class); 00236 } 00237 00238 void rtnl_class_set_parent(struct rtnl_class *class, uint32_t parent) 00239 { 00240 tca_set_parent((struct rtnl_tca *) class, parent); 00241 } 00242 00243 uint32_t rtnl_class_get_parent(struct rtnl_class *class) 00244 { 00245 return tca_get_parent((struct rtnl_tca *) class); 00246 } 00247 00248 void rtnl_class_set_kind(struct rtnl_class *class, const char *name) 00249 { 00250 tca_set_kind((struct rtnl_tca *) class, name); 00251 class->c_ops = __rtnl_class_lookup_ops(name); 00252 } 00253 00254 char *rtnl_class_get_kind(struct rtnl_class *class) 00255 { 00256 return tca_get_kind((struct rtnl_tca *) class); 00257 } 00258 00259 uint64_t rtnl_class_get_stat(struct rtnl_class *class, 00260 enum rtnl_tc_stats_id id) 00261 { 00262 return tca_get_stat((struct rtnl_tca *) class, id); 00263 } 00264 00265 /** @} */ 00266 00267 struct nl_object_ops class_obj_ops = { 00268 .oo_name = "route/class", 00269 .oo_size = sizeof(struct rtnl_class), 00270 .oo_free_data = class_free_data, 00271 .oo_clone = class_clone, 00272 .oo_dump = { 00273 [NL_DUMP_LINE] = class_dump_line, 00274 [NL_DUMP_DETAILS] = class_dump_details, 00275 [NL_DUMP_STATS] = class_dump_stats, 00276 }, 00277 .oo_compare = tca_compare, 00278 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), 00279 }; 00280 00281 /** @} */