libnl  3.4.0
macvlan.c
1 /*
2  * lib/route/link/macvlan.c MACVLAN Link Info
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2013 Michael Braun <michael-dev@fami-braun.de>
10  */
11 
12 /**
13  * @ingroup link
14  * @defgroup macvlan MACVLAN/MACVTAP
15  * MAC-based Virtual LAN link module
16  *
17  * @details
18  * \b Link Type Name: "macvlan"
19  *
20  * @route_doc{link_macvlan, MACVLAN Documentation}
21  * @route_doc{link_macvtap, MACVTAP Documentation}
22  *
23  * @{
24  */
25 
26 #include <netlink-private/netlink.h>
27 #include <netlink/netlink.h>
28 #include <netlink/attr.h>
29 #include <netlink/utils.h>
30 #include <netlink/object.h>
31 #include <netlink/route/rtnl.h>
32 #include <netlink-private/route/link/api.h>
33 #include <netlink/route/link/macvlan.h>
34 #include <netlink/route/link/macvtap.h>
35 
36 #include <linux/if_link.h>
37 
38 /** @cond SKIP */
39 #define MACVLAN_HAS_MODE (1<<0)
40 #define MACVLAN_HAS_FLAGS (1<<1)
41 #define MACVLAN_HAS_MACADDR (1<<2)
42 
43 struct macvlan_info
44 {
45  uint32_t mvi_mode;
46  uint16_t mvi_flags; // there currently is only one flag and kernel has no flags_mask yet
47  uint32_t mvi_mask;
48  uint32_t mvi_maccount;
49  uint32_t mvi_macmode;
50  struct nl_addr **mvi_macaddr;
51 };
52 
53 /** @endcond */
54 
55 static struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX+1] = {
56  [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
57  [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
58  [IFLA_MACVLAN_MACADDR_MODE] = { .type = NLA_U32 },
59  [IFLA_MACVLAN_MACADDR] = { .type = NLA_UNSPEC },
60  [IFLA_MACVLAN_MACADDR_DATA] = { .type = NLA_NESTED },
61  [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
62 };
63 
64 static int macvlan_alloc(struct rtnl_link *link)
65 {
66  struct macvlan_info *mvi;
67  uint32_t i;
68 
69  if (link->l_info) {
70  mvi = link->l_info;
71  for (i = 0; i < mvi->mvi_maccount; i++)
72  nl_addr_put(mvi->mvi_macaddr[i]);
73  free(mvi->mvi_macaddr);
74  memset(mvi, 0, sizeof(*mvi));
75  } else {
76  if ((mvi = calloc(1, sizeof(*mvi))) == NULL)
77  return -NLE_NOMEM;
78 
79  link->l_info = mvi;
80  }
81  mvi->mvi_macmode = MACVLAN_MACADDR_SET;
82 
83  return 0;
84 }
85 
86 static int macvlan_parse(struct rtnl_link *link, struct nlattr *data,
87  struct nlattr *xstats)
88 {
89  struct nlattr *tb[IFLA_MACVLAN_MAX+1];
90  struct macvlan_info *mvi;
91  struct nlattr *nla;
92  int len;
93  int err;
94 
95  NL_DBG(3, "Parsing %s link info", link->l_info_ops->io_name);
96 
97  if ((err = nla_parse_nested(tb, IFLA_MACVLAN_MAX, data, macvlan_policy)) < 0)
98  goto errout;
99 
100  if ((err = macvlan_alloc(link)) < 0)
101  goto errout;
102 
103  mvi = link->l_info;
104 
105  if (tb[IFLA_MACVLAN_MODE]) {
106  mvi->mvi_mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]);
107  mvi->mvi_mask |= MACVLAN_HAS_MODE;
108  }
109 
110  if (tb[IFLA_MACVLAN_FLAGS]) {
111  mvi->mvi_mode = nla_get_u16(tb[IFLA_MACVLAN_FLAGS]);
112  mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
113  }
114 
115  if ( tb[IFLA_MACVLAN_MACADDR_COUNT]
116  && tb[IFLA_MACVLAN_MACADDR_DATA]) {
117  mvi->mvi_maccount = nla_get_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]);
118  if (mvi->mvi_maccount > 0) {
119  uint32_t i;
120 
121  nla = nla_data(tb[IFLA_MACVLAN_MACADDR_DATA]);
122  len = nla_len(tb[IFLA_MACVLAN_MACADDR_DATA]);
123 
124  mvi->mvi_macaddr = calloc(mvi->mvi_maccount,
125  sizeof(*(mvi->mvi_macaddr)));
126 
127  i = 0;
128  for (; nla_ok(nla, len); nla = nla_next(nla, &len)) {
129  if (i >= mvi->mvi_maccount)
130  break;
131  if (nla_type(nla) != IFLA_MACVLAN_MACADDR ||
132  nla_len(nla) < ETH_ALEN)
133  continue;
134  mvi->mvi_macaddr[i] = nl_addr_alloc_attr(nla, AF_LLC);
135  i++;
136  }
137  }
138  mvi->mvi_mask |= MACVLAN_HAS_MACADDR;
139  }
140 
141  err = 0;
142 errout:
143  return err;
144 }
145 
146 static void macvlan_free(struct rtnl_link *link)
147 {
148  struct macvlan_info *mvi;
149  uint32_t i;
150 
151  mvi = link->l_info;
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(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  for (i = 0; i < mvi->mvi_maccount; i++) {
181  nl_dump(p, "macvlan-sourcemac %s",
182  nl_addr2str(mvi->mvi_macaddr[i], buf,
183  sizeof(buf)));
184  }
185  }
186 }
187 
188 static int macvlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
189 {
190  struct macvlan_info *vdst, *vsrc = src->l_info;
191  int err;
192  uint32_t i;
193 
194  dst->l_info = NULL;
195  if ((err = rtnl_link_set_type(dst, "macvlan")) < 0)
196  return err;
197  vdst = dst->l_info;
198 
199  if (!vdst || !vsrc)
200  return -NLE_NOMEM;
201 
202  memcpy(vdst, vsrc, sizeof(struct macvlan_info));
203 
204  if ( vsrc->mvi_mask & MACVLAN_HAS_MACADDR
205  && vsrc->mvi_maccount > 0) {
206  vdst->mvi_macaddr = calloc(vdst->mvi_maccount,
207  sizeof(*(vdst->mvi_macaddr)));
208  for (i = 0; i < vdst->mvi_maccount; i++)
209  vdst->mvi_macaddr[i] = nl_addr_clone(vsrc->mvi_macaddr[i]);
210  } else
211  vdst->mvi_macaddr = NULL;
212 
213  return 0;
214 }
215 
216 static int macvlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
217 {
218  struct macvlan_info *mvi = link->l_info;
219  struct nlattr *data, *datamac = NULL;
220  int i, ret;
221 
222  if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
223  return -NLE_MSGSIZE;
224 
225  ret = -NLE_NOMEM;
226 
227  if (mvi->mvi_mask & MACVLAN_HAS_MODE)
228  NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, mvi->mvi_mode);
229 
230  if (mvi->mvi_mask & MACVLAN_HAS_FLAGS)
231  NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, mvi->mvi_flags);
232 
233  if (mvi->mvi_mask & MACVLAN_HAS_MACADDR) {
234  NLA_PUT_U32(msg, IFLA_MACVLAN_MACADDR_MODE, mvi->mvi_macmode);
235  datamac = nla_nest_start(msg, IFLA_MACVLAN_MACADDR_DATA);
236  if (!datamac)
237  goto nla_put_failure;
238 
239  for (i = 0; i < mvi->mvi_maccount; i++) {
240  NLA_PUT_ADDR(msg, IFLA_MACVLAN_MACADDR,
241  mvi->mvi_macaddr[i]);
242  }
243  }
244 
245  ret = 0;
246 
247 nla_put_failure:
248  if (datamac)
249  nla_nest_end(msg, datamac);
250 
251  nla_nest_end(msg, data);
252 
253  return ret;
254 }
255 
256 static struct rtnl_link_info_ops macvlan_info_ops = {
257  .io_name = "macvlan",
258  .io_alloc = macvlan_alloc,
259  .io_parse = macvlan_parse,
260  .io_dump = {
261  [NL_DUMP_LINE] = macvlan_dump,
262  [NL_DUMP_DETAILS] = macvlan_dump,
263  },
264  .io_clone = macvlan_clone,
265  .io_put_attrs = macvlan_put_attrs,
266  .io_free = macvlan_free,
267 };
268 
269 static struct rtnl_link_info_ops macvtap_info_ops = {
270  .io_name = "macvtap",
271  .io_alloc = macvlan_alloc,
272  .io_parse = macvlan_parse,
273  .io_dump = {
274  [NL_DUMP_LINE] = macvlan_dump,
275  [NL_DUMP_DETAILS] = macvlan_dump,
276  },
277  .io_clone = macvlan_clone,
278  .io_put_attrs = macvlan_put_attrs,
279  .io_free = macvlan_free,
280 };
281 
282 /** @cond SKIP */
283 #define IS_MACVLAN_LINK_ASSERT(link) \
284  if ((link)->l_info_ops != &macvlan_info_ops) { \
285  APPBUG("Link is not a macvlan link. set type \"macvlan\" first."); \
286  return -NLE_OPNOTSUPP; \
287  }
288 
289 #define IS_MACVTAP_LINK_ASSERT(link) \
290  if ((link)->l_info_ops != &macvtap_info_ops) { \
291  APPBUG("Link is not a macvtap link. set type \"macvtap\" first."); \
292  return -NLE_OPNOTSUPP; \
293  }
294 /** @endcond */
295 
296 /**
297  * @name MACVLAN Object
298  * @{
299  */
300 
301 /**
302  * Allocate link object of type MACVLAN
303  *
304  * @return Allocated link object or NULL.
305  */
307 {
308  struct rtnl_link *link;
309  int err;
310 
311  if (!(link = rtnl_link_alloc()))
312  return NULL;
313 
314  if ((err = 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  */
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  */
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  */
653 {
654  struct rtnl_link *link;
655  int err;
656 
657  if (!(link = rtnl_link_alloc()))
658  return NULL;
659 
660  if ((err = rtnl_link_set_type(link, "macvtap")) < 0) {
661  rtnl_link_put(link);
662  return NULL;
663  }
664 
665  return link;
666 }
667 
668 /**
669  * Check if link is a MACVTAP link
670  * @arg link Link object
671  *
672  * @return True if link is a MACVTAP link, otherwise false is returned.
673  */
675 {
676  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "macvtap");
677 }
678 
679 /**
680  * Set MACVTAP MODE
681  * @arg link Link object
682  * @arg mode MACVTAP mode
683  *
684  * @return 0 on success or a negative error code
685  */
686 int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode)
687 {
688  struct macvlan_info *mvi = link->l_info;
689 
690  IS_MACVTAP_LINK_ASSERT(link);
691 
692  mvi->mvi_mode = mode;
693  mvi->mvi_mask |= MACVLAN_HAS_MODE;
694 
695  return 0;
696 }
697 
698 /**
699  * Get MACVTAP Mode
700  * @arg link Link object
701  *
702  * @return MACVTAP mode, 0 if not set or a negative error code.
703  */
704 uint32_t rtnl_link_macvtap_get_mode(struct rtnl_link *link)
705 {
706  struct macvlan_info *mvi = link->l_info;
707 
708  IS_MACVTAP_LINK_ASSERT(link);
709 
710  if (mvi->mvi_mask & MACVLAN_HAS_MODE)
711  return mvi->mvi_mode;
712  else
713  return 0;
714 }
715 
716 /**
717  * Set MACVTAP flags
718  * @arg link Link object
719  * @arg flags MACVTAP flags
720  *
721  * @return 0 on success or a negative error code.
722  */
723 int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags)
724 {
725  struct macvlan_info *mvi = link->l_info;
726 
727  IS_MACVTAP_LINK_ASSERT(link);
728 
729  mvi->mvi_flags |= flags;
730  mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
731 
732  return 0;
733 }
734 
735 /**
736  * Unset MACVTAP flags
737  * @arg link Link object
738  * @arg flags MACVTAP flags
739  *
740  * Note: kernel currently only has a single flag and lacks flags_mask to
741  * indicate which flags shall be changed (it always all).
742  *
743  * @return 0 on success or a negative error code.
744  */
745 int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags)
746 {
747  struct macvlan_info *mvi = link->l_info;
748 
749  IS_MACVTAP_LINK_ASSERT(link);
750 
751  mvi->mvi_flags &= ~flags;
752  mvi->mvi_mask |= MACVLAN_HAS_FLAGS;
753 
754  return 0;
755 }
756 
757 /**
758  * Get MACVTAP flags
759  * @arg link Link object
760  *
761  * @return MACVTAP flags, 0 if none set, or a negative error code.
762  */
764 {
765  struct macvlan_info *mvi = link->l_info;
766 
767  IS_MACVTAP_LINK_ASSERT(link);
768 
769  return mvi->mvi_flags;
770 }
771 
772 /** @} */
773 
774 
775 static const struct trans_tbl macvlan_flags[] = {
776  __ADD(MACVLAN_FLAG_NOPROMISC, nopromisc),
777 };
778 
779 static const struct trans_tbl macvlan_modes[] = {
780  __ADD(MACVLAN_MODE_PRIVATE, private),
781  __ADD(MACVLAN_MODE_VEPA, vepa),
782  __ADD(MACVLAN_MODE_BRIDGE, bridge),
783  __ADD(MACVLAN_MODE_PASSTHRU, passthru),
784  __ADD(MACVLAN_MODE_SOURCE, source),
785 };
786 
787 static const struct trans_tbl macvlan_macmodes[] = {
788  __ADD(MACVLAN_MACADDR_ADD, "add"),
789  __ADD(MACVLAN_MACADDR_DEL, "del"),
790  __ADD(MACVLAN_MACADDR_SET, "set"),
791  __ADD(MACVLAN_MACADDR_FLUSH, "flush"),
792 };
793 
794 /**
795  * @name Flag Translation
796  * @{
797  */
798 
799 char *rtnl_link_macvlan_flags2str(int flags, char *buf, size_t len)
800 {
801  return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
802 }
803 
804 int rtnl_link_macvlan_str2flags(const char *name)
805 {
806  return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
807 }
808 
809 char *rtnl_link_macvtap_flags2str(int flags, char *buf, size_t len)
810 {
811  return __flags2str(flags, buf, len, macvlan_flags, ARRAY_SIZE(macvlan_flags));
812 }
813 
814 int rtnl_link_macvtap_str2flags(const char *name)
815 {
816  return __str2flags(name, macvlan_flags, ARRAY_SIZE(macvlan_flags));
817 }
818 
819 /** @} */
820 
821 /**
822  * @name Mode Translation
823  * @{
824  */
825 
826 char *rtnl_link_macvlan_mode2str(int mode, char *buf, size_t len)
827 {
828  return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
829 }
830 
831 int rtnl_link_macvlan_str2mode(const char *name)
832 {
833  return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
834 }
835 
836 char *rtnl_link_macvlan_macmode2str(int mode, char *buf, size_t len)
837 {
838  return __type2str(mode, buf, len, macvlan_macmodes,
839  ARRAY_SIZE(macvlan_macmodes));
840 }
841 
842 int rtnl_link_macvlan_str2macmode(const char *name)
843 {
844  return __str2type(name, macvlan_macmodes, ARRAY_SIZE(macvlan_macmodes));
845 }
846 
847 char *rtnl_link_macvtap_mode2str(int mode, char *buf, size_t len)
848 {
849  return __type2str(mode, buf, len, macvlan_modes, ARRAY_SIZE(macvlan_modes));
850 }
851 
852 int rtnl_link_macvtap_str2mode(const char *name)
853 {
854  return __str2type(name, macvlan_modes, ARRAY_SIZE(macvlan_modes));
855 }
856 
857 /** @} */
858 
859 static void __init macvlan_init(void)
860 {
861  rtnl_link_register_info(&macvlan_info_ops);
862  rtnl_link_register_info(&macvtap_info_ops);
863 }
864 
865 static void __exit macvlan_exit(void)
866 {
867  rtnl_link_unregister_info(&macvlan_info_ops);
868  rtnl_link_unregister_info(&macvtap_info_ops);
869 }
870 
871 /** @} */
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:493
Dump object briefly on one line.
Definition: types.h:22
int rtnl_link_macvlan_get_macmode(struct rtnl_link *link, uint32_t *out_macmode)
Get MACVLAN MACMODE.
Definition: macvlan.c:415
int nla_ok(const struct nlattr *nla, int remaining)
Check if the attribute header and payload can be accessed safely.
Definition: attr.c:148
int rtnl_link_is_macvlan(struct rtnl_link *link)
Check if link is a MACVLAN link.
Definition: macvlan.c:328
int rtnl_link_macvlan_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVLAN flags.
Definition: macvlan.c:462
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition: addr.c:585
uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *link)
Get MACVLAN flags.
Definition: macvlan.c:480
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:288
Attribute validation policy.
Definition: attr.h:69
Unspecified type, binary data chunk.
Definition: attr.h:40
uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *link)
Get MACVLAN Mode.
Definition: macvlan.c:369
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
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:706
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
int rtnl_link_macvlan_set_macmode(struct rtnl_link *link, uint32_t macmode)
Set MACVLAN MACMODE.
Definition: macvlan.c:390
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:523
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:262
int rtnl_link_macvtap_unset_flags(struct rtnl_link *link, uint16_t flags)
Unset MACVTAP flags.
Definition: macvlan.c:745
Dump all attributes but no statistics.
Definition: types.h:23
int rtnl_link_is_macvtap(struct rtnl_link *link)
Check if link is a MACVTAP link.
Definition: macvlan.c:674
struct rtnl_link * rtnl_link_macvtap_alloc(void)
Allocate link object of type MACVTAP.
Definition: macvlan.c:652
int rtnl_link_macvlan_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVLAN flags.
Definition: macvlan.c:440
int rtnl_link_macvlan_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVLAN MODE.
Definition: macvlan.c:340
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:924
struct nlattr * nla_next(const struct nlattr *nla, int *remaining)
Return next attribute in a stream of attributes.
Definition: attr.c:171
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:999
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition: attr.c:109
16 bit integer
Definition: attr.h:42
uint16_t rtnl_link_macvtap_get_flags(struct rtnl_link *link)
Get MACVTAP flags.
Definition: macvlan.c:763
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:120
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:235
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:131
Nested attributes.
Definition: attr.h:48
int rtnl_link_macvtap_set_flags(struct rtnl_link *link, uint16_t flags)
Set MACVTAP flags.
Definition: macvlan.c:723
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:539
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
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:656
32 bit integer
Definition: attr.h:43
Dumping parameters.
Definition: types.h:33
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:217
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:961
uint32_t rtnl_link_macvtap_get_mode(struct rtnl_link *link)
Get MACVTAP Mode.
Definition: macvlan.c:704
int rtnl_link_macvtap_set_mode(struct rtnl_link *link, uint32_t mode)
Set MACVTAP MODE.
Definition: macvlan.c:686
struct rtnl_link * rtnl_link_macvlan_alloc(void)
Allocate link object of type MACVLAN.
Definition: macvlan.c:306
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:902
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:991
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
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition: addr.c:885