libnl 3.11.0
basic.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup cls
8 * @defgroup cls_basic Basic Classifier
9 *
10 * @par Introduction
11 * The basic classifier is the simplest form of a classifier. It does
12 * not have any special classification capabilities, instead it can be
13 * used to classify exclusively based on extended matches or to
14 * create a "catch-all" filter.
15 *
16 * @{
17 */
18
19#include "nl-default.h"
20
21#include <netlink/netlink.h>
22#include <netlink/route/classifier.h>
23#include <netlink/route/action.h>
24#include <netlink/route/cls/basic.h>
25#include <netlink/route/cls/ematch.h>
26
27#include "tc-api.h"
28#include "nl-aux-route/nl-route.h"
29
31{
32 uint32_t b_target;
33 struct rtnl_ematch_tree * b_ematch;
34 int b_mask;
35 struct rtnl_act * b_act;
36};
37
38/** @cond SKIP */
39#define BASIC_ATTR_TARGET 0x001
40#define BASIC_ATTR_EMATCH 0x002
41#define BASIC_ATTR_ACTION 0x004
42/** @endcond */
43
44static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = {
46 [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
47};
48
49static int basic_clone(void *_dst, void *_src)
50{
51 return -NLE_OPNOTSUPP;
52}
53
54static void basic_free_data(struct rtnl_tc *tc, void *data)
55{
56 struct rtnl_basic *b = data;
57
58 if (!b)
59 return;
60
61 if (b->b_act)
62 rtnl_act_put_all(&b->b_act);
63 rtnl_ematch_tree_free(b->b_ematch);
64}
65
66static int basic_msg_parser(struct rtnl_tc *tc, void *data)
67{
68 struct nlattr *tb[TCA_BASIC_MAX + 1];
69 struct rtnl_basic *b = data;
70 int err;
71
72 err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy);
73 if (err < 0)
74 return err;
75
76 if (tb[TCA_BASIC_CLASSID]) {
77 b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
78 b->b_mask |= BASIC_ATTR_TARGET;
79 }
80
81 if (tb[TCA_BASIC_EMATCHES]) {
82 if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES],
83 &b->b_ematch)) < 0)
84 return err;
85
86 if (b->b_ematch)
87 b->b_mask |= BASIC_ATTR_EMATCH;
88 }
89 if (tb[TCA_BASIC_ACT]) {
90 b->b_mask |= BASIC_ATTR_ACTION;
91 err = rtnl_act_parse(&b->b_act, tb[TCA_BASIC_ACT]);
92 if (err < 0)
93 return err;
94 }
95
96 return 0;
97}
98
99static void basic_dump_line(struct rtnl_tc *tc, void *data,
100 struct nl_dump_params *p)
101{
102 struct rtnl_basic *b = data;
103 char buf[32];
104
105 if (!b)
106 return;
107
108 if (b->b_mask & BASIC_ATTR_EMATCH)
109 nl_dump(p, " ematch");
110 else
111 nl_dump(p, " match-all");
112
113 if (b->b_mask & BASIC_ATTR_TARGET)
114 nl_dump(p, " target %s",
115 rtnl_tc_handle2str(b->b_target, buf, sizeof(buf)));
116}
117
118static void basic_dump_details(struct rtnl_tc *tc, void *data,
119 struct nl_dump_params *p)
120{
121 struct rtnl_basic *b = data;
122
123 if (!b)
124 return;
125
126 if (b->b_mask & BASIC_ATTR_EMATCH) {
127 nl_dump_line(p, " ematch ");
128 rtnl_ematch_tree_dump(b->b_ematch, p);
129 } else
130 nl_dump(p, "no options.\n");
131}
132
133static int basic_msg_fill(struct rtnl_tc *tc, void *data,
134 struct nl_msg *msg)
135{
136 struct rtnl_basic *b = data;
137
138 if (!b)
139 return 0;
140
141 if (b->b_mask & BASIC_ATTR_TARGET)
142 NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target);
143
144 if (b->b_mask & BASIC_ATTR_EMATCH &&
145 rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0)
146 goto nla_put_failure;
147
148 if (b->b_mask & BASIC_ATTR_ACTION) {
149 int err;
150
151 err = rtnl_act_fill(msg, TCA_BASIC_ACT, b->b_act);
152 if (err)
153 return err;
154 }
155
156 return 0;
157
158nla_put_failure:
159 return -NLE_NOMEM;
160}
161
162/**
163 * @name Attribute Modifications
164 * @{
165 */
166
167void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
168{
169 struct rtnl_basic *b;
170
171 if (!(b = rtnl_tc_data(TC_CAST(cls))))
172 return;
173
174 b->b_target = target;
175 b->b_mask |= BASIC_ATTR_TARGET;
176}
177
178uint32_t rtnl_basic_get_target(struct rtnl_cls *cls)
179{
180 struct rtnl_basic *b;
181
182 if (!(b = rtnl_tc_data(TC_CAST(cls))))
183 return 0;
184
185 return b->b_target;
186}
187
188void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
189{
190 struct rtnl_basic *b;
191
192 if (!(b = rtnl_tc_data(TC_CAST(cls))))
193 return;
194
195 if (b->b_ematch) {
196 rtnl_ematch_tree_free(b->b_ematch);
197 b->b_mask &= ~BASIC_ATTR_EMATCH;
198 }
199
200 b->b_ematch = tree;
201
202 if (tree)
203 b->b_mask |= BASIC_ATTR_EMATCH;
204}
205
206struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
207{
208 struct rtnl_basic *b;
209
210 if (!(b = rtnl_tc_data(TC_CAST(cls))))
211 return NULL;
212
213 return b->b_ematch;
214}
215
216int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
217{
218 struct rtnl_basic *b;
219 int err;
220
221 if (!act)
222 return 0;
223
224 if (!(b = rtnl_tc_data(TC_CAST(cls))))
225 return -NLE_NOMEM;
226
227 if ((err = _rtnl_act_append_get(&b->b_act, act)) < 0)
228 return err;
229
230 b->b_mask |= BASIC_ATTR_ACTION;
231 return 0;
232}
233
234struct rtnl_act* rtnl_basic_get_action(struct rtnl_cls *cls)
235{
236 struct rtnl_basic *b;
237
238 if (!(b = rtnl_tc_data_peek(TC_CAST(cls))))
239 return NULL;
240
241 if (!(b->b_mask & BASIC_ATTR_ACTION))
242 return NULL;
243
244 return b->b_act;
245}
246
247int rtnl_basic_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
248{
249 struct rtnl_basic *b;
250 int ret;
251
252 if (!act)
253 return 0;
254
255 if (!(b = rtnl_tc_data(TC_CAST(cls))))
256 return -NLE_NOMEM;
257
258 if (!(b->b_mask & BASIC_ATTR_ACTION))
259 return -NLE_INVAL;
260 ret = rtnl_act_remove(&b->b_act, act);
261 if (ret)
262 return ret;
263
264 if (!b->b_act)
265 b->b_mask &= ~BASIC_ATTR_ACTION;
266 rtnl_act_put(act);
267 return 0;
268}
269/** @} */
270
271static struct rtnl_tc_ops basic_ops = {
272 .to_kind = "basic",
273 .to_type = RTNL_TC_TYPE_CLS,
274 .to_size = sizeof(struct rtnl_basic),
275 .to_msg_parser = basic_msg_parser,
276 .to_clone = basic_clone,
277 .to_free_data = basic_free_data,
278 .to_msg_fill = basic_msg_fill,
279 .to_dump = {
280 [NL_DUMP_LINE] = basic_dump_line,
281 [NL_DUMP_DETAILS] = basic_dump_details,
282 },
283};
284
285static void _nl_init basic_init(void)
286{
287 rtnl_tc_register(&basic_ops);
288}
289
290static void _nl_exit basic_exit(void)
291{
292 rtnl_tc_unregister(&basic_ops);
293}
294
295/** @} */
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_NESTED
Nested attributes.
Definition attr.h:42
@ 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
void rtnl_ematch_tree_free(struct rtnl_ematch_tree *tree)
Free ematch tree object.
Definition ematch.c:278
int rtnl_ematch_parse_attr(struct nlattr *attr, struct rtnl_ematch_tree **result)
Parse ematch netlink attributes.
Definition ematch.c:396
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