libnl 3.9.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] = {
55 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
56 [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
57 [IFLA_MACVLAN_MACADDR_MODE] = { .type = NLA_U32 },
58 [IFLA_MACVLAN_MACADDR] = { .type = NLA_UNSPEC },
59 [IFLA_MACVLAN_MACADDR_DATA] = { .type = NLA_NESTED },
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 i, 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 NLA_PUT_U32(msg, IFLA_MACVLAN_MACADDR_MODE, mvi->mvi_macmode);
243 datamac = nla_nest_start(msg, IFLA_MACVLAN_MACADDR_DATA);
244 if (!datamac)
245 goto nla_put_failure;
246
247 for (i = 0; i < mvi->mvi_maccount; i++) {
248 NLA_PUT_ADDR(msg, IFLA_MACVLAN_MACADDR,
249 mvi->mvi_macaddr[i]);
250 }
251 }
252
253 ret = 0;
254
255nla_put_failure:
256 if (datamac)
257 nla_nest_end(msg, datamac);
258
259 nla_nest_end(msg, data);
260
261 return ret;
262}
263
264static struct rtnl_link_info_ops macvlan_info_ops = {
265 .io_name = "macvlan",
266 .io_alloc = macvlan_alloc,
267 .io_parse = macvlan_parse,
268 .io_dump = {
269 [NL_DUMP_DETAILS] = macvlan_dump_details,
270 },
271 .io_clone = macvlan_clone,
272 .io_put_attrs = macvlan_put_attrs,
273 .io_free = macvlan_free,
274};
275
276static struct rtnl_link_info_ops macvtap_info_ops = {
277 .io_name = "macvtap",
278 .io_alloc = macvlan_alloc,
279 .io_parse = macvlan_parse,
280 .io_dump = {
281 [NL_DUMP_DETAILS] = macvlan_dump_details,
282 },
283 .io_clone = macvlan_clone,
284 .io_put_attrs = macvlan_put_attrs,
285 .io_free = macvlan_free,
286};
287
288/** @cond SKIP */
289#define IS_MACVLAN_LINK_ASSERT(link) \
290 if ((link)->l_info_ops != &macvlan_info_ops) { \
291 APPBUG("Link is not a macvlan link. set type \"macvlan\" first."); \
292 return -NLE_OPNOTSUPP; \
293 }
294
295#define IS_MACVTAP_LINK_ASSERT(link) \
296 if ((link)->l_info_ops != &macvtap_info_ops) { \
297 APPBUG("Link is not a macvtap link. set type \"macvtap\" first."); \
298 return -NLE_OPNOTSUPP; \
299 }
300/** @endcond */
301
302/**
303 * @name MACVLAN Object
304 * @{
305 */
306
307/**
308 * Allocate link object of type MACVLAN
309 *
310 * @return Allocated link object or NULL.
311 */
313{
314 struct rtnl_link *link;
315
316 if (!(link = rtnl_link_alloc()))
317 return NULL;
318
319 if (rtnl_link_set_type(link, "macvlan") < 0) {
320 rtnl_link_put(link);
321 return NULL;
322 }
323
324 return link;
325}
326
327/**
328 * Check if link is a MACVLAN link
329 * @arg link Link object
330 *
331 * @return True if link is a MACVLAN link, otherwise false is returned.
332 */
334{
335 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvlan");
336}
337
338/**
339 * Set MACVLAN MODE
340 * @arg link Link object
341 * @arg mode MACVLAN mode
342 *
343 * @return 0 on success or a negative error code
344 */
345int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
346{
347 struct macvlan_info *mvi = link->l_info;
348 int i;
349
350 IS_MACVLAN_LINK_ASSERT(link);
351
352 mvi->mvi_mode = mode;
353 mvi->mvi_mask |= MACVLAN_HAS_MODE;
354
355 if (mode != MACVLAN_MODE_SOURCE) {
356 for (i = 0; i < mvi->mvi_maccount; i++)
357 nl_addr_put(mvi->mvi_macaddr[i]);
358 free(mvi->mvi_macaddr);
359 mvi->mvi_maccount = 0;
360 mvi->mvi_macaddr = NULL;
361 mvi->mvi_macmode = MACVLAN_MACADDR_SET;
362 mvi->mvi_mask &= ~MACVLAN_HAS_MACADDR;
363 }
364
365 return 0;
366}
367
368/**
369 * Get MACVLAN Mode
370 * @arg link Link object
371 *
372 * @return MACVLAN mode, 0 if not set or a negative error code.
373 */
375{
376 struct macvlan_info *mvi = link->l_info;
377
378 IS_MACVLAN_LINK_ASSERT(link);
379
380 if (mvi->mvi_mask & MACVLAN_HAS_MODE)
381 return mvi->mvi_mode;
382 else
383 return 0;
384}
385
386/**
387 * Set MACVLAN MACMODE
388 * @arg link Link object
389 * @arg mode MACVLAN mac list modification mode
390 *
391 * Only for macvlan SOURCE mode.
392 *
393 * @return 0 on success or a negative error code
394 */
395int rtnl_link_macvlan_set_macmode(struct rtnl_link *link, uint32_t macmode)
396{
397 struct macvlan_info *mvi = link->l_info;
398
399 IS_MACVLAN_LINK_ASSERT(link);
400
401 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
402 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
403 return -NLE_INVAL;
404
405 mvi->mvi_macmode = macmode;
406 mvi->mvi_mask |= MACVLAN_HAS_MACADDR;
407
408 return 0;
409}
410
411/**
412 * Get MACVLAN MACMODE
413 * @arg link Link object
414 * @arg out_macmode mac list modification mode
415 *
416 * Only for SOURCE mode.
417 *
418 * @return 0 on success or a negative error code.
419 */
420int rtnl_link_macvlan_get_macmode(struct rtnl_link *link, uint32_t *out_macmode)
421{
422 struct macvlan_info *mvi = link->l_info;
423
424 IS_MACVLAN_LINK_ASSERT(link);
425
426 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
427 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
428 return -NLE_INVAL;
429
430 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
431 return -NLE_INVAL;
432
433 *out_macmode = mvi->mvi_macmode;
434
435 return 0;
436}
437
438/**
439 * Set MACVLAN flags
440 * @arg link Link object
441 * @arg flags MACVLAN flags
442 *
443 * @return 0 on success or a negative error code.
444 */
445int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
446{
447 struct macvlan_info *mvi = link->l_info;
448
449 IS_MACVLAN_LINK_ASSERT(link);
450
451 mvi->mvi_flags |= flags;
452 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
453
454 return 0;
455}
456
457/**
458 * Unset MACVLAN flags
459 * @arg link Link object
460 * @arg flags MACVLAN flags
461 *
462 * Note: kernel currently only has a single flag and lacks flags_mask to
463 * indicate which flags shall be changed (it always all).
464 *
465 * @return 0 on success or a negative error code.
466 */
467int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
468{
469 struct macvlan_info *mvi = link->l_info;
470
471 IS_MACVLAN_LINK_ASSERT(link);
472
473 mvi->mvi_flags &= ~flags;
474 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
475
476 return 0;
477}
478
479/**
480 * Get MACVLAN flags
481 * @arg link Link object
482 *
483 * @return MACVLAN flags, 0 if none set, or a negative error code.
484 */
486{
487 struct macvlan_info *mvi = link->l_info;
488
489 IS_MACVLAN_LINK_ASSERT(link);
490
491 return mvi->mvi_flags;
492}
493
494/**
495 * Get number of MAC-Addr for MACVLAN device in source mode
496 * @arg link Link object
497 * @arg out_count number of mac addresses
498 *
499 * @return 0 on success or a negative error code.
500 */
501int rtnl_link_macvlan_count_macaddr(struct rtnl_link *link, uint32_t *out_count)
502{
503 struct macvlan_info *mvi = link->l_info;
504
505 IS_MACVLAN_LINK_ASSERT(link);
506
507 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
508 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
509 return -NLE_INVAL;
510
511 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
512 return -NLE_INVAL;
513
514 *out_count = mvi->mvi_maccount;
515
516 return 0;
517}
518
519/**
520 * Get configured remote MAC-Addr from MACVLAN device in source mode
521 * @arg link Link object
522 * @arg out_addr address object
523 *
524 * The returned nl_addr struct needs NOT to be released using nl_addr_put.
525 * It is only valid until the address is not removed from this link object
526 * or its mode is changed to non-source.
527 *
528 * @return 0 on success or negative error code
529 */
530int rtnl_link_macvlan_get_macaddr(struct rtnl_link *link, uint32_t idx,
531 const struct nl_addr **out_addr)
532{
533 struct macvlan_info *mvi = link->l_info;
534
535 IS_MACVLAN_LINK_ASSERT(link);
536
537 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
538 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
539 return -NLE_INVAL;
540
541 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
542 return -NLE_INVAL;
543
544 if (idx >= mvi->mvi_maccount)
545 return -NLE_INVAL;
546
547 *out_addr = mvi->mvi_macaddr[idx];
548 return 0;
549}
550
551/**
552 * Add MAC-Addr to MACVLAN device in source mode
553 * @arg link Link object
554 * @arg addr MAC-Addr
555 *
556 * addr is not release but cloned by this method.
557 *
558 * @return 0 on success or a negative error code.
559 */
560int rtnl_link_macvlan_add_macaddr(struct rtnl_link *link, struct nl_addr *addr)
561{
562 struct macvlan_info *mvi = link->l_info;
563 struct nl_addr **mvi_macaddr;
564 size_t newsize;
565
566 IS_MACVLAN_LINK_ASSERT(link);
567
568 if (nl_addr_get_family(addr) != AF_LLC)
569 return -NLE_INVAL;
570
571 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
572 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
573 return -NLE_INVAL;
574
575 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
576 return -NLE_INVAL;
577
578 if (mvi->mvi_maccount >= UINT32_MAX)
579 return -NLE_INVAL;
580
581 newsize = (mvi->mvi_maccount + 1) * sizeof(*(mvi->mvi_macaddr));
582 mvi_macaddr = realloc(mvi->mvi_macaddr, newsize);
583 if (!mvi_macaddr)
584 return -NLE_NOMEM;
585
586 mvi->mvi_macaddr = mvi_macaddr;
587 mvi->mvi_macaddr[mvi->mvi_maccount] = nl_addr_clone(addr);
588 mvi->mvi_maccount++;
589
590 mvi->mvi_mask |= MACVLAN_HAS_MACADDR;
591
592 return 0;
593}
594
595/**
596 * Remove MAC-Addr from MACVLAN device in source mode
597 * @arg link Link object
598 * @arg addr MAC-Addr
599 *
600 * addr is not release by this method.
601 *
602 * @return a negative error code on failure, or the number
603 * of deleted addresses on success.
604 */
605int rtnl_link_macvlan_del_macaddr(struct rtnl_link *link, struct nl_addr *addr)
606{
607 struct macvlan_info *mvi = link->l_info;
608 uint32_t found, i;
609
610 IS_MACVLAN_LINK_ASSERT(link);
611
612 if (nl_addr_get_family(addr) != AF_LLC)
613 return -NLE_INVAL;
614
615 if (!(mvi->mvi_mask & MACVLAN_HAS_MODE) ||
616 (mvi->mvi_mode != MACVLAN_MODE_SOURCE))
617 return -NLE_INVAL;
618
619 if (!(mvi->mvi_mask & MACVLAN_HAS_MACADDR))
620 return -NLE_INVAL;
621
622 nl_addr_get(addr);
623
624 found = 0; i = 0;
625 while (i + found < mvi->mvi_maccount) {
626 mvi->mvi_macaddr[i] = mvi->mvi_macaddr[i + found];
627 if (found > 0)
628 mvi->mvi_macaddr[i + found] = NULL;
629 if (nl_addr_cmp(addr, mvi->mvi_macaddr[i]) == 0) {
630 nl_addr_put(mvi->mvi_macaddr[i]);
631 mvi->mvi_macaddr[i] = NULL;
632 found++;
633 } else
634 i++;
635 }
636
637 nl_addr_put(addr);
638
639 mvi->mvi_maccount -= found;
640
641 return found > INT_MAX ? INT_MAX : (int) found;
642}
643
644/** @} */
645
646
647/**
648 * @name MACVTAP Object
649 * @{
650 */
651
652/**
653 * Allocate link object of type MACVTAP
654 *
655 * @return Allocated link object or NULL.
656 */
658{
659 struct rtnl_link *link;
660
661 if (!(link = rtnl_link_alloc()))
662 return NULL;
663
664 if (rtnl_link_set_type(link, "macvtap") < 0) {
665 rtnl_link_put(link);
666 return NULL;
667 }
668
669 return link;
670}
671
672/**
673 * Check if link is a MACVTAP link
674 * @arg link Link object
675 *
676 * @return True if link is a MACVTAP link, otherwise false is returned.
677 */
679{
680 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvtap");
681}
682
683/**
684 * Set MACVTAP MODE
685 * @arg link Link object
686 * @arg mode MACVTAP mode
687 *
688 * @return 0 on success or a negative error code
689 */
690int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode)
691{
692 struct macvlan_info *mvi = link->l_info;
693
694 IS_MACVTAP_LINK_ASSERT(link);
695
696 mvi->mvi_mode = mode;
697 mvi->mvi_mask |= MACVLAN_HAS_MODE;
698
699 return 0;
700}
701
702/**
703 * Get MACVTAP Mode
704 * @arg link Link object
705 *
706 * @return MACVTAP mode, 0 if not set or a negative error code.
707 */
709{
710 struct macvlan_info *mvi = link->l_info;
711
712 IS_MACVTAP_LINK_ASSERT(link);
713
714 if (mvi->mvi_mask & MACVLAN_HAS_MODE)
715 return mvi->mvi_mode;
716 else
717 return 0;
718}
719
720/**
721 * Set MACVTAP flags
722 * @arg link Link object
723 * @arg flags MACVTAP flags
724 *
725 * @return 0 on success or a negative error code.
726 */
727int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags)
728{
729 struct macvlan_info *mvi = link->l_info;
730
731 IS_MACVTAP_LINK_ASSERT(link);
732
733 mvi->mvi_flags |= flags;
734 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
735
736 return 0;
737}
738
739/**
740 * Unset MACVTAP flags
741 * @arg link Link object
742 * @arg flags MACVTAP flags
743 *
744 * Note: kernel currently only has a single flag and lacks flags_mask to
745 * indicate which flags shall be changed (it always all).
746 *
747 * @return 0 on success or a negative error code.
748 */
749int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags)
750{
751 struct macvlan_info *mvi = link->l_info;
752
753 IS_MACVTAP_LINK_ASSERT(link);
754
755 mvi->mvi_flags &= ~flags;
756 mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
757
758 return 0;
759}
760
761/**
762 * Get MACVTAP flags
763 * @arg link Link object
764 *
765 * @return MACVTAP flags, 0 if none set, or a negative error code.
766 */
768{
769 struct macvlan_info *mvi = link->l_info;
770
771 IS_MACVTAP_LINK_ASSERT(link);
772
773 return mvi->mvi_flags;
774}
775
776/** @} */
777
778
779static const struct trans_tbl macvlan_flags[] = {
780 __ADD(MACVLAN_FLAG_NOPROMISC, nopromisc),
781};
782
783static const struct trans_tbl macvlan_modes[] = {
784 __ADD(MACVLAN_MODE_PRIVATE, private),
785 __ADD(MACVLAN_MODE_VEPA, vepa),
786 __ADD(MACVLAN_MODE_BRIDGE, bridge),
787 __ADD(MACVLAN_MODE_PASSTHRU, passthru),
788 __ADD(MACVLAN_MODE_SOURCE, source),
789};
790
791static const struct trans_tbl macvlan_macmodes[] = {
792 __ADD(MACVLAN_MACADDR_ADD, "add"),
793 __ADD(MACVLAN_MACADDR_DEL, "del"),
794 __ADD(MACVLAN_MACADDR_SET, "set"),
795 __ADD(MACVLAN_MACADDR_FLUSH, "flush"),
796};
797
798/**
799 * @name Flag Translation
800 * @{
801 */
802
803char *rtnl_link_macvlan_flags2str(int flags, char *buf, size_t len)
804{
805 return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
806}
807
808int rtnl_link_macvlan_str2flags(const char *name)
809{
810 return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
811}
812
813char *rtnl_link_macvtap_flags2str(int flags, char *buf, size_t len)
814{
815 return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
816}
817
818int rtnl_link_macvtap_str2flags(const char *name)
819{
820 return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
821}
822
823/** @} */
824
825/**
826 * @name Mode Translation
827 * @{
828 */
829
830char *rtnl_link_macvlan_mode2str(int mode, char *buf, size_t len)
831{
832 return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
833}
834
835int rtnl_link_macvlan_str2mode(const char *name)
836{
837 return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
838}
839
840char *rtnl_link_macvlan_macmode2str(int mode, char *buf, size_t len)
841{
842 return __type2str(mode, buf, len, macvlan_macmodes,
843 ARRAY_SIZE(macvlan_macmodes));
844}
845
846int rtnl_link_macvlan_str2macmode(const char *name)
847{
848 return __str2type(name, macvlan_macmodes, ARRAY_SIZE(macvlan_macmodes));
849}
850
851char *rtnl_link_macvtap_mode2str(int mode, char *buf, size_t len)
852{
853 return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
854}
855
856int rtnl_link_macvtap_str2mode(const char *name)
857{
858 return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
859}
860
861/** @} */
862
863static void _nl_init macvlan_init(void)
864{
865 rtnl_link_register_info(&macvlan_info_ops);
866 rtnl_link_register_info(&macvtap_info_ops);
867}
868
869static void _nl_exit macvlan_exit(void)
870{
871 rtnl_link_unregister_info(&macvlan_info_ops);
872 rtnl_link_unregister_info(&macvtap_info_ops);
873}
874
875/** @} */
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:710
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
struct nlattr * nla_next(const struct nlattr *nla, int *remaining)
Return next attribute in a stream of attributes.
Definition attr.c:170
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:283
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:230
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:906
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:1033
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:969
@ 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:420
int rtnl_link_is_macvtap(struct rtnl_link *link)
Check if link is a MACVTAP link.
Definition macvlan.c:678
int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVTAP flags.
Definition macvlan.c:727
int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVLAN flags.
Definition macvlan.c:467
int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVLAN MODE.
Definition macvlan.c:345
uint32_t rtnl_link_macvtap_get_mode(struct rtnl_link *link)
Get MACVTAP Mode.
Definition macvlan.c:708
struct rtnl_link * rtnl_link_macvlan_alloc(void)
Allocate link object of type MACVLAN.
Definition macvlan.c:312
int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVTAP MODE.
Definition macvlan.c:690
uint16_t rtnl_link_macvtap_get_flags(struct rtnl_link *link)
Get MACVTAP flags.
Definition macvlan.c:767
uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link)
Get MACVLAN Mode.
Definition macvlan.c:374
int rtnl_link_macvlan_set_macmode(struct rtnl_link *link, uint32_t macmode)
Set MACVLAN MACMODE.
Definition macvlan.c:395
int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVTAP flags.
Definition macvlan.c:749
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:530
int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVLAN flags.
Definition macvlan.c:445
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:605
uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *link)
Get MACVLAN flags.
Definition macvlan.c:485
int rtnl_link_is_macvlan(struct rtnl_link *link)
Check if link is a MACVLAN link.
Definition macvlan.c:333
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:560
struct rtnl_link * rtnl_link_macvtap_alloc(void)
Allocate link object of type MACVTAP.
Definition macvlan.c:657
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:501
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1017
@ 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 type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65