libnl 3.7.0
vlan.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
4 */
5
6/**
7 * @ingroup act
8 * @defgroup act_vlan VLAN Manipulation
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/act/vlan.h>
20
21
22#define VLAN_F_VID (1 << 0)
23#define VLAN_F_PROTO (1 << 1)
24#define VLAN_F_PRIO (1 << 2)
25#define VLAN_F_ACT (1 << 3)
26#define VLAN_F_MODE (1 << 4)
27
28static struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
29 [TCA_VLAN_PARMS] = { .minlen = sizeof(struct tc_vlan) },
30 [TCA_VLAN_PUSH_VLAN_ID] = { .type = NLA_U16 },
31 [TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NLA_U16 },
32 [TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NLA_U8 },
33};
34
35static int vlan_msg_parser(struct rtnl_tc *tc, void *data)
36{
37 struct rtnl_vlan *v = data;
38 struct nlattr *tb[TCA_VLAN_MAX + 1];
39 int err;
40
41 err = tca_parse(tb, TCA_VLAN_MAX, tc, vlan_policy);
42 if (err < 0)
43 return err;
44
45 v->v_flags = 0;
46 if (!tb[TCA_VLAN_PARMS])
47 return -NLE_MISSING_ATTR;
48 else {
49 nla_memcpy(&v->v_parm, tb[TCA_VLAN_PARMS], sizeof(v->v_parm));
50 v->v_flags |= VLAN_F_ACT;
51 v->v_flags |= VLAN_F_MODE;
52 }
53
54 if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
55 v->v_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
56 v->v_flags |= VLAN_F_VID;
57 }
58
59 if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
60 v->v_proto = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
61 v->v_flags |= VLAN_F_PROTO;
62 }
63
64 if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) {
65 v->v_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
66 v->v_flags |= VLAN_F_PRIO;
67 }
68
69 return 0;
70}
71
72static int vlan_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
73{
74 struct rtnl_vlan *v = data;
75
76 if (!v)
77 return 0;
78 if (!(v->v_flags & VLAN_F_MODE))
79 return -NLE_MISSING_ATTR;
80
81 NLA_PUT(msg, TCA_VLAN_PARMS, sizeof(v->v_parm), &v->v_parm);
82
83 /* vid is required for PUSH & MODIFY modes */
84 if ((v->v_parm.v_action != TCA_VLAN_ACT_POP) && !(v->v_flags & VLAN_F_VID))
85 return -NLE_MISSING_ATTR;
86
87 if (v->v_flags & VLAN_F_VID)
88 NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_ID, v->v_vid);
89
90 if (v->v_flags & VLAN_F_PROTO)
91 NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_PROTOCOL, v->v_proto);
92
93 if (v->v_flags & VLAN_F_PRIO)
94 NLA_PUT_U8(msg, TCA_VLAN_PUSH_VLAN_PRIORITY, v->v_prio);
95
96 return 0;
97
98nla_put_failure:
99 return -NLE_NOMEM;
100}
101
102static void vlan_free_data(struct rtnl_tc *tc, void *data)
103{
104}
105
106static void vlan_dump_line(struct rtnl_tc *tc, void *data,
107 struct nl_dump_params *p)
108{
109 struct rtnl_vlan *v = data;
110
111 if (!v)
112 return;
113
114 if (!(v->v_flags & VLAN_F_ACT))
115 return;
116
117 if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_GOTO_CHAIN))
118 nl_dump(p, " goto chain %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK);
119
120 if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_JUMP))
121 nl_dump(p, " jump %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK);
122
123 switch(v->v_parm.action){
124 case TC_ACT_UNSPEC:
125 nl_dump(p, " unspecified");
126 break;
127 case TC_ACT_PIPE:
128 nl_dump(p, " pipe");
129 break;
130 case TC_ACT_STOLEN:
131 nl_dump(p, " stolen");
132 break;
133 case TC_ACT_SHOT:
134 nl_dump(p, " shot");
135 break;
136 case TC_ACT_QUEUED:
137 nl_dump(p, " queued");
138 break;
139 case TC_ACT_REPEAT:
140 nl_dump(p, " repeat");
141 break;
142 }
143}
144
145static void vlan_dump_details(struct rtnl_tc *tc, void *data,
146 struct nl_dump_params *p)
147{
148 struct rtnl_vlan *v = data;
149
150 if (!v)
151 return;
152
153 if (v->v_flags & VLAN_F_MODE) {
154 switch (v->v_parm.v_action) {
155 case TCA_VLAN_ACT_POP:
156 nl_dump(p, " mode POP");
157 break;
158 case TCA_VLAN_ACT_PUSH:
159 nl_dump(p, " mode PUSH");
160 break;
161 case TCA_VLAN_ACT_MODIFY:
162 nl_dump(p, " mode MODIFY");
163 break;
164 }
165 }
166
167 if (v->v_flags & VLAN_F_VID)
168 nl_dump(p, " vlan id %u", v->v_vid);
169
170 if (v->v_flags & VLAN_F_PRIO)
171 nl_dump(p, " priority %u", v->v_prio);
172
173 if (v->v_flags & VLAN_F_PROTO)
174 nl_dump(p, " protocol %u", v->v_proto);
175}
176
177/**
178 * @name Attribute Modifications
179 * @{
180 */
181
182/**
183 * Set vlan mode
184 * @arg act vlan action
185 * @arg mode one of (TCA_VLAN_ACT_*: POP, PUSH, MODIFY)
186 * @return 0 on success or a negative error code.
187 */
188int rtnl_vlan_set_mode(struct rtnl_act *act, int mode)
189{
190 struct rtnl_vlan *v;
191
192 if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
193 return -NLE_NOMEM;
194
195 if (mode > TCA_VLAN_ACT_MODIFY)
196 return -NLE_RANGE;
197
198 v->v_parm.v_action = mode;
199 v->v_flags |= VLAN_F_MODE;
200
201 return 0;
202}
203
204/**
205 * Get vlan mode
206 * @arg act vlan action
207 * @arg out_mode vlan mode output paramter
208 * @return 0 on success if the vlan mode was returned or a negative error code.
209*/
210int rtnl_vlan_get_mode(struct rtnl_act *act, int *out_mode)
211{
212 struct rtnl_vlan *v;
213
214 if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
215 return -NLE_INVAL;
216
217 if (!(v->v_flags & VLAN_F_MODE))
218 return -NLE_MISSING_ATTR;
219
220 *out_mode = v->v_parm.v_action;
221 return 0;
222}
223
224/**
225 * Set general action
226 * @arg act vlan action
227 * @arg action one of (TCA_ACT_*: PIPE, SHOT, GOTO_CHAIN, etc)
228 * @return 0 on success or a negative error code.
229 */
230int rtnl_vlan_set_action(struct rtnl_act *act, int action)
231{
232 struct rtnl_vlan *v;
233
234 if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
235 return -NLE_NOMEM;
236
237 v->v_parm.action = action;
238 v->v_flags |= VLAN_F_ACT;
239
240 return 0;
241}
242
243/**
244 * Get general action
245 * @arg act vlan action
246 * @arg out_action output parameter
247 * @return general 0 if out_action was set or a negative error code.
248*/
249int rtnl_vlan_get_action(struct rtnl_act *act, int *out_action)
250{
251 struct rtnl_vlan *v;
252
253 if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
254 return -NLE_INVAL;
255
256 if (!(v->v_flags & VLAN_F_ACT))
257 return -NLE_MISSING_ATTR;
258
259 *out_action = v->v_parm.action;
260 return 0;
261}
262
263/**
264 * Set protocol
265 * @arg act vlan action
266 * @arg protocol one of (ETH_P_8021Q || ETH_P_8021AD)
267 * @return 0 on success or a negative error code.
268 */
269int rtnl_vlan_set_protocol(struct rtnl_act *act, uint16_t protocol)
270{
271 struct rtnl_vlan *v;
272
273 if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
274 return -NLE_NOMEM;
275
276 v->v_proto = protocol;
277 v->v_flags |= VLAN_F_PROTO;
278
279 return 0;
280}
281
282/**
283 * Get protocol
284 * @arg act vlan action
285 * @arg out_protocol protocol output argument
286 * @return 0 if the protocol was returned or a negative error code.
287*/
288int rtnl_vlan_get_protocol(struct rtnl_act *act, uint16_t *out_protocol)
289{
290 struct rtnl_vlan *v;
291
292 if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
293 return -NLE_INVAL;
294
295 if (!(v->v_flags & VLAN_F_PROTO))
296 return -NLE_MISSING_ATTR;
297
298 *out_protocol = v->v_proto;
299 return 0;
300}
301
302/**
303 * Set vlan id
304 * @arg act vlan action
305 * @arg vid vlan id
306 * @return 0 on success or a negative error code.
307 */
308int rtnl_vlan_set_vlan_id(struct rtnl_act *act, uint16_t vid)
309{
310 struct rtnl_vlan *v;
311
312 if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
313 return -NLE_NOMEM;
314
315 if (vid > 4095)
316 return -NLE_RANGE;
317
318 v->v_vid = vid;
319 v->v_flags |= VLAN_F_VID;
320
321 return 0;
322}
323
324/**
325 * Get vlan id
326 * @arg act vlan action
327 * @arg out_vid output vlan id
328 * @return 0 if the vlan id was returned or a negative error code.
329*/
330int rtnl_vlan_get_vlan_id(struct rtnl_act *act, uint16_t *out_vid)
331{
332 struct rtnl_vlan *v;
333
334 if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
335 return -NLE_INVAL;
336
337 if (!(v->v_flags & VLAN_F_VID))
338 return -NLE_MISSING_ATTR;
339
340 *out_vid = v->v_vid;
341 return 0;
342}
343
344/**
345 * Set vlan prio
346 * @arg act vlan action
347 * @arg prio vlan priority (0 - 7)
348 * @return 0 on success or a negative error code.
349 */
350int rtnl_vlan_set_vlan_prio(struct rtnl_act *act, uint8_t prio)
351{
352 struct rtnl_vlan *v;
353
354 if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
355 return -NLE_NOMEM;
356
357 if (prio > 7)
358 return -NLE_RANGE;
359
360 v->v_prio = prio;
361 v->v_flags |= VLAN_F_PRIO;
362
363 return 0;
364}
365
366/**
367 * Get vlan prio
368 * @arg act vlan action
369 * @arg out_prio the output vlan prio
370 * @return 0 if the vlan prio was returned or a negative error code.
371*/
372int rtnl_vlan_get_vlan_prio(struct rtnl_act *act, uint8_t *out_prio)
373{
374 struct rtnl_vlan *v;
375
376 if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
377 return -NLE_INVAL;
378
379 if (!(v->v_flags & VLAN_F_PRIO))
380 return -NLE_MISSING_ATTR;
381
382 *out_prio = v->v_prio;
383 return 0;
384}
385
386/** @} */
387
388static struct rtnl_tc_ops vlan_ops = {
389 .to_kind = "vlan",
390 .to_type = RTNL_TC_TYPE_ACT,
391 .to_size = sizeof(struct rtnl_vlan),
392 .to_msg_parser = vlan_msg_parser,
393 .to_free_data = vlan_free_data,
394 .to_clone = NULL,
395 .to_msg_fill = vlan_msg_fill,
396 .to_dump = {
397 [NL_DUMP_LINE] = vlan_dump_line,
398 [NL_DUMP_DETAILS] = vlan_dump_details,
399 },
400};
401
402static void __init vlan_init(void)
403{
404 rtnl_tc_register(&vlan_ops);
405}
406
407static void __exit vlan_exit(void)
408{
409 rtnl_tc_unregister(&vlan_ops);
410}
411
412/** @} */
int rtnl_vlan_get_vlan_prio(struct rtnl_act *act, uint8_t *out_prio)
Get vlan prio.
Definition: vlan.c:372
int rtnl_vlan_set_mode(struct rtnl_act *act, int mode)
Set vlan mode.
Definition: vlan.c:188
int rtnl_vlan_set_protocol(struct rtnl_act *act, uint16_t protocol)
Set protocol.
Definition: vlan.c:269
int rtnl_vlan_set_vlan_prio(struct rtnl_act *act, uint8_t prio)
Set vlan prio.
Definition: vlan.c:350
int rtnl_vlan_set_action(struct rtnl_act *act, int action)
Set general action.
Definition: vlan.c:230
int rtnl_vlan_set_vlan_id(struct rtnl_act *act, uint16_t vid)
Set vlan id.
Definition: vlan.c:308
int rtnl_vlan_get_protocol(struct rtnl_act *act, uint16_t *out_protocol)
Get protocol.
Definition: vlan.c:288
int rtnl_vlan_get_vlan_id(struct rtnl_act *act, uint16_t *out_vid)
Get vlan id.
Definition: vlan.c:330
int rtnl_vlan_get_mode(struct rtnl_act *act, int *out_mode)
Get vlan mode.
Definition: vlan.c:210
int rtnl_vlan_get_action(struct rtnl_act *act, int *out_action)
Get general action.
Definition: vlan.c:249
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:652
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:212
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:194
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:159
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:602
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition: attr.c:346
@ NLA_U8
8 bit integer
Definition: attr.h:35
@ NLA_U16
16 bit integer
Definition: attr.h:36
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 minlen
Minimal length of payload required.
Definition: attr.h:68