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