libnl 3.7.0
vlan.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup vlan VLAN
9 * Virtual LAN link module
10 *
11 * @details
12 * \b Link Type Name: "vlan"
13 *
14 * @route_doc{link_vlan, VLAN Documentation}
15 *
16 * @{
17 */
18
19#include <netlink-private/netlink.h>
20#include <netlink/netlink.h>
21#include <netlink/attr.h>
22#include <netlink/utils.h>
23#include <netlink/object.h>
24#include <netlink/route/rtnl.h>
25#include <netlink-private/route/link/api.h>
26#include <netlink/route/link/vlan.h>
27
28#include <linux/if_vlan.h>
29
30/** @cond SKIP */
31#define VLAN_HAS_ID (1<<0)
32#define VLAN_HAS_FLAGS (1<<1)
33#define VLAN_HAS_INGRESS_QOS (1<<2)
34#define VLAN_HAS_EGRESS_QOS (1<<3)
35#define VLAN_HAS_PROTOCOL (1<<4)
36
37struct vlan_info
38{
39 uint16_t vi_vlan_id;
40 uint16_t vi_protocol;
41 unsigned int vi_ingress_qos_mask:(VLAN_PRIO_MAX+1);
42 uint32_t vi_flags;
43 uint32_t vi_flags_mask;
44 uint32_t vi_ingress_qos[VLAN_PRIO_MAX+1];
45 uint32_t vi_negress;
46 uint32_t vi_egress_size;
47 struct vlan_map * vi_egress_qos;
48 uint32_t vi_mask;
49};
50
51/** @endcond */
52
53static struct nla_policy vlan_policy[IFLA_VLAN_MAX+1] = {
54 [IFLA_VLAN_ID] = { .type = NLA_U16 },
55 [IFLA_VLAN_FLAGS] = { .minlen = sizeof(struct ifla_vlan_flags) },
56 [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
57 [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED },
58 [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 },
59};
60
61static int vlan_alloc(struct rtnl_link *link)
62{
63 struct vlan_info *vi;
64
65 if (link->l_info) {
66 vi = link->l_info;
67 free(vi->vi_egress_qos);
68 memset(link->l_info, 0, sizeof(*vi));
69 } else {
70 if ((vi = calloc(1, sizeof(*vi))) == NULL)
71 return -NLE_NOMEM;
72
73 link->l_info = vi;
74 }
75
76 return 0;
77}
78
79static int vlan_parse(struct rtnl_link *link, struct nlattr *data,
80 struct nlattr *xstats)
81{
82 struct nlattr *tb[IFLA_VLAN_MAX+1];
83 struct vlan_info *vi;
84 int err;
85
86 NL_DBG(3, "Parsing VLAN link info\n");
87
88 if ((err = nla_parse_nested(tb, IFLA_VLAN_MAX, data, vlan_policy)) < 0)
89 goto errout;
90
91 if ((err = vlan_alloc(link)) < 0)
92 goto errout;
93
94 vi = link->l_info;
95
96 if (tb[IFLA_VLAN_ID]) {
97 vi->vi_vlan_id = nla_get_u16(tb[IFLA_VLAN_ID]);
98 vi->vi_mask |= VLAN_HAS_ID;
99 }
100
101 if (tb[IFLA_VLAN_PROTOCOL]) {
102 vi->vi_protocol = nla_get_u16(tb[IFLA_VLAN_PROTOCOL]);
103 vi->vi_mask |= VLAN_HAS_PROTOCOL;
104 }
105
106 if (tb[IFLA_VLAN_FLAGS]) {
107 struct ifla_vlan_flags flags;
108 nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags));
109
110 vi->vi_flags = flags.flags;
111 vi->vi_mask |= VLAN_HAS_FLAGS;
112 }
113
114 if (tb[IFLA_VLAN_INGRESS_QOS]) {
115 struct ifla_vlan_qos_mapping *map;
116 struct nlattr *nla;
117 int remaining;
118
119 vi->vi_ingress_qos_mask = 0;
120 memset(vi->vi_ingress_qos, 0, sizeof(vi->vi_ingress_qos));
121
122 nla_for_each_nested(nla, tb[IFLA_VLAN_INGRESS_QOS], remaining) {
123 if (nla_len(nla) < sizeof(*map))
124 return -NLE_INVAL;
125
126 map = nla_data(nla);
127 if (map->from > VLAN_PRIO_MAX) {
128 return -NLE_INVAL;
129 }
130
131 /* Kernel will not explicitly serialize mappings with "to" zero
132 * (although they are implicitly set).
133 *
134 * Thus we only mark those as "set" which are explicitly sent.
135 * That is similar to what we do with the egress map and it preserves
136 * previous behavior before NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR.
137 *
138 * It matters only when a received object is send back to kernel to modify
139 * the link.
140 */
141 vi->vi_ingress_qos_mask |= (1 << map->from);
142 vi->vi_ingress_qos[map->from] = map->to;
143 }
144
145 vi->vi_mask |= VLAN_HAS_INGRESS_QOS;
146 }
147
148 if (tb[IFLA_VLAN_EGRESS_QOS]) {
149 struct ifla_vlan_qos_mapping *map;
150 struct nlattr *nla;
151 int remaining, i = 0;
152
153 nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) {
154 if (nla_len(nla) < sizeof(*map))
155 return -NLE_INVAL;
156 i++;
157 }
158
159 /* align to have a little reserve */
160 vi->vi_egress_size = (i + 32) & ~31;
161 vi->vi_egress_qos = calloc(vi->vi_egress_size, sizeof(*vi->vi_egress_qos));
162 if (vi->vi_egress_qos == NULL)
163 return -NLE_NOMEM;
164
165 i = 0;
166 nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) {
167 map = nla_data(nla);
168 NL_DBG(4, "Assigning egress qos mapping %d\n", i);
169 vi->vi_egress_qos[i].vm_from = map->from;
170 vi->vi_egress_qos[i++].vm_to = map->to;
171 }
172
173 vi->vi_negress = i;
174 vi->vi_mask |= VLAN_HAS_EGRESS_QOS;
175 }
176
177 err = 0;
178errout:
179 return err;
180}
181
182static void vlan_free(struct rtnl_link *link)
183{
184 struct vlan_info *vi = link->l_info;
185
186 if (vi) {
187 free(vi->vi_egress_qos);
188 vi->vi_egress_qos = NULL;
189 }
190
191 free(vi);
192 link->l_info = NULL;
193}
194
195static void vlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
196{
197 struct vlan_info *vi = link->l_info;
198
199 nl_dump(p, "vlan-id %d", vi->vi_vlan_id);
200}
201
202static void vlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
203{
204 struct vlan_info *vi = link->l_info;
205 int printed;
206 uint32_t i;
207 char buf[64];
208
209 rtnl_link_vlan_flags2str(vi->vi_flags, buf, sizeof(buf));
210 nl_dump_line(p, " vlan-info id %d <%s>", vi->vi_vlan_id, buf);
211
212 if (vi->vi_mask & VLAN_HAS_PROTOCOL)
213 nl_dump_line(p, " vlan protocol <%d>", ntohs(vi->vi_protocol));
214
215 nl_dump(p, "\n");
216
217 if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) {
218 nl_dump_line(p,
219 " ingress vlan prio -> qos/socket prio mapping:\n");
220 for (i = 0, printed = 0; i <= VLAN_PRIO_MAX; i++) {
221 if (vi->vi_ingress_qos_mask & (1 << i)) {
222 if (printed == 0)
223 nl_dump_line(p, " ");
224 nl_dump(p, "%x -> %#08x, ",
225 i, vi->vi_ingress_qos[i]);
226 if (printed++ == 3) {
227 nl_dump(p, "\n");
228 printed = 0;
229 }
230 }
231 }
232
233 if (printed > 0 && printed != 4)
234 nl_dump(p, "\n");
235 }
236
237 if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
238 nl_dump_line(p,
239 " egress qos/socket prio -> vlan prio mapping:\n");
240 for (i = 0, printed = 0; i < vi->vi_negress; i++) {
241 if (printed == 0)
242 nl_dump_line(p, " ");
243 nl_dump(p, "%#08x -> %x, ",
244 vi->vi_egress_qos[i].vm_from,
245 vi->vi_egress_qos[i].vm_to);
246 if (printed++ == 3) {
247 nl_dump(p, "\n");
248 printed = 0;
249 }
250 }
251
252 if (printed > 0 && printed != 4)
253 nl_dump(p, "\n");
254 }
255}
256
257static int vlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
258{
259 struct vlan_info *vdst, *vsrc = src->l_info;
260 int err;
261 struct vlan_map *p = NULL;
262
263 dst->l_info = NULL;
264 if ((err = rtnl_link_set_type(dst, "vlan")) < 0)
265 return err;
266 vdst = dst->l_info;
267
268 if (vsrc->vi_negress) {
269 p = calloc(vsrc->vi_negress,
270 sizeof(struct vlan_map));
271 if (!p)
272 return -NLE_NOMEM;
273 }
274
275 *vdst = *vsrc;
276
277 if (vsrc->vi_negress) {
278 vdst->vi_egress_size = vsrc->vi_negress;
279 vdst->vi_egress_qos = p;
280 memcpy(vdst->vi_egress_qos, vsrc->vi_egress_qos,
281 vsrc->vi_negress * sizeof(struct vlan_map));
282 }
283
284 return 0;
285}
286
287static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
288{
289 struct vlan_info *vi = link->l_info;
290 struct nlattr *data;
291 int nest_count = 0;
292
293 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
294 goto nla_put_failure;
295
296 nest_count++;
297
298 if (vi->vi_mask & VLAN_HAS_ID)
299 NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id);
300
301 if (vi->vi_mask & VLAN_HAS_PROTOCOL)
302 NLA_PUT_U16(msg, IFLA_VLAN_PROTOCOL, vi->vi_protocol);
303
304 if (vi->vi_mask & VLAN_HAS_FLAGS) {
305 struct ifla_vlan_flags flags = {
306 .flags = vi->vi_flags,
307 .mask = vi->vi_flags_mask,
308 };
309
310 NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags);
311 }
312
313 if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) {
314 struct ifla_vlan_qos_mapping map;
315 struct nlattr *qos;
316 int i;
317
318 if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
319 goto nla_put_failure;
320
321 nest_count++;
322
323 for (i = 0; i <= VLAN_PRIO_MAX; i++) {
324 if (vi->vi_ingress_qos_mask & (1 << i)) {
325 map.from = i;
326 map.to = vi->vi_ingress_qos[i];
327
328 NLA_PUT(msg, i, sizeof(map), &map);
329 }
330 }
331
332 nla_nest_end(msg, qos);
333 nest_count--;
334 }
335
336 if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
337 struct ifla_vlan_qos_mapping map;
338 struct nlattr *qos;
339 uint32_t i;
340
341 if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
342 goto nla_put_failure;
343
344 nest_count++;
345
346 for (i = 0; i < vi->vi_negress; i++) {
347 map.from = vi->vi_egress_qos[i].vm_from;
348 map.to = vi->vi_egress_qos[i].vm_to;
349
350 NLA_PUT(msg, i, sizeof(map), &map);
351 }
352
353 nla_nest_end(msg, qos);
354 nest_count--;
355 }
356
357 nla_nest_end(msg, data);
358 return 0;
359
360nla_put_failure:
361 for (; nest_count > 0; nest_count--)
362 nla_nest_cancel(msg, data);
363 return -NLE_MSGSIZE;
364}
365
366static struct rtnl_link_info_ops vlan_info_ops = {
367 .io_name = "vlan",
368 .io_alloc = vlan_alloc,
369 .io_parse = vlan_parse,
370 .io_dump = {
371 [NL_DUMP_LINE] = vlan_dump_line,
372 [NL_DUMP_DETAILS] = vlan_dump_details,
373 },
374 .io_clone = vlan_clone,
375 .io_put_attrs = vlan_put_attrs,
376 .io_free = vlan_free,
377};
378
379/** @cond SKIP */
380#define IS_VLAN_LINK_ASSERT(link) \
381 if ((link)->l_info_ops != &vlan_info_ops) { \
382 APPBUG("Link is not a vlan link. set type \"vlan\" first."); \
383 return -NLE_OPNOTSUPP; \
384 }
385/** @endcond */
386
387/**
388 * @name VLAN Object
389 * @{
390 */
391
392/**
393 * Allocate link object of type VLAN
394 *
395 * @return Allocated link object or NULL.
396 */
398{
399 struct rtnl_link *link;
400
401 if (!(link = rtnl_link_alloc()))
402 return NULL;
403
404 if (rtnl_link_set_type(link, "vlan") < 0) {
405 rtnl_link_put(link);
406 return NULL;
407 }
408
409 return link;
410}
411
412/**
413 * Check if link is a VLAN link
414 * @arg link Link object
415 *
416 * @return True if link is a VLAN link, otherwise false is returned.
417 */
419{
420 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vlan");
421}
422
423/**
424 * Set VLAN ID
425 * @arg link Link object
426 * @arg id VLAN identifier
427 *
428 * @return 0 on success or a negative error code
429 */
430int rtnl_link_vlan_set_id(struct rtnl_link *link, uint16_t id)
431{
432 struct vlan_info *vi = link->l_info;
433
434 IS_VLAN_LINK_ASSERT(link);
435
436 vi->vi_vlan_id = id;
437 vi->vi_mask |= VLAN_HAS_ID;
438
439 return 0;
440}
441
442/**
443 * Get VLAN Id
444 * @arg link Link object
445 *
446 * @return VLAN id, 0 if not set or a negative error code.
447 */
449{
450 struct vlan_info *vi = link->l_info;
451
452 IS_VLAN_LINK_ASSERT(link);
453
454 if (vi->vi_mask & VLAN_HAS_ID)
455 return vi->vi_vlan_id;
456 else
457 return 0;
458}
459
460/**
461 * Set VLAN protocol
462 * @arg link Link object
463 * @arg protocol VLAN protocol in network byte order.
464 * Probably you want to set it to something like htons(ETH_P_8021Q).
465 *
466 * @return 0 on success or a negative error code
467 */
468int rtnl_link_vlan_set_protocol(struct rtnl_link *link, uint16_t protocol)
469{
470 struct vlan_info *vi = link->l_info;
471
472 IS_VLAN_LINK_ASSERT(link);
473
474 vi->vi_protocol = protocol;
475 vi->vi_mask |= VLAN_HAS_PROTOCOL;
476
477 return 0;
478}
479
480/**
481 * Get VLAN protocol
482 * @arg link Link object
483 *
484 * @return VLAN protocol in network byte order like htons(ETH_P_8021Q),
485 * 0 if not set or a negative error code.
486 */
488{
489 struct vlan_info *vi = link->l_info;
490
491 IS_VLAN_LINK_ASSERT(link);
492
493 if (vi->vi_mask & VLAN_HAS_PROTOCOL)
494 return vi->vi_protocol;
495 else
496 return 0;
497}
498
499/**
500 * Set VLAN flags
501 * @arg link Link object
502 * @arg flags VLAN flags
503 *
504 * @return 0 on success or a negative error code.
505 */
506int rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags)
507{
508 struct vlan_info *vi = link->l_info;
509
510 IS_VLAN_LINK_ASSERT(link);
511
512 vi->vi_flags_mask |= flags;
513 vi->vi_flags |= flags;
514 vi->vi_mask |= VLAN_HAS_FLAGS;
515
516 return 0;
517}
518
519/**
520 * Unset VLAN flags
521 * @arg link Link object
522 * @arg flags VLAN flags
523 *
524 * @return 0 on success or a negative error code.
525 */
526int rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags)
527{
528 struct vlan_info *vi = link->l_info;
529
530 IS_VLAN_LINK_ASSERT(link);
531
532 vi->vi_flags_mask |= flags;
533 vi->vi_flags &= ~flags;
534 vi->vi_mask |= VLAN_HAS_FLAGS;
535
536 return 0;
537}
538
539/**
540 * Get VLAN flags
541 * @arg link Link object
542 *
543 * @return VLAN flags, 0 if none set, or a negative error code.
544 */
546{
547 struct vlan_info *vi = link->l_info;
548
549 IS_VLAN_LINK_ASSERT(link);
550
551 return vi->vi_flags;
552}
553
554/** @} */
555
556/**
557 * @name Quality of Service
558 * @{
559 */
560
561int rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from,
562 uint32_t to)
563{
564 struct vlan_info *vi = link->l_info;
565
566 IS_VLAN_LINK_ASSERT(link);
567
568 if (from < 0 || from > VLAN_PRIO_MAX)
569 return -NLE_INVAL;
570
571 vi->vi_ingress_qos_mask |= (1 << from);
572 vi->vi_ingress_qos[from] = to;
573 vi->vi_mask |= VLAN_HAS_INGRESS_QOS;
574
575 return 0;
576}
577
578uint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *link)
579{
580 struct vlan_info *vi = link->l_info;
581
582 if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
583 return NULL;
584
585 if (vi->vi_mask & VLAN_HAS_INGRESS_QOS)
586 return vi->vi_ingress_qos;
587 else
588 return NULL;
589}
590
591int rtnl_link_vlan_set_egress_map(struct rtnl_link *link, uint32_t from, int to)
592{
593 struct vlan_info *vi = link->l_info;
594
595 if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
596 return -NLE_OPNOTSUPP;
597
598 if (to < 0 || to > VLAN_PRIO_MAX)
599 return -NLE_INVAL;
600
601 if (vi->vi_negress >= vi->vi_egress_size) {
602 uint32_t new_size = vi->vi_egress_size + 1 + vi->vi_egress_size / 2;
603 size_t bytes;
604 void *ptr;
605
606 if (new_size < vi->vi_egress_size)
607 return -NLE_NOMEM;
608 bytes = (size_t) new_size * sizeof(struct vlan_map);
609 if (bytes / sizeof (struct vlan_map) != new_size)
610 return -NLE_NOMEM;
611 ptr = realloc(vi->vi_egress_qos, bytes);
612 if (!ptr)
613 return -NLE_NOMEM;
614
615 vi->vi_egress_qos = ptr;
616 vi->vi_egress_size = new_size;
617 }
618
619 vi->vi_egress_qos[vi->vi_negress].vm_from = from;
620 vi->vi_egress_qos[vi->vi_negress].vm_to = to;
621 vi->vi_negress++;
622 vi->vi_mask |= VLAN_HAS_EGRESS_QOS;
623
624 return 0;
625}
626
627struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *link,
628 int *negress)
629{
630 struct vlan_info *vi = link->l_info;
631
632 if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
633 return NULL;
634
635 if (negress == NULL)
636 return NULL;
637
638 if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
639 *negress = vi->vi_negress;
640 return vi->vi_egress_qos;
641 } else {
642 *negress = 0;
643 return NULL;
644 }
645}
646
647/** @} */
648
649static const struct trans_tbl vlan_flags[] = {
650 __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr),
651 __ADD(VLAN_FLAG_GVRP, gvrp),
652 __ADD(VLAN_FLAG_LOOSE_BINDING, loose_binding),
653 __ADD(VLAN_FLAG_MVRP, mvrp),
654 __ADD(VLAN_FLAG_BRIDGE_BINDING, bridge_binding),
655};
656
657/**
658 * @name Flag Translation
659 * @{
660 */
661
662char *rtnl_link_vlan_flags2str(int flags, char *buf, size_t len)
663{
664 return __flags2str(flags, buf, len, vlan_flags, ARRAY_SIZE(vlan_flags));
665}
666
667int rtnl_link_vlan_str2flags(const char *name)
668{
669 return __str2flags(name, vlan_flags, ARRAY_SIZE(vlan_flags));
670}
671
672/** @} */
673
674
675static void __init vlan_init(void)
676{
677 rtnl_link_register_info(&vlan_info_ops);
678}
679
680static void __exit vlan_exit(void)
681{
682 rtnl_link_unregister_info(&vlan_info_ops);
683}
684
685/** @} */
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
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:114
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:159
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition: attr.c:346
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:898
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1016
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
Definition: attr.c:990
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition: attr.h:324
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:125
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:961
@ NLA_U16
16 bit integer
Definition: attr.h:36
@ NLA_NESTED
Nested attributes.
Definition: attr.h:42
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
int rtnl_link_vlan_get_protocol(struct rtnl_link *link)
Get VLAN protocol.
Definition: vlan.c:487
int rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset VLAN flags.
Definition: vlan.c:526
int rtnl_link_vlan_set_id(struct rtnl_link *link, uint16_t id)
Set VLAN ID.
Definition: vlan.c:430
int rtnl_link_vlan_set_protocol(struct rtnl_link *link, uint16_t protocol)
Set VLAN protocol.
Definition: vlan.c:468
int rtnl_link_is_vlan(struct rtnl_link *link)
Check if link is a VLAN link.
Definition: vlan.c:418
int rtnl_link_vlan_get_id(struct rtnl_link *link)
Get VLAN Id.
Definition: vlan.c:448
struct rtnl_link * rtnl_link_vlan_alloc(void)
Allocate link object of type VLAN.
Definition: vlan.c:397
int rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags)
Set VLAN flags.
Definition: vlan.c:506
int rtnl_link_vlan_get_flags(struct rtnl_link *link)
Get VLAN flags.
Definition: vlan.c:545
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
Definition: vlan.h:17