libnl 3.7.0
mall.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2017 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
4 */
5
6/**
7 * @ingroup cls
8 * @defgroup cls_mall Match-all Classifier
9 *
10 * @{
11 */
12
13#include <netlink-private/netlink.h>
14#include <netlink-private/tc.h>
15#include <netlink/netlink.h>
16#include <netlink/attr.h>
17#include <netlink/utils.h>
18#include <netlink-private/route/tc-api.h>
19#include <netlink/route/classifier.h>
20#include <netlink/route/cls/matchall.h>
21#include <netlink/route/action.h>
22
23
24#define MALL_ATTR_CLASSID 0x01
25#define MALL_ATTR_FLAGS 0x02
26#define MALL_ATTR_ACTION 0x03
27
28
29static struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
30 [TCA_MATCHALL_CLASSID] = { .type = NLA_U32 },
31 [TCA_MATCHALL_FLAGS] = { .type = NLA_U32 },
32};
33
34/**
35 * @name Attribute Modifications
36 * @{
37 */
38
39int rtnl_mall_set_classid(struct rtnl_cls *cls, uint32_t classid)
40{
41 struct rtnl_mall *mall;
42 if (!(mall = rtnl_tc_data(TC_CAST(cls))))
43 return -NLE_NOMEM;
44
45 mall->m_classid = classid;
46 mall->m_mask |= MALL_ATTR_CLASSID;
47
48 return 0;
49}
50
51int rtnl_mall_get_classid(struct rtnl_cls *cls, uint32_t *classid)
52{
53 struct rtnl_mall *mall;
54
55 if (!(mall = rtnl_tc_data_peek(TC_CAST(cls))))
56 return -NLE_INVAL;
57
58 if (!(mall->m_mask & MALL_ATTR_CLASSID))
59 return -NLE_INVAL;
60
61 *classid = mall->m_classid;
62 return 0;
63}
64
65int rtnl_mall_set_flags(struct rtnl_cls *cls, uint32_t flags)
66{
67 struct rtnl_mall *mall;
68
69 if (!(mall = rtnl_tc_data(TC_CAST(cls))))
70 return -NLE_NOMEM;
71
72 mall->m_flags = flags;
73 mall->m_mask |= MALL_ATTR_FLAGS;
74
75 return 0;
76}
77
78int rtnl_mall_get_flags(struct rtnl_cls *cls, uint32_t *flags)
79{
80 struct rtnl_mall *mall;
81
82 if (!(mall = rtnl_tc_data_peek(TC_CAST(cls))))
83 return -NLE_INVAL;
84
85 if (!(mall->m_mask & MALL_ATTR_FLAGS))
86 return -NLE_INVAL;
87
88 *flags = mall->m_flags;
89 return 0;
90}
91
92int rtnl_mall_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
93{
94 struct rtnl_mall *mall;
95 int err;
96
97 if (!act)
98 return 0;
99
100 if (!(mall = rtnl_tc_data(TC_CAST(cls))))
101 return -NLE_NOMEM;
102
103 mall->m_mask |= MALL_ATTR_ACTION;
104 err = rtnl_act_append(&mall->m_act, act);
105 if (err < 0)
106 return err;
107
108 rtnl_act_get(act);
109 return 0;
110}
111
112struct rtnl_act *rtnl_mall_get_first_action(struct rtnl_cls *cls)
113{
114 struct rtnl_mall *mall;
115 struct rtnl_act *act;
116
117 if (!(mall = rtnl_tc_data(TC_CAST(cls))))
118 return NULL;
119
120 if (!(mall->m_mask & MALL_ATTR_ACTION))
121 return NULL;
122
123 act = mall->m_act;
124 rtnl_act_get(act);
125
126 return act;
127}
128
129int rtnl_mall_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
130{
131 struct rtnl_mall *mall;
132 int ret;
133
134 if (!act)
135 return 0;
136
137 if (!(mall = rtnl_tc_data(TC_CAST(cls))))
138 return -NLE_NOMEM;
139
140 if (!(mall->m_mask & MALL_ATTR_ACTION))
141 return -NLE_INVAL;
142
143 ret = rtnl_act_remove(&mall->m_act, act);
144 if (ret < 0)
145 return ret;
146
147 rtnl_act_put(act);
148
149 return 0;
150}
151
152/** @} */
153
154static void mall_free_data(struct rtnl_tc *tc, void *data)
155{
156 struct rtnl_mall *mall = data;
157
158 if (mall->m_act)
159 rtnl_act_put_all(&mall->m_act);
160}
161
162static int mall_msg_parser(struct rtnl_tc *tc, void *data)
163{
164 struct rtnl_mall *mall = data;
165 struct nlattr *tb[TCA_MATCHALL_MAX + 1];
166 int err;
167
168 err = tca_parse(tb, TCA_MATCHALL_MAX, tc, mall_policy);
169 if (err < 0)
170 return err;
171
172 if (tb[TCA_MATCHALL_CLASSID]) {
173 mall->m_classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
174 mall->m_mask |= MALL_ATTR_CLASSID;
175 }
176
177 if (tb[TCA_MATCHALL_FLAGS]) {
178 mall->m_flags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]);
179 mall->m_mask |= MALL_ATTR_FLAGS;
180 }
181
182 if (tb[TCA_MATCHALL_ACT]) {
183 mall->m_mask |= MALL_ATTR_ACTION;
184 err = rtnl_act_parse(&mall->m_act, tb[TCA_MATCHALL_ACT]);
185 if (err < 0)
186 return err;
187 }
188
189 return 0;
190}
191
192static int mall_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
193{
194 struct rtnl_mall *mall = data;
195
196 if (!mall)
197 return 0;
198
199 if (mall->m_mask & MALL_ATTR_CLASSID)
200 NLA_PUT_U32(msg, TCA_MATCHALL_CLASSID, mall->m_classid);
201
202 if (mall->m_mask & MALL_ATTR_FLAGS)
203 NLA_PUT_U32(msg, TCA_MATCHALL_FLAGS, mall->m_flags);
204
205 if (mall->m_mask & MALL_ATTR_ACTION) {
206 int err;
207
208 err = rtnl_act_fill(msg, TCA_MATCHALL_ACT, mall->m_act);
209 if (err < 0)
210 return err;
211 }
212
213 return 0;
214
215nla_put_failure:
216 return -NLE_NOMEM;
217}
218
219static int mall_clone(void *_dst, void *_src)
220{
221 struct rtnl_mall *dst = _dst, *src = _src;
222 struct rtnl_act *next, *new;
223 int err;
224
225 dst->m_act = NULL;
226
227 if (src->m_act) {
228 if (!(dst->m_act = rtnl_act_alloc()))
229 return -NLE_NOMEM;
230
231 /* action nl list next and prev pointers must be updated */
232 nl_init_list_head(&dst->m_act->ce_list);
233
234 memcpy(dst->m_act, src->m_act, sizeof(struct rtnl_act));
235 next = rtnl_act_next(src->m_act);
236 while (next) {
237 new = (struct rtnl_act *) nl_object_clone((struct nl_object *) next);
238 if (!new)
239 return -NLE_NOMEM;
240
241 err = rtnl_act_append(&dst->m_act, new);
242 if (err < 0)
243 return err;
244
245 next = rtnl_act_next(next);
246 }
247 }
248
249 return 0;
250}
251
252static void mall_dump_line(struct rtnl_tc *tc, void *data,
253 struct nl_dump_params *p)
254{
255 struct rtnl_mall *mall = data;
256 char buf[32];
257
258 if (!mall)
259 return;
260
261 if (mall->m_mask & MALL_ATTR_CLASSID)
262 nl_dump(p, " target %s",
263 rtnl_tc_handle2str(mall->m_classid, buf, sizeof(buf)));
264}
265
266static void mall_dump_details(struct rtnl_tc *tc, void *data,
267 struct nl_dump_params *p)
268{
269 struct rtnl_mall *mall = data;
270
271 if (!mall)
272 return;
273
274 nl_dump(p, "no details for match-all");
275}
276
277static struct rtnl_tc_ops mall_ops = {
278 .to_kind = "matchall",
279 .to_type = RTNL_TC_TYPE_CLS,
280 .to_size = sizeof(struct rtnl_mall),
281 .to_msg_parser = mall_msg_parser,
282 .to_free_data = mall_free_data,
283 .to_clone = mall_clone,
284 .to_msg_fill = mall_msg_fill,
285 .to_dump = {
286 [NL_DUMP_LINE] = mall_dump_line,
287 [NL_DUMP_DETAILS] = mall_dump_details,
288 },
289};
290
291static void __init mall_init(void)
292{
293 rtnl_tc_register(&mall_ops);
294}
295
296static void __exit mall_exit(void)
297{
298 rtnl_tc_unregister(&mall_ops);
299}
300
301/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:702
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:230
@ NLA_U32
32 bit integer
Definition: attr.h:37
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
Definition: classid.c:103
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
Definition: object.c:104
void * rtnl_tc_data_peek(struct rtnl_tc *tc)
Returns the private data of the traffic control object.
Definition: tc.c:1062
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:50
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
Definition: tc.c:1076
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:1015
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition: tc.c:1049
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65