libnl 2.0

/build/buildd/libnl2-2.0/lib/route/cls_obj.c

00001 /*
00002  * lib/route/cls_api.c       Classifier 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 cls
00014  * @defgroup cls_obj Classifier 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/tc.h>
00023 #include <netlink/route/classifier.h>
00024 #include <netlink/route/classifier-modules.h>
00025 #include <netlink/route/link.h>
00026 
00027 /** @cond SKIP */
00028 #define CLS_ATTR_PRIO           (TCA_ATTR_MAX << 1)
00029 #define CLS_ATTR_PROTOCOL       (TCA_ATTR_MAX << 2)
00030 /** @endcond */
00031 
00032 static void cls_free_data(struct nl_object *obj)
00033 {
00034         struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00035         struct rtnl_cls_ops *cops;
00036         
00037         tca_free_data((struct rtnl_tca *) cls);
00038 
00039         cops = rtnl_cls_lookup_ops(cls);
00040         if (cops && cops->co_free_data)
00041                 cops->co_free_data(cls);
00042 
00043         nl_data_free(cls->c_subdata);
00044 }
00045 
00046 static int cls_clone(struct nl_object *_dst, struct nl_object *_src)
00047 {
00048         struct rtnl_cls *dst = nl_object_priv(_dst);
00049         struct rtnl_cls *src = nl_object_priv(_src);
00050         struct rtnl_cls_ops *cops;
00051         int err;
00052         
00053         err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
00054         if (err < 0)
00055                 goto errout;
00056 
00057         if (src->c_subdata) {
00058                 if (!(dst->c_subdata = nl_data_clone(src->c_subdata))) {
00059                         err = -NLE_NOMEM;
00060                         goto errout;
00061                 }
00062         }
00063 
00064         cops = rtnl_cls_lookup_ops(src);
00065         if (cops && cops->co_clone)
00066                 err = cops->co_clone(dst, src);
00067 errout:
00068         return err;
00069 }
00070 
00071 static void cls_dump_line(struct nl_object *obj, struct nl_dump_params *p)
00072 {
00073         char buf[32];
00074         struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00075         struct rtnl_cls_ops *cops;
00076 
00077         tca_dump_line((struct rtnl_tca *) cls, "cls", p);
00078 
00079         nl_dump(p, " prio %u protocol %s", cls->c_prio,
00080                 nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
00081 
00082         cops = rtnl_cls_lookup_ops(cls);
00083         if (cops && cops->co_dump[NL_DUMP_LINE])
00084                 cops->co_dump[NL_DUMP_LINE](cls, p);
00085         nl_dump(p, "\n");
00086 }
00087 
00088 static void cls_dump_details(struct nl_object *obj, struct nl_dump_params *p)
00089 {
00090         struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00091         struct rtnl_cls_ops *cops;
00092 
00093         cls_dump_line(obj, p);
00094         tca_dump_details((struct rtnl_tca *) cls, p);
00095 
00096         cops = rtnl_cls_lookup_ops(cls);
00097         if (cops && cops->co_dump[NL_DUMP_DETAILS])
00098                 cops->co_dump[NL_DUMP_DETAILS](cls, p);
00099         else
00100                 nl_dump(p, "no options\n");
00101 }
00102 
00103 static void cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00104 {
00105         struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00106         struct rtnl_cls_ops *cops;
00107 
00108         cls_dump_details(obj, p);
00109         tca_dump_stats((struct rtnl_tca *) cls, p);
00110         nl_dump(p, "\n");
00111 
00112         cops = rtnl_cls_lookup_ops(cls);
00113         if (cops && cops->co_dump[NL_DUMP_STATS])
00114                 cops->co_dump[NL_DUMP_STATS](cls, p);
00115 }
00116 
00117 /**
00118  * @name Allocation/Freeing
00119  * @{
00120  */
00121 
00122 struct rtnl_cls *rtnl_cls_alloc(void)
00123 {
00124         return (struct rtnl_cls *) nl_object_alloc(&cls_obj_ops);
00125 }
00126 
00127 void rtnl_cls_put(struct rtnl_cls *cls)
00128 {
00129         nl_object_put((struct nl_object *) cls);
00130 }
00131 
00132 /** @} */
00133 
00134 
00135 /**
00136  * @name Attributes
00137  * @{
00138  */
00139 
00140 void rtnl_cls_set_ifindex(struct rtnl_cls *f, int ifindex)
00141 {
00142         tca_set_ifindex((struct rtnl_tca *) f, ifindex);
00143 }
00144 
00145 int rtnl_cls_get_ifindex(struct rtnl_cls *cls)
00146 {
00147         return cls->c_ifindex;
00148 }
00149 
00150 void rtnl_cls_set_handle(struct rtnl_cls *f, uint32_t handle)
00151 {
00152         tca_set_handle((struct rtnl_tca *) f, handle);
00153 }
00154 
00155 void rtnl_cls_set_parent(struct rtnl_cls *f, uint32_t parent)
00156 {
00157         tca_set_parent((struct rtnl_tca *) f, parent);
00158 }
00159 
00160 uint32_t rtnl_cls_get_parent(struct rtnl_cls *cls)
00161 {
00162         return cls->c_parent;
00163 }
00164 
00165 int rtnl_cls_set_kind(struct rtnl_cls *cls, const char *kind)
00166 {
00167         if (cls->ce_mask & TCA_ATTR_KIND)
00168                 return -NLE_EXIST;
00169 
00170         tca_set_kind((struct rtnl_tca *) cls, kind);
00171 
00172         /* Force allocation of data */
00173         rtnl_cls_data(cls);
00174 
00175         return 0;
00176 }
00177 
00178 struct rtnl_cls_ops *rtnl_cls_get_ops(struct rtnl_cls *cls)
00179 {
00180         return cls->c_ops;
00181 }
00182 
00183 void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
00184 {
00185         cls->c_prio = prio;
00186         cls->ce_mask |= CLS_ATTR_PRIO;
00187 }
00188 
00189 uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
00190 {
00191         if (cls->ce_mask & CLS_ATTR_PRIO)
00192                 return cls->c_prio;
00193         else
00194                 return 0;
00195 }
00196 
00197 void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
00198 {
00199         cls->c_protocol = protocol;
00200         cls->ce_mask |= CLS_ATTR_PROTOCOL;
00201 }
00202 
00203 uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
00204 {
00205         if (cls->ce_mask & CLS_ATTR_PROTOCOL)
00206                 return cls->c_protocol;
00207         else
00208                 return ETH_P_ALL;
00209 }
00210 
00211 void *rtnl_cls_data(struct rtnl_cls *cls)
00212 {
00213         if (!cls->c_subdata) {
00214                 struct rtnl_cls_ops *ops = cls->c_ops;
00215 
00216                 if (!ops) {
00217                         if (!cls->c_kind[0])
00218                                 BUG();
00219 
00220                         ops = __rtnl_cls_lookup_ops(cls->c_kind);
00221                         if (ops == NULL)
00222                                 return NULL;
00223 
00224                         cls->c_ops = ops;
00225                 }
00226 
00227                 if (!ops->co_size)
00228                         BUG();
00229 
00230                 if (!(cls->c_subdata = nl_data_alloc(NULL, ops->co_size)))
00231                         return NULL;
00232         }
00233 
00234         return nl_data_get(cls->c_subdata);
00235 }
00236 
00237 /** @} */
00238 
00239 struct nl_object_ops cls_obj_ops = {
00240         .oo_name                = "route/cls",
00241         .oo_size                = sizeof(struct rtnl_cls),
00242         .oo_free_data           = cls_free_data,
00243         .oo_clone               = cls_clone,
00244         .oo_dump = {
00245             [NL_DUMP_LINE]      = cls_dump_line,
00246             [NL_DUMP_DETAILS]   = cls_dump_details,
00247             [NL_DUMP_STATS]     = cls_dump_stats,
00248         },
00249         .oo_compare             = tca_compare,
00250         .oo_id_attrs            = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
00251 };
00252 
00253 /** @} */