libnl 1.1
|
00001 /* 00002 * lib/route/qdisc_obj.c Queueing Discipline Object 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 qdisc 00014 * @defgroup qdisc_obj Queueing Discipline Object 00015 * @{ 00016 */ 00017 00018 #include <netlink-local.h> 00019 #include <netlink-tc.h> 00020 #include <netlink/netlink.h> 00021 #include <netlink/utils.h> 00022 #include <netlink/route/link.h> 00023 #include <netlink/route/tc.h> 00024 #include <netlink/route/qdisc.h> 00025 #include <netlink/route/class.h> 00026 #include <netlink/route/classifier.h> 00027 #include <netlink/route/qdisc-modules.h> 00028 00029 static void qdisc_free_data(struct nl_object *obj) 00030 { 00031 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj; 00032 struct rtnl_qdisc_ops *qops; 00033 00034 tca_free_data((struct rtnl_tca *) qdisc); 00035 00036 qops = rtnl_qdisc_lookup_ops(qdisc); 00037 if (qops && qops->qo_free_data) 00038 qops->qo_free_data(qdisc); 00039 } 00040 00041 static int qdisc_clone(struct nl_object *_dst, struct nl_object *_src) 00042 { 00043 struct rtnl_qdisc *dst = (struct rtnl_qdisc *) _dst; 00044 struct rtnl_qdisc *src = (struct rtnl_qdisc *) _src; 00045 struct rtnl_qdisc_ops *qops; 00046 int err; 00047 00048 err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src); 00049 if (err < 0) 00050 goto errout; 00051 00052 qops = rtnl_qdisc_lookup_ops(src); 00053 if (qops && qops->qo_clone) 00054 err = qops->qo_clone(dst, src); 00055 errout: 00056 return err; 00057 } 00058 00059 static int qdisc_dump_brief(struct nl_object *obj, struct nl_dump_params *p) 00060 { 00061 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj; 00062 struct rtnl_qdisc_ops *qops; 00063 00064 int line = tca_dump_brief((struct rtnl_tca *) qdisc, "qdisc", p, 0); 00065 00066 qops = rtnl_qdisc_lookup_ops(qdisc); 00067 if (qops && qops->qo_dump[NL_DUMP_BRIEF]) 00068 line = qops->qo_dump[NL_DUMP_BRIEF](qdisc, p, line); 00069 00070 dp_dump(p, "\n"); 00071 00072 return line; 00073 } 00074 00075 static int qdisc_dump_full(struct nl_object *arg, struct nl_dump_params *p) 00076 { 00077 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) arg; 00078 struct rtnl_qdisc_ops *qops; 00079 00080 int line = qdisc_dump_brief(arg, p); 00081 00082 line = tca_dump_full((struct rtnl_tca *) qdisc, p, line); 00083 dp_dump(p, "refcnt %u ", qdisc->q_info); 00084 00085 qops = rtnl_qdisc_lookup_ops(qdisc); 00086 if (qops && qops->qo_dump[NL_DUMP_FULL]) 00087 line = qops->qo_dump[NL_DUMP_FULL](qdisc, p, line); 00088 00089 dp_dump(p, "\n"); 00090 return line; 00091 } 00092 00093 static int qdisc_dump_stats(struct nl_object *arg, struct nl_dump_params *p) 00094 { 00095 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) arg; 00096 struct rtnl_qdisc_ops *qops; 00097 00098 int line = qdisc_dump_full(arg, p); 00099 line = tca_dump_stats((struct rtnl_tca *) qdisc, p, line ); 00100 dp_dump(p, "\n"); 00101 00102 qops = rtnl_qdisc_lookup_ops(qdisc); 00103 if (qops && qops->qo_dump[NL_DUMP_STATS]) 00104 line = qops->qo_dump[NL_DUMP_STATS](qdisc, p, line); 00105 00106 return line; 00107 } 00108 00109 /** 00110 * @name Allocation/Freeing 00111 * @{ 00112 */ 00113 00114 struct rtnl_qdisc *rtnl_qdisc_alloc(void) 00115 { 00116 return (struct rtnl_qdisc *) nl_object_alloc(&qdisc_obj_ops); 00117 } 00118 00119 void rtnl_qdisc_put(struct rtnl_qdisc *qdisc) 00120 { 00121 nl_object_put((struct nl_object *) qdisc); 00122 } 00123 00124 /** @} */ 00125 00126 /** 00127 * @name Iterators 00128 * @{ 00129 */ 00130 00131 /** 00132 * Call a callback for each child class of a qdisc 00133 * @arg qdisc the parent qdisc 00134 * @arg cache a class cache including all classes of the interface 00135 * the specified qdisc is attached to 00136 * @arg cb callback function 00137 * @arg arg argument to be passed to callback function 00138 */ 00139 void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache, 00140 void (*cb)(struct nl_object *, void *), void *arg) 00141 { 00142 struct rtnl_class *filter; 00143 00144 filter = rtnl_class_alloc(); 00145 if (!filter) 00146 return; 00147 00148 rtnl_class_set_parent(filter, qdisc->q_handle); 00149 rtnl_class_set_ifindex(filter, qdisc->q_ifindex); 00150 rtnl_class_set_kind(filter, qdisc->q_kind); 00151 00152 nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); 00153 00154 rtnl_class_put(filter); 00155 } 00156 00157 /** 00158 * Call a callback for each filter attached to the qdisc 00159 * @arg qdisc the parent qdisc 00160 * @arg cache a filter cache including at least all the filters 00161 * attached to the specified qdisc 00162 * @arg cb callback function 00163 * @arg arg argument to be passed to callback function 00164 */ 00165 void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache, 00166 void (*cb)(struct nl_object *, void *), void *arg) 00167 { 00168 struct rtnl_cls *filter; 00169 00170 filter = rtnl_cls_alloc(); 00171 if (!filter) 00172 return; 00173 00174 rtnl_cls_set_ifindex(filter, qdisc->q_ifindex); 00175 rtnl_cls_set_parent(filter, qdisc->q_parent); 00176 00177 nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); 00178 rtnl_cls_put(filter); 00179 } 00180 00181 /** @} */ 00182 00183 /** 00184 * @name Attributes 00185 * @{ 00186 */ 00187 00188 void rtnl_qdisc_set_ifindex(struct rtnl_qdisc *qdisc, int ifindex) 00189 { 00190 tca_set_ifindex((struct rtnl_tca *) qdisc, ifindex); 00191 } 00192 00193 int rtnl_qdisc_get_ifindex(struct rtnl_qdisc *qdisc) 00194 { 00195 return tca_get_ifindex((struct rtnl_tca *) qdisc); 00196 } 00197 00198 void rtnl_qdisc_set_handle(struct rtnl_qdisc *qdisc, uint32_t handle) 00199 { 00200 tca_set_handle((struct rtnl_tca *) qdisc, handle); 00201 } 00202 00203 uint32_t rtnl_qdisc_get_handle(struct rtnl_qdisc *qdisc) 00204 { 00205 return tca_get_handle((struct rtnl_tca *) qdisc); 00206 } 00207 00208 void rtnl_qdisc_set_parent(struct rtnl_qdisc *qdisc, uint32_t parent) 00209 { 00210 tca_set_parent((struct rtnl_tca *) qdisc, parent); 00211 } 00212 00213 uint32_t rtnl_qdisc_get_parent(struct rtnl_qdisc *qdisc) 00214 { 00215 return tca_get_parent((struct rtnl_tca *) qdisc); 00216 } 00217 00218 void rtnl_qdisc_set_kind(struct rtnl_qdisc *qdisc, const char *name) 00219 { 00220 tca_set_kind((struct rtnl_tca *) qdisc, name); 00221 qdisc->q_ops = __rtnl_qdisc_lookup_ops(name); 00222 } 00223 00224 char *rtnl_qdisc_get_kind(struct rtnl_qdisc *qdisc) 00225 { 00226 return tca_get_kind((struct rtnl_tca *) qdisc); 00227 } 00228 00229 uint64_t rtnl_qdisc_get_stat(struct rtnl_qdisc *qdisc, 00230 enum rtnl_tc_stats_id id) 00231 { 00232 return tca_get_stat((struct rtnl_tca *) qdisc, id); 00233 } 00234 00235 /** @} */ 00236 00237 /** 00238 * @name Qdisc Specific Options 00239 * @{ 00240 */ 00241 00242 /** 00243 * Return qdisc specific options for use in TCA_OPTIONS 00244 * @arg qdisc qdisc carrying the optiosn 00245 * 00246 * @return new headerless netlink message carrying the options as payload 00247 */ 00248 struct nl_msg *rtnl_qdisc_get_opts(struct rtnl_qdisc *qdisc) 00249 { 00250 struct rtnl_qdisc_ops *ops; 00251 00252 ops = rtnl_qdisc_lookup_ops(qdisc); 00253 if (ops && ops->qo_get_opts) 00254 return ops->qo_get_opts(qdisc); 00255 00256 return NULL; 00257 } 00258 00259 /** @} */ 00260 00261 struct nl_object_ops qdisc_obj_ops = { 00262 .oo_name = "route/qdisc", 00263 .oo_size = sizeof(struct rtnl_qdisc), 00264 .oo_free_data = qdisc_free_data, 00265 .oo_clone = qdisc_clone, 00266 .oo_dump[NL_DUMP_BRIEF] = qdisc_dump_brief, 00267 .oo_dump[NL_DUMP_FULL] = qdisc_dump_full, 00268 .oo_dump[NL_DUMP_STATS] = qdisc_dump_stats, 00269 .oo_compare = tca_compare, 00270 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), 00271 }; 00272 00273 /** @} */