Home | History | Annotate | Download | only in route
      1 /*
      2  * lib/route/cls_api.c       Classifier Object
      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 cls
     14  * @defgroup cls_obj Classifier Object
     15  * @{
     16  */
     17 
     18 #include <netlink-local.h>
     19 #include <netlink-tc.h>
     20 #include <netlink/netlink.h>
     21 #include <netlink/utils.h>
     22 #include <netlink/route/tc.h>
     23 #include <netlink/route/classifier.h>
     24 #include <netlink/route/classifier-modules.h>
     25 #include <netlink/route/link.h>
     26 
     27 /** @cond SKIP */
     28 #define CLS_ATTR_PRIO		(TCA_ATTR_MAX << 1)
     29 #define CLS_ATTR_PROTOCOL	(TCA_ATTR_MAX << 2)
     30 /** @endcond */
     31 
     32 static void cls_free_data(struct nl_object *obj)
     33 {
     34 	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
     35 	struct rtnl_cls_ops *cops;
     36 
     37 	tca_free_data((struct rtnl_tca *) cls);
     38 
     39 	cops = rtnl_cls_lookup_ops(cls);
     40 	if (cops && cops->co_free_data)
     41 		cops->co_free_data(cls);
     42 
     43 	nl_data_free(cls->c_subdata);
     44 }
     45 
     46 static int cls_clone(struct nl_object *_dst, struct nl_object *_src)
     47 {
     48 	struct rtnl_cls *dst = nl_object_priv(_dst);
     49 	struct rtnl_cls *src = nl_object_priv(_src);
     50 	struct rtnl_cls_ops *cops;
     51 	int err;
     52 
     53 	err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
     54 	if (err < 0)
     55 		goto errout;
     56 
     57 	if (src->c_subdata) {
     58 		if (!(dst->c_subdata = nl_data_clone(src->c_subdata))) {
     59 			err = -NLE_NOMEM;
     60 			goto errout;
     61 		}
     62 	}
     63 
     64 	cops = rtnl_cls_lookup_ops(src);
     65 	if (cops && cops->co_clone)
     66 		err = cops->co_clone(dst, src);
     67 errout:
     68 	return err;
     69 }
     70 
     71 static void cls_dump_line(struct nl_object *obj, struct nl_dump_params *p)
     72 {
     73 	char buf[32];
     74 	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
     75 	struct rtnl_cls_ops *cops;
     76 
     77 	tca_dump_line((struct rtnl_tca *) cls, "cls", p);
     78 
     79 	nl_dump(p, " prio %u protocol %s", cls->c_prio,
     80 		nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
     81 
     82 	cops = rtnl_cls_lookup_ops(cls);
     83 	if (cops && cops->co_dump[NL_DUMP_LINE])
     84 		cops->co_dump[NL_DUMP_LINE](cls, p);
     85 	nl_dump(p, "\n");
     86 }
     87 
     88 static void cls_dump_details(struct nl_object *obj, struct nl_dump_params *p)
     89 {
     90 	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
     91 	struct rtnl_cls_ops *cops;
     92 
     93 	cls_dump_line(obj, p);
     94 	tca_dump_details((struct rtnl_tca *) cls, p);
     95 
     96 	cops = rtnl_cls_lookup_ops(cls);
     97 	if (cops && cops->co_dump[NL_DUMP_DETAILS])
     98 		cops->co_dump[NL_DUMP_DETAILS](cls, p);
     99 	else
    100 		nl_dump(p, "no options\n");
    101 }
    102 
    103 static void cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
    104 {
    105 	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
    106 	struct rtnl_cls_ops *cops;
    107 
    108 	cls_dump_details(obj, p);
    109 	tca_dump_stats((struct rtnl_tca *) cls, p);
    110 	nl_dump(p, "\n");
    111 
    112 	cops = rtnl_cls_lookup_ops(cls);
    113 	if (cops && cops->co_dump[NL_DUMP_STATS])
    114 		cops->co_dump[NL_DUMP_STATS](cls, p);
    115 }
    116 
    117 /**
    118  * @name Allocation/Freeing
    119  * @{
    120  */
    121 
    122 struct rtnl_cls *rtnl_cls_alloc(void)
    123 {
    124 	return (struct rtnl_cls *) nl_object_alloc(&cls_obj_ops);
    125 }
    126 
    127 void rtnl_cls_put(struct rtnl_cls *cls)
    128 {
    129 	nl_object_put((struct nl_object *) cls);
    130 }
    131 
    132 /** @} */
    133 
    134 
    135 /**
    136  * @name Attributes
    137  * @{
    138  */
    139 
    140 void rtnl_cls_set_ifindex(struct rtnl_cls *f, int ifindex)
    141 {
    142 	tca_set_ifindex((struct rtnl_tca *) f, ifindex);
    143 }
    144 
    145 int rtnl_cls_get_ifindex(struct rtnl_cls *cls)
    146 {
    147 	return cls->c_ifindex;
    148 }
    149 
    150 void rtnl_cls_set_handle(struct rtnl_cls *f, uint32_t handle)
    151 {
    152 	tca_set_handle((struct rtnl_tca *) f, handle);
    153 }
    154 
    155 void rtnl_cls_set_parent(struct rtnl_cls *f, uint32_t parent)
    156 {
    157 	tca_set_parent((struct rtnl_tca *) f, parent);
    158 }
    159 
    160 uint32_t rtnl_cls_get_parent(struct rtnl_cls *cls)
    161 {
    162 	return cls->c_parent;
    163 }
    164 
    165 int rtnl_cls_set_kind(struct rtnl_cls *cls, const char *kind)
    166 {
    167 	if (cls->ce_mask & TCA_ATTR_KIND)
    168 		return -NLE_EXIST;
    169 
    170 	tca_set_kind((struct rtnl_tca *) cls, kind);
    171 
    172 	/* Force allocation of data */
    173 	rtnl_cls_data(cls);
    174 
    175 	return 0;
    176 }
    177 
    178 struct rtnl_cls_ops *rtnl_cls_get_ops(struct rtnl_cls *cls)
    179 {
    180 	return cls->c_ops;
    181 }
    182 
    183 void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
    184 {
    185 	cls->c_prio = prio;
    186 	cls->ce_mask |= CLS_ATTR_PRIO;
    187 }
    188 
    189 uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
    190 {
    191 	if (cls->ce_mask & CLS_ATTR_PRIO)
    192 		return cls->c_prio;
    193 	else
    194 		return 0;
    195 }
    196 
    197 void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
    198 {
    199 	cls->c_protocol = protocol;
    200 	cls->ce_mask |= CLS_ATTR_PROTOCOL;
    201 }
    202 
    203 uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
    204 {
    205 	if (cls->ce_mask & CLS_ATTR_PROTOCOL)
    206 		return cls->c_protocol;
    207 	else
    208 		return ETH_P_ALL;
    209 }
    210 
    211 void *rtnl_cls_data(struct rtnl_cls *cls)
    212 {
    213 	if (!cls->c_subdata) {
    214 		struct rtnl_cls_ops *ops = cls->c_ops;
    215 
    216 		if (!ops) {
    217 			if (!cls->c_kind[0])
    218 				BUG();
    219 
    220 			ops = __rtnl_cls_lookup_ops(cls->c_kind);
    221 			if (ops == NULL)
    222 				return NULL;
    223 
    224 			cls->c_ops = ops;
    225 		}
    226 
    227 		if (!ops->co_size)
    228 			BUG();
    229 
    230 		if (!(cls->c_subdata = nl_data_alloc(NULL, ops->co_size)))
    231 			return NULL;
    232 	}
    233 
    234 	return nl_data_get(cls->c_subdata);
    235 }
    236 
    237 /** @} */
    238 
    239 struct nl_object_ops cls_obj_ops = {
    240 	.oo_name		= "route/cls",
    241 	.oo_size		= sizeof(struct rtnl_cls),
    242 	.oo_free_data		= cls_free_data,
    243 	.oo_clone		= cls_clone,
    244 	.oo_dump = {
    245 	    [NL_DUMP_LINE]	= cls_dump_line,
    246 	    [NL_DUMP_DETAILS]	= cls_dump_details,
    247 	    [NL_DUMP_STATS]	= cls_dump_stats,
    248 	},
    249 	.oo_compare		= tca_compare,
    250 	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
    251 };
    252 
    253 /** @} */
    254