libnl 2.0
|
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 void qdisc_dump_line(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 tca_dump_line((struct rtnl_tca *) qdisc, "qdisc", p); 00065 00066 qops = rtnl_qdisc_lookup_ops(qdisc); 00067 if (qops && qops->qo_dump[NL_DUMP_LINE]) 00068 qops->qo_dump[NL_DUMP_LINE](qdisc, p); 00069 00070 nl_dump(p, "\n"); 00071 } 00072 00073 static void qdisc_dump_details(struct nl_object *arg, struct nl_dump_params *p) 00074 { 00075 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) arg; 00076 struct rtnl_qdisc_ops *qops; 00077 00078 qdisc_dump_line(arg, p); 00079 00080 tca_dump_details((struct rtnl_tca *) qdisc, p); 00081 nl_dump(p, "refcnt %u ", qdisc->q_info); 00082 00083 qops = rtnl_qdisc_lookup_ops(qdisc); 00084 if (qops && qops->qo_dump[NL_DUMP_DETAILS]) 00085 qops->qo_dump[NL_DUMP_DETAILS](qdisc, p); 00086 00087 nl_dump(p, "\n"); 00088 } 00089 00090 static void qdisc_dump_stats(struct nl_object *arg, struct nl_dump_params *p) 00091 { 00092 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) arg; 00093 struct rtnl_qdisc_ops *qops; 00094 00095 qdisc_dump_details(arg, p); 00096 tca_dump_stats((struct rtnl_tca *) qdisc, p); 00097 nl_dump(p, "\n"); 00098 00099 qops = rtnl_qdisc_lookup_ops(qdisc); 00100 if (qops && qops->qo_dump[NL_DUMP_STATS]) 00101 qops->qo_dump[NL_DUMP_STATS](qdisc, p); 00102 } 00103 00104 /** 00105 * @name Allocation/Freeing 00106 * @{ 00107 */ 00108 00109 struct rtnl_qdisc *rtnl_qdisc_alloc(void) 00110 { 00111 return (struct rtnl_qdisc *) nl_object_alloc(&qdisc_obj_ops); 00112 } 00113 00114 void rtnl_qdisc_put(struct rtnl_qdisc *qdisc) 00115 { 00116 nl_object_put((struct nl_object *) qdisc); 00117 } 00118 00119 /** @} */ 00120 00121 /** 00122 * @name Iterators 00123 * @{ 00124 */ 00125 00126 /** 00127 * Call a callback for each child class of a qdisc 00128 * @arg qdisc the parent qdisc 00129 * @arg cache a class cache including all classes of the interface 00130 * the specified qdisc is attached to 00131 * @arg cb callback function 00132 * @arg arg argument to be passed to callback function 00133 */ 00134 void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache, 00135 void (*cb)(struct nl_object *, void *), void *arg) 00136 { 00137 struct rtnl_class *filter; 00138 00139 filter = rtnl_class_alloc(); 00140 if (!filter) 00141 return; 00142 00143 rtnl_class_set_parent(filter, qdisc->q_handle); 00144 rtnl_class_set_ifindex(filter, qdisc->q_ifindex); 00145 rtnl_class_set_kind(filter, qdisc->q_kind); 00146 00147 nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); 00148 00149 rtnl_class_put(filter); 00150 } 00151 00152 /** 00153 * Call a callback for each filter attached to the qdisc 00154 * @arg qdisc the parent qdisc 00155 * @arg cache a filter cache including at least all the filters 00156 * attached to the specified qdisc 00157 * @arg cb callback function 00158 * @arg arg argument to be passed to callback function 00159 */ 00160 void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache, 00161 void (*cb)(struct nl_object *, void *), void *arg) 00162 { 00163 struct rtnl_cls *filter; 00164 00165 filter = rtnl_cls_alloc(); 00166 if (!filter) 00167 return; 00168 00169 rtnl_cls_set_ifindex(filter, qdisc->q_ifindex); 00170 rtnl_cls_set_parent(filter, qdisc->q_parent); 00171 00172 nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg); 00173 rtnl_cls_put(filter); 00174 } 00175 00176 /** @} */ 00177 00178 /** 00179 * @name Attributes 00180 * @{ 00181 */ 00182 00183 void rtnl_qdisc_set_ifindex(struct rtnl_qdisc *qdisc, int ifindex) 00184 { 00185 tca_set_ifindex((struct rtnl_tca *) qdisc, ifindex); 00186 } 00187 00188 int rtnl_qdisc_get_ifindex(struct rtnl_qdisc *qdisc) 00189 { 00190 return tca_get_ifindex((struct rtnl_tca *) qdisc); 00191 } 00192 00193 void rtnl_qdisc_set_handle(struct rtnl_qdisc *qdisc, uint32_t handle) 00194 { 00195 tca_set_handle((struct rtnl_tca *) qdisc, handle); 00196 } 00197 00198 uint32_t rtnl_qdisc_get_handle(struct rtnl_qdisc *qdisc) 00199 { 00200 return tca_get_handle((struct rtnl_tca *) qdisc); 00201 } 00202 00203 void rtnl_qdisc_set_parent(struct rtnl_qdisc *qdisc, uint32_t parent) 00204 { 00205 tca_set_parent((struct rtnl_tca *) qdisc, parent); 00206 } 00207 00208 uint32_t rtnl_qdisc_get_parent(struct rtnl_qdisc *qdisc) 00209 { 00210 return tca_get_parent((struct rtnl_tca *) qdisc); 00211 } 00212 00213 void rtnl_qdisc_set_kind(struct rtnl_qdisc *qdisc, const char *name) 00214 { 00215 tca_set_kind((struct rtnl_tca *) qdisc, name); 00216 qdisc->q_ops = __rtnl_qdisc_lookup_ops(name); 00217 } 00218 00219 char *rtnl_qdisc_get_kind(struct rtnl_qdisc *qdisc) 00220 { 00221 return tca_get_kind((struct rtnl_tca *) qdisc); 00222 } 00223 00224 uint64_t rtnl_qdisc_get_stat(struct rtnl_qdisc *qdisc, 00225 enum rtnl_tc_stats_id id) 00226 { 00227 return tca_get_stat((struct rtnl_tca *) qdisc, id); 00228 } 00229 00230 /** @} */ 00231 00232 /** 00233 * @name Qdisc Specific Options 00234 * @{ 00235 */ 00236 00237 /** 00238 * Return qdisc specific options for use in TCA_OPTIONS 00239 * @arg qdisc qdisc carrying the optiosn 00240 * 00241 * @return new headerless netlink message carrying the options as payload 00242 */ 00243 struct nl_msg *rtnl_qdisc_get_opts(struct rtnl_qdisc *qdisc) 00244 { 00245 struct rtnl_qdisc_ops *ops; 00246 00247 ops = rtnl_qdisc_lookup_ops(qdisc); 00248 if (ops && ops->qo_get_opts) 00249 return ops->qo_get_opts(qdisc); 00250 00251 return NULL; 00252 } 00253 00254 /** @} */ 00255 00256 struct nl_object_ops qdisc_obj_ops = { 00257 .oo_name = "route/qdisc", 00258 .oo_size = sizeof(struct rtnl_qdisc), 00259 .oo_free_data = qdisc_free_data, 00260 .oo_clone = qdisc_clone, 00261 .oo_dump = { 00262 [NL_DUMP_LINE] = qdisc_dump_line, 00263 [NL_DUMP_DETAILS] = qdisc_dump_details, 00264 [NL_DUMP_STATS] = qdisc_dump_stats, 00265 }, 00266 .oo_compare = tca_compare, 00267 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), 00268 }; 00269 00270 /** @} */