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