libnl: /data/src/libnl3/lib/route/link/macvlan.c Source File

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