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