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