libnl 3.11.0
macvlan.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2013 Michael Braun <michael-dev@fami-braun.de>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup macvlan MACVLAN/MACVTAP
9 * MAC-based Virtual LAN link module
10 *
11 * @details
12 * \b Link Type Name: "macvlan"
13 *
14 * @route_doc{link_macvlan, MACVLAN Documentation}
15 * @route_doc{link_macvtap, MACVTAP Documentation}
16 *
17 * @{
18 */
19
20#include "nl-default.h"
21
22#include <linux/if_link.h>
23
24#include <linux/ethtool.h>
25
26#include <netlink/netlink.h>
27#include <netlink/attr.h>
28#include <netlink/utils.h>
29#include <netlink/object.h>
30#include <netlink/route/rtnl.h>
31#include <netlink/route/link/macvlan.h>
32#include <netlink/route/link/macvtap.h>
33
34#include "nl-route.h"
35#include "link-api.h"
36
37/** @cond SKIP */
38#define MACVLAN_HAS_MODE (1<<0)
39#define MACVLAN_HAS_FLAGS (1<<1)
40#define MACVLAN_HAS_MACADDR (1<<2)
41
42struct macvlan_info
43{
44 uint32_t mvi_mode;
45 uint16_t mvi_flags; // there currently is only one flag and kernel has no flags_mask yet
46 uint32_t mvi_mask;
47 uint32_t mvi_maccount;
48 uint32_t mvi_macmode;
49 struct nl_addr **mvi_macaddr;
50};
51
52/** @endcond */
53
54static struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX+1] = {
56 [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
57 [IFLA_MACVLAN_MACADDR_MODE] = { .type = NLA_U32 },
58 [IFLA_MACVLAN_MACADDR] = { .type = NLA_UNSPEC },
60 [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
61};
62
63static int macvlan_alloc(struct rtnl_link *link)
64{
65 struct macvlan_info *mvi;
66 uint32_t i;
67
68 if (link->l_info) {
69 mvi = link->l_info;
70 for (i = 0; i < mvi->mvi_maccount; i++)
71 nl_addr_put(mvi->mvi_macaddr[i]);
72 free(mvi->mvi_macaddr);
73 memset(mvi, 0, sizeof(*mvi));
74 } else {
75 if ((mvi = calloc(1, sizeof(*mvi))) == NULL)
76 return -NLE_NOMEM;
77
78 link->l_info = mvi;
79 }
80 mvi->mvi_macmode = MACVLAN_MACADDR_SET;
81
82 return 0;
83}
84
85static int macvlan_parse(struct rtnl_link *link, struct nlattr *data,
86 struct nlattr *xstats)
87{
88 struct nlattr *tb[IFLA_MACVLAN_MAX+1];
89 struct macvlan_info *mvi;
90 struct nlattr *nla;
91 int len;
92 int err;
93
94 NL_DBG(3, "Parsing %s link info", link->l_info_ops->io_name);
95
96 if ((err = nla_parse_nested(tb, IFLA_MACVLAN_MAX, data, macvlan_policy)) < 0)
97 goto errout;
98
99 if ((err = macvlan_alloc(link)) < 0)
100 goto errout;
101
102 mvi = link->l_info;
103
104 if (tb[IFLA_MACVLAN_MODE]) {
105 mvi->mvi_mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]);
106 mvi->mvi_mask |= MACVLAN_HAS_MODE;
107 }
108
109 if (tb[IFLA_MACVLAN_FLAGS]) {
110 mvi->mvi_flags = nla_get_u16(tb[IFLA_MACVLAN_FLAGS]);
111 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
112 }
113
114 if ( tb[IFLA_MACVLAN_MACADDR_COUNT]
115 && tb[IFLA_MACVLAN_MACADDR_DATA]) {
116 mvi->mvi_maccount = nla_get_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]);
117 if (mvi->mvi_maccount > 0) {
118 uint32_t i;
119
120 nla = nla_data(tb[IFLA_MACVLAN_MACADDR_DATA]);
121 len = nla_len(tb[IFLA_MACVLAN_MACADDR_DATA]);
122
123 mvi->mvi_macaddr = calloc(mvi->mvi_maccount,
124 sizeof(*(mvi->mvi_macaddr)));
125 if (mvi->mvi_macaddr == NULL) {
126 err = -NLE_NOMEM;
127 goto errout;
128 }
129
130 i = 0;
131 for (; nla_ok(nla, len); nla = nla_next(nla, &len)) {
132 if (i >= mvi->mvi_maccount)
133 break;
134 if (nla_type(nla) != IFLA_MACVLAN_MACADDR ||
135 nla_len(nla) < ETH_ALEN)
136 continue;
137 mvi->mvi_macaddr[i] = nl_addr_alloc_attr(nla, AF_LLC);
138 i++;
139 }
140 }
141 mvi->mvi_mask |= MACVLAN_HAS_MACADDR;
142 }
143
144 err = 0;
145errout:
146 return err;
147}
148
149static void macvlan_free(struct rtnl_link *link)
150{
151 struct macvlan_info *mvi;
152 uint32_t i;
153
154 mvi = link->l_info;
155 if (!mvi)
156 return;
157
158 for (i = 0; i < mvi->mvi_maccount; i++)
159 nl_addr_put(mvi->mvi_macaddr[i]);
160 free(mvi->mvi_macaddr);
161 free(mvi);
162
163 link->l_info = NULL;
164}
165
166static void macvlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
167{
168 char buf[64];
169 uint32_t i;
170 struct macvlan_info *mvi = link->l_info;
171
172 if (mvi->mvi_mask & MACVLAN_HAS_MODE) {
173 rtnl_link_macvlan_mode2str(mvi->mvi_mode, buf, sizeof(buf));
174 nl_dump(p, " %s-mode %s", link->l_info_ops->io_name, buf);
175 }
176
177 if (mvi->mvi_mask & MACVLAN_HAS_FLAGS) {
178 rtnl_link_macvlan_flags2str(mvi->mvi_flags, buf, sizeof(buf));
179 nl_dump(p, " %s-flags %s", link->l_info_ops->io_name, buf);
180 }
181
182 if (mvi->mvi_mask & MACVLAN_HAS_MACADDR) {
183 nl_dump(p, " macvlan-count %u", (unsigned) mvi->mvi_maccount);
184
185 if (mvi->mvi_maccount)
186 nl_dump(p, " macvlan-sourcemac");
187
188 for (i = 0; i < mvi->mvi_maccount; i++) {
189 nl_dump(p, " %s", nl_addr2str(mvi->mvi_macaddr[i], buf,
190 sizeof(buf)));
191 }
192 }
193 nl_dump(p, "\n");
194}
195
196static int macvlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
197{
198 struct macvlan_info *vdst, *vsrc = src->l_info;
199 int err;
200 uint32_t i;
201
202 dst->l_info = NULL;
203 if ((err = rtnl_link_set_type(dst, "macvlan")) < 0)
204 return err;
205 vdst = dst->l_info;
206
207 if (!vdst || !vsrc)
208 return -NLE_NOMEM;
209
210 memcpy(vdst, vsrc, sizeof(struct macvlan_info));
211
212 if ( vsrc->mvi_mask & MACVLAN_HAS_MACADDR
213 && vsrc->mvi_maccount > 0) {
214 vdst->mvi_macaddr = calloc(vdst->mvi_maccount,
215 sizeof(*(vdst->mvi_macaddr)));
216 for (i = 0; i < vdst->mvi_maccount; i++)
217 vdst->mvi_macaddr[i] = nl_addr_clone(vsrc->mvi_macaddr[i]);
218 } else
219 vdst->mvi_macaddr = NULL;
220
221 return 0;
222}
223
224static int macvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
225{
226 struct macvlan_info *mvi = link->l_info;
227 struct nlattr *data, *datamac = NULL;
228 int ret;
229
230 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
231 return -NLE_MSGSIZE;
232
233 ret = -NLE_NOMEM;
234
235 if (mvi->mvi_mask & MACVLAN_HAS_MODE)
236 NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, mvi->mvi_mode);
237
238 if (mvi->mvi_mask & MACVLAN_HAS_FLAGS)
239 NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, mvi->mvi_flags);
240
241 if (mvi->mvi_mask & MACVLAN_HAS_MACADDR) {
242 uint32_t i;
243
244 NLA_PUT_U32(msg, IFLA_MACVLAN_MACADDR_MODE, mvi->mvi_macmode);
245 datamac = nla_nest_start(msg, IFLA_MACVLAN_MACADDR_DATA);
246 if (!datamac)
247 goto nla_put_failure;
248
249 for (i = 0; i < mvi->mvi_maccount; i++) {
250 NLA_PUT_ADDR(msg, IFLA_MACVLAN_MACADDR,
251 mvi->mvi_macaddr[i]);
252 }
253 }
254
255 ret = 0;
256
257nla_put_failure:
258 if (datamac)
259 nla_nest_end(msg, datamac);
260
261 nla_nest_end(msg, data);
262
263 return ret;
264}
265
266static struct rtnl_link_info_ops macvlan_info_ops = {
267 .io_name = "macvlan",
268 .io_alloc = macvlan_alloc,
269 .io_parse = macvlan_parse,
270 .io_dump = {
271 [NL_DUMP_DETAILS] = macvlan_dump_details,
272 },
273 .io_clone = macvlan_clone,
274 .io_put_attrs = macvlan_put_attrs,
275 .io_free = macvlan_free,
276};
277
278static struct rtnl_link_info_ops macvtap_info_ops = {
279 .io_name = "macvtap",
280 .io_alloc = macvlan_alloc,
281 .io_parse = macvlan_parse,
282 .io_dump = {
283 [NL_DUMP_DETAILS] = macvlan_dump_details,
284 },
285 .io_clone = macvlan_clone,
286 .io_put_attrs = macvlan_put_attrs,
287 .io_free = macvlan_free,
288};
289
290/** @cond SKIP */
291#define IS_MACVLAN_LINK_ASSERT(link) \
292 if ((link)->l_info_ops != &macvlan_info_ops) { \
293 APPBUG("Link is not a macvlan link. set type \"macvlan\" first."); \
294 return -NLE_OPNOTSUPP; \
295 }
296
297#define IS_MACVTAP_LINK_ASSERT(link) \
298 if ((link)->l_info_ops != &macvtap_info_ops) { \
299 APPBUG("Link is not a macvtap link. set type \"macvtap\" first."); \
300 return -NLE_OPNOTSUPP; \
301 }
302/** @endcond */
303
304/**
305 * @name MACVLAN Object
306 * @{
307 */
308
309/**
310 * Allocate link object of type MACVLAN
311 *
312 * @return Allocated link object or NULL.
313 */
315{
316 struct rtnl_link *link;
317
318 if (!(link = rtnl_link_alloc()))
319 return NULL;
320
321 if (rtnl_link_set_type(link, "macvlan") < 0) {
322 rtnl_link_put(link);
323 return NULL;
324 }
325
326 return link;
327}
328
329/**
330 * Check if link is a MACVLAN link
331 * @arg link Link object
332 *
333 * @return True if link is a MACVLAN link, otherwise false is returned.
334 */
336{
337 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvlan");
338}
339
340/**
341 * Set MACVLAN MODE
342 * @arg link Link object
343 * @arg mode MACVLAN mode
344 *
345 * @return 0 on success or a negative error code
346 */
347int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
348{
349 struct macvlan_info *mvi = link->l_info;
350
351 IS_MACVLAN_LINK_ASSERT(link);
352
353 mvi->mvi_mode = mode;
354 mvi->mvi_mask |= MACVLAN_HAS_MODE;
355
356 if (mode != MACVLAN_MODE_SOURCE) {
357 uint32_t i;
358
359 for (i = 0; i < mvi->mvi_maccount; i++)
360 nl_addr_put(mvi->mvi_macaddr[i]);
361 free(mvi->mvi_macaddr);
362 mvi->mvi_maccount = 0;
363 mvi->mvi_macaddr = NULL;
364 mvi->mvi_macmode = MACVLAN_MACADDR_SET;
365 mvi->mvi_mask &= ~MACVLAN_HAS_MACADDR;
366 }
367
368 return 0;
369}
370
371/**
372 * Get MACVLAN Mode
373 * @arg link Link object
374 *
375 * @return MACVLAN mode, 0 if not set or a negative error code.
376 */
378{
379 struct macvlan_info *mvi = link->l_info;
380
381 IS_MACVLAN_LINK_ASSERT(link);
382
383 if (mvi->mvi_mask & MACVLAN_HAS_MODE)
384 return mvi->mvi_mode;
385 else
386 return 0;
387}
388
389/**
390 * Set MACVLAN MACMODE
391 * @arg link Link object
392 * @arg mode MACVLAN mac list modification mode
393 *
394 * Only for macvlan SOURCE mode.
395 *
396 * @return 0 on success or a negative error code
397 */
398int rtnl_link_macvlan_set_macmode(struct rtnl_link *link, uint32_t macmode)
399{
400 struct macvlan_info *mvi = link->l_info;
401
402 IS_MACVLAN_LINK_ASSERT(link);
403
404 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
405 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
406 return -NLE_INVAL;
407
408 mvi->mvi_macmode = macmode;
409 mvi->mvi_mask |= MACVLAN_HAS_MACADDR;
410
411 return 0;
412}
413
414/**
415 * Get MACVLAN MACMODE
416 * @arg link Link object
417 * @arg out_macmode mac list modification mode
418 *
419 * Only for SOURCE mode.
420 *
421 * @return 0 on success or a negative error code.
422 */
423int rtnl_link_macvlan_get_macmode(struct rtnl_link *link, uint32_t *out_macmode)
424{
425 struct macvlan_info *mvi = link->l_info;
426
427 IS_MACVLAN_LINK_ASSERT(link);
428
429 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
430 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
431 return -NLE_INVAL;
432
433 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
434 return -NLE_INVAL;
435
436 *out_macmode = mvi->mvi_macmode;
437
438 return 0;
439}
440
441/**
442 * Set MACVLAN flags
443 * @arg link Link object
444 * @arg flags MACVLAN flags
445 *
446 * @return 0 on success or a negative error code.
447 */
448int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
449{
450 struct macvlan_info *mvi = link->l_info;
451
452 IS_MACVLAN_LINK_ASSERT(link);
453
454 mvi->mvi_flags |= flags;
455 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
456
457 return 0;
458}
459
460/**
461 * Unset MACVLAN flags
462 * @arg link Link object
463 * @arg flags MACVLAN flags
464 *
465 * Note: kernel currently only has a single flag and lacks flags_mask to
466 * indicate which flags shall be changed (it always all).
467 *
468 * @return 0 on success or a negative error code.
469 */
470int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
471{
472 struct macvlan_info *mvi = link->l_info;
473
474 IS_MACVLAN_LINK_ASSERT(link);
475
476 mvi->mvi_flags &= ~flags;
477 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
478
479 return 0;
480}
481
482/**
483 * Get MACVLAN flags
484 * @arg link Link object
485 *
486 * @return MACVLAN flags, 0 if none set, or a negative error code.
487 */
489{
490 struct macvlan_info *mvi = link->l_info;
491
492 IS_MACVLAN_LINK_ASSERT(link);
493
494 return mvi->mvi_flags;
495}
496
497/**
498 * Get number of MAC-Addr for MACVLAN device in source mode
499 * @arg link Link object
500 * @arg out_count number of mac addresses
501 *
502 * @return 0 on success or a negative error code.
503 */
504int rtnl_link_macvlan_count_macaddr(struct rtnl_link *link, uint32_t *out_count)
505{
506 struct macvlan_info *mvi = link->l_info;
507
508 IS_MACVLAN_LINK_ASSERT(link);
509
510 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
511 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
512 return -NLE_INVAL;
513
514 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
515 return -NLE_INVAL;
516
517 *out_count = mvi->mvi_maccount;
518
519 return 0;
520}
521
522/**
523 * Get configured remote MAC-Addr from MACVLAN device in source mode
524 * @arg link Link object
525 * @arg out_addr address object
526 *
527 * The returned nl_addr struct needs NOT to be released using nl_addr_put.
528 * It is only valid until the address is not removed from this link object
529 * or its mode is changed to non-source.
530 *
531 * @return 0 on success or negative error code
532 */
533int rtnl_link_macvlan_get_macaddr(struct rtnl_link *link, uint32_t idx,
534 const struct nl_addr **out_addr)
535{
536 struct macvlan_info *mvi = link->l_info;
537
538 IS_MACVLAN_LINK_ASSERT(link);
539
540 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
541 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
542 return -NLE_INVAL;
543
544 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
545 return -NLE_INVAL;
546
547 if (idx >= mvi->mvi_maccount)
548 return -NLE_INVAL;
549
550 *out_addr = mvi->mvi_macaddr[idx];
551 return 0;
552}
553
554/**
555 * Add MAC-Addr to MACVLAN device in source mode
556 * @arg link Link object
557 * @arg addr MAC-Addr
558 *
559 * addr is not release but cloned by this method.
560 *
561 * @return 0 on success or a negative error code.
562 */
563int rtnl_link_macvlan_add_macaddr(struct rtnl_link *link, struct nl_addr *addr)
564{
565 struct macvlan_info *mvi = link->l_info;
566 struct nl_addr **mvi_macaddr;
567 size_t newsize;
568
569 IS_MACVLAN_LINK_ASSERT(link);
570
571 if (nl_addr_get_family(addr) != AF_LLC)
572 return -NLE_INVAL;
573
574 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
575 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
576 return -NLE_INVAL;
577
578 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
579 return -NLE_INVAL;
580
581 if (mvi->mvi_maccount >= UINT32_MAX)
582 return -NLE_INVAL;
583
584 newsize = (mvi->mvi_maccount + 1) * sizeof(*(mvi->mvi_macaddr));
585 mvi_macaddr = realloc(mvi->mvi_macaddr, newsize);
586 if (!mvi_macaddr)
587 return -NLE_NOMEM;
588
589 mvi->mvi_macaddr = mvi_macaddr;
590 mvi->mvi_macaddr[mvi->mvi_maccount] = nl_addr_clone(addr);
591 mvi->mvi_maccount++;
592
593 mvi->mvi_mask |= MACVLAN_HAS_MACADDR;
594
595 return 0;
596}
597
598/**
599 * Remove MAC-Addr from MACVLAN device in source mode
600 * @arg link Link object
601 * @arg addr MAC-Addr
602 *
603 * addr is not release by this method.
604 *
605 * @return a negative error code on failure, or the number
606 * of deleted addresses on success.
607 */
608int rtnl_link_macvlan_del_macaddr(struct rtnl_link *link, struct nl_addr *addr)
609{
610 struct macvlan_info *mvi = link->l_info;
611 uint32_t found, i;
612
613 IS_MACVLAN_LINK_ASSERT(link);
614
615 if (nl_addr_get_family(addr) != AF_LLC)
616 return -NLE_INVAL;
617
618 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
619 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
620 return -NLE_INVAL;
621
622 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
623 return -NLE_INVAL;
624
625 nl_addr_get(addr);
626
627 found = 0; i = 0;
628 while (i + found < mvi->mvi_maccount) {
629 mvi->mvi_macaddr[i] = mvi->mvi_macaddr[i + found];
630 if (found > 0)
631 mvi->mvi_macaddr[i + found] = NULL;
632 if (nl_addr_cmp(addr, mvi->mvi_macaddr[i]) == 0) {
633 nl_addr_put(mvi->mvi_macaddr[i]);
634 mvi->mvi_macaddr[i] = NULL;
635 found++;
636 } else
637 i++;
638 }
639
640 nl_addr_put(addr);
641
642 mvi->mvi_maccount -= found;
643
644 return found > INT_MAX ? INT_MAX : (int) found;
645}
646
647/** @} */
648
649
650/**
651 * @name MACVTAP Object
652 * @{
653 */
654
655/**
656 * Allocate link object of type MACVTAP
657 *
658 * @return Allocated link object or NULL.
659 */
661{
662 struct rtnl_link *link;
663
664 if (!(link = rtnl_link_alloc()))
665 return NULL;
666
667 if (rtnl_link_set_type(link, "macvtap") < 0) {
668 rtnl_link_put(link);
669 return NULL;
670 }
671
672 return link;
673}
674
675/**
676 * Check if link is a MACVTAP link
677 * @arg link Link object
678 *
679 * @return True if link is a MACVTAP link, otherwise false is returned.
680 */
682{
683 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvtap");
684}
685
686/**
687 * Set MACVTAP MODE
688 * @arg link Link object
689 * @arg mode MACVTAP mode
690 *
691 * @return 0 on success or a negative error code
692 */
693int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode)
694{
695 struct macvlan_info *mvi = link->l_info;
696
697 IS_MACVTAP_LINK_ASSERT(link);
698
699 mvi->mvi_mode = mode;
700 mvi->mvi_mask |= MACVLAN_HAS_MODE;
701
702 return 0;
703}
704
705/**
706 * Get MACVTAP Mode
707 * @arg link Link object
708 *
709 * @return MACVTAP mode, 0 if not set or a negative error code.
710 */
712{
713 struct macvlan_info *mvi = link->l_info;
714
715 IS_MACVTAP_LINK_ASSERT(link);
716
717 if (mvi->mvi_mask & MACVLAN_HAS_MODE)
718 return mvi->mvi_mode;
719 else
720 return 0;
721}
722
723/**
724 * Set MACVTAP flags
725 * @arg link Link object
726 * @arg flags MACVTAP flags
727 *
728 * @return 0 on success or a negative error code.
729 */
730int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags)
731{
732 struct macvlan_info *mvi = link->l_info;
733
734 IS_MACVTAP_LINK_ASSERT(link);
735
736 mvi->mvi_flags |= flags;
737 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
738
739 return 0;
740}
741
742/**
743 * Unset MACVTAP flags
744 * @arg link Link object
745 * @arg flags MACVTAP flags
746 *
747 * Note: kernel currently only has a single flag and lacks flags_mask to
748 * indicate which flags shall be changed (it always all).
749 *
750 * @return 0 on success or a negative error code.
751 */
752int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags)
753{
754 struct macvlan_info *mvi = link->l_info;
755
756 IS_MACVTAP_LINK_ASSERT(link);
757
758 mvi->mvi_flags &= ~flags;
759 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
760
761 return 0;
762}
763
764/**
765 * Get MACVTAP flags
766 * @arg link Link object
767 *
768 * @return MACVTAP flags, 0 if none set, or a negative error code.
769 */
771{
772 struct macvlan_info *mvi = link->l_info;
773
774 IS_MACVTAP_LINK_ASSERT(link);
775
776 return mvi->mvi_flags;
777}
778
779/** @} */
780
781
782static const struct trans_tbl macvlan_flags[] = {
783 __ADD(MACVLAN_FLAG_NOPROMISC, nopromisc),
784};
785
786static const struct trans_tbl macvlan_modes[] = {
787 __ADD(MACVLAN_MODE_PRIVATE, private),
788 __ADD(MACVLAN_MODE_VEPA, vepa),
789 __ADD(MACVLAN_MODE_BRIDGE, bridge),
790 __ADD(MACVLAN_MODE_PASSTHRU, passthru),
791 __ADD(MACVLAN_MODE_SOURCE, source),
792};
793
794static const struct trans_tbl macvlan_macmodes[] = {
795 __ADD(MACVLAN_MACADDR_ADD, "add"),
796 __ADD(MACVLAN_MACADDR_DEL, "del"),
797 __ADD(MACVLAN_MACADDR_SET, "set"),
798 __ADD(MACVLAN_MACADDR_FLUSH, "flush"),
799};
800
801/**
802 * @name Flag Translation
803 * @{
804 */
805
806char *rtnl_link_macvlan_flags2str(int flags, char *buf, size_t len)
807{
808 return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
809}
810
811int rtnl_link_macvlan_str2flags(const char *name)
812{
813 return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
814}
815
816char *rtnl_link_macvtap_flags2str(int flags, char *buf, size_t len)
817{
818 return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
819}
820
821int rtnl_link_macvtap_str2flags(const char *name)
822{
823 return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
824}
825
826/** @} */
827
828/**
829 * @name Mode Translation
830 * @{
831 */
832
833char *rtnl_link_macvlan_mode2str(int mode, char *buf, size_t len)
834{
835 return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
836}
837
838int rtnl_link_macvlan_str2mode(const char *name)
839{
840 return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
841}
842
843char *rtnl_link_macvlan_macmode2str(int mode, char *buf, size_t len)
844{
845 return __type2str(mode, buf, len, macvlan_macmodes,
846 ARRAY_SIZE(macvlan_macmodes));
847}
848
849int rtnl_link_macvlan_str2macmode(const char *name)
850{
851 return __str2type(name, macvlan_macmodes, ARRAY_SIZE(macvlan_macmodes));
852}
853
854char *rtnl_link_macvtap_mode2str(int mode, char *buf, size_t len)
855{
856 return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
857}
858
859int rtnl_link_macvtap_str2mode(const char *name)
860{
861 return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
862}
863
864/** @} */
865
866static void _nl_init macvlan_init(void)
867{
868 rtnl_link_register_info(&macvlan_info_ops);
869 rtnl_link_register_info(&macvtap_info_ops);
870}
871
872static void _nl_exit macvlan_exit(void)
873{
874 rtnl_link_unregister_info(&macvlan_info_ops);
875 rtnl_link_unregister_info(&macvtap_info_ops);
876}
877
878/** @} */
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition addr.c:525
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition addr.c:261
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition addr.c:587
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition addr.c:495
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition addr.c:895
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition addr.c:1001
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition addr.c:541
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:714
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:664
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition attr.h:219
struct nlattr * nla_next(const struct nlattr *nla, int *remaining)
Return next attribute in a stream of attributes.
Definition attr.c:172
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition attr.c:108
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition attr.h:290
int nla_ok(const struct nlattr *nla, int remaining)
Check if the attribute header and payload can be accessed safely.
Definition attr.c:147
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:237
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:974
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:1101
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:1037
@ NLA_UNSPEC
Unspecified type, binary data chunk.
Definition attr.h:34
@ NLA_U16
16 bit integer
Definition attr.h:36
@ NLA_NESTED
Nested attributes.
Definition attr.h:42
@ NLA_U32
32 bit integer
Definition attr.h:37
int rtnl_link_macvlan_get_macmode(struct rtnl_link *link, uint32_t *out_macmode)
Get MACVLAN MACMODE.
Definition macvlan.c:423
int rtnl_link_is_macvtap(struct rtnl_link *link)
Check if link is a MACVTAP link.
Definition macvlan.c:681
int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVTAP flags.
Definition macvlan.c:730
int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVLAN flags.
Definition macvlan.c:470
int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVLAN MODE.
Definition macvlan.c:347
uint32_t rtnl_link_macvtap_get_mode(struct rtnl_link *link)
Get MACVTAP Mode.
Definition macvlan.c:711
struct rtnl_link * rtnl_link_macvlan_alloc(void)
Allocate link object of type MACVLAN.
Definition macvlan.c:314
int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVTAP MODE.
Definition macvlan.c:693
uint16_t rtnl_link_macvtap_get_flags(struct rtnl_link *link)
Get MACVTAP flags.
Definition macvlan.c:770
uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link)
Get MACVLAN Mode.
Definition macvlan.c:377
int rtnl_link_macvlan_set_macmode(struct rtnl_link *link, uint32_t macmode)
Set MACVLAN MACMODE.
Definition macvlan.c:398
int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVTAP flags.
Definition macvlan.c:752
int rtnl_link_macvlan_get_macaddr(struct rtnl_link *link, uint32_t idx, const struct nl_addr **out_addr)
Get configured remote MAC-Addr from MACVLAN device in source mode.
Definition macvlan.c:533
int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVLAN flags.
Definition macvlan.c:448
int rtnl_link_macvlan_del_macaddr(struct rtnl_link *link, struct nl_addr *addr)
Remove MAC-Addr from MACVLAN device in source mode.
Definition macvlan.c:608
uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *link)
Get MACVLAN flags.
Definition macvlan.c:488
int rtnl_link_is_macvlan(struct rtnl_link *link)
Check if link is a MACVLAN link.
Definition macvlan.c:335
int rtnl_link_macvlan_add_macaddr(struct rtnl_link *link, struct nl_addr *addr)
Add MAC-Addr to MACVLAN device in source mode.
Definition macvlan.c:563
struct rtnl_link * rtnl_link_macvtap_alloc(void)
Allocate link object of type MACVTAP.
Definition macvlan.c:660
int rtnl_link_macvlan_count_macaddr(struct rtnl_link *link, uint32_t *out_count)
Get number of MAC-Addr for MACVLAN device in source mode.
Definition macvlan.c:504
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
@ 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