Tizen 2.1 base
[platform/upstream/libnl2.git] / lib / route / cls_obj.c
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@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 /** @} */