libnl  3.2.27
vxlan.c
1 /*
2  * lib/route/link/vxlan.c VXLAN 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 Yasunobu Chiba <yasu@dsl.gr.jp>
10  */
11 
12 /**
13  * @ingroup link
14  * @defgroup vxlan VXLAN
15  * Virtual eXtensible Local Area Network link module
16  *
17  * @details
18  * \b Link Type Name: "vxlan"
19  *
20  * @route_doc{link_vxlan, VXLAN Documentation}
21  *
22  * @{
23  */
24 
25 #include <netlink-private/netlink.h>
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-private/route/link/api.h>
32 #include <netlink/route/link/vxlan.h>
33 
34 #include <linux/if_link.h>
35 
36 /** @cond SKIP */
37 #define VXLAN_HAS_ID (1<<0)
38 #define VXLAN_HAS_GROUP (1<<1)
39 #define VXLAN_HAS_LINK (1<<2)
40 #define VXLAN_HAS_LOCAL (1<<3)
41 #define VXLAN_HAS_TTL (1<<4)
42 #define VXLAN_HAS_TOS (1<<5)
43 #define VXLAN_HAS_LEARNING (1<<6)
44 #define VXLAN_HAS_AGEING (1<<7)
45 #define VXLAN_HAS_LIMIT (1<<8)
46 #define VXLAN_HAS_PORT_RANGE (1<<9)
47 #define VXLAN_HAS_PROXY (1<<10)
48 #define VXLAN_HAS_RSC (1<<11)
49 #define VXLAN_HAS_L2MISS (1<<12)
50 #define VXLAN_HAS_L3MISS (1<<13)
51 
52 struct vxlan_info
53 {
54  uint32_t vxi_id;
55  uint32_t vxi_group;
56  uint32_t vxi_link;
57  uint32_t vxi_local;
58  uint8_t vxi_ttl;
59  uint8_t vxi_tos;
60  uint8_t vxi_learning;
61  uint32_t vxi_ageing;
62  uint32_t vxi_limit;
63  struct ifla_vxlan_port_range vxi_port_range;
64  uint8_t vxi_proxy;
65  uint8_t vxi_rsc;
66  uint8_t vxi_l2miss;
67  uint8_t vxi_l3miss;
68  uint32_t vxi_mask;
69 };
70 
71 /** @endcond */
72 
73 static struct nla_policy vxlan_policy[IFLA_VXLAN_MAX+1] = {
74  [IFLA_VXLAN_ID] = { .type = NLA_U32 },
75  [IFLA_VXLAN_GROUP] = { .minlen = sizeof(uint32_t) },
76  [IFLA_VXLAN_LINK] = { .type = NLA_U32 },
77  [IFLA_VXLAN_LOCAL] = { .minlen = sizeof(uint32_t) },
78  [IFLA_VXLAN_TTL] = { .type = NLA_U8 },
79  [IFLA_VXLAN_TOS] = { .type = NLA_U8 },
80  [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 },
81  [IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
82  [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
83  [IFLA_VXLAN_PORT_RANGE] = { .minlen = sizeof(struct ifla_vxlan_port_range) },
84  [IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
85  [IFLA_VXLAN_RSC] = { .type = NLA_U8 },
86  [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
87  [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
88 };
89 
90 static int vxlan_alloc(struct rtnl_link *link)
91 {
92  struct vxlan_info *vxi;
93 
94  if (link->l_info)
95  memset(link->l_info, 0, sizeof(*vxi));
96  else {
97  if ((vxi = calloc(1, sizeof(*vxi))) == NULL)
98  return -NLE_NOMEM;
99 
100  link->l_info = vxi;
101  }
102 
103  return 0;
104 }
105 
106 static int vxlan_parse(struct rtnl_link *link, struct nlattr *data,
107  struct nlattr *xstats)
108 {
109  struct nlattr *tb[IFLA_VXLAN_MAX+1];
110  struct vxlan_info *vxi;
111  int err;
112 
113  NL_DBG(3, "Parsing VXLAN link info\n");
114 
115  if ((err = nla_parse_nested(tb, IFLA_VXLAN_MAX, data, vxlan_policy)) < 0)
116  goto errout;
117 
118  if ((err = vxlan_alloc(link)) < 0)
119  goto errout;
120 
121  vxi = link->l_info;
122 
123  if (tb[IFLA_VXLAN_ID]) {
124  vxi->vxi_id = nla_get_u32(tb[IFLA_VXLAN_ID]);
125  vxi->vxi_mask |= VXLAN_HAS_ID;
126  }
127 
128  if (tb[IFLA_VXLAN_GROUP]) {
129  nla_memcpy(&vxi->vxi_group, tb[IFLA_VXLAN_GROUP],
130  sizeof(vxi->vxi_group));
131  vxi->vxi_mask |= VXLAN_HAS_GROUP;
132  }
133 
134  if (tb[IFLA_VXLAN_LINK]) {
135  vxi->vxi_link = nla_get_u32(tb[IFLA_VXLAN_LINK]);
136  vxi->vxi_mask |= VXLAN_HAS_LINK;
137  }
138 
139  if (tb[IFLA_VXLAN_LOCAL]) {
140  nla_memcpy(&vxi->vxi_local, tb[IFLA_VXLAN_LOCAL],
141  sizeof(vxi->vxi_local));
142  vxi->vxi_mask |= VXLAN_HAS_LOCAL;
143  }
144 
145  if (tb[IFLA_VXLAN_TTL]) {
146  vxi->vxi_ttl = nla_get_u8(tb[IFLA_VXLAN_TTL]);
147  vxi->vxi_mask |= VXLAN_HAS_TTL;
148  }
149 
150  if (tb[IFLA_VXLAN_TOS]) {
151  vxi->vxi_tos = nla_get_u8(tb[IFLA_VXLAN_TOS]);
152  vxi->vxi_mask |= VXLAN_HAS_TOS;
153  }
154 
155  if (tb[IFLA_VXLAN_LEARNING]) {
156  vxi->vxi_learning = nla_get_u8(tb[IFLA_VXLAN_LEARNING]);
157  vxi->vxi_mask |= VXLAN_HAS_LEARNING;
158  }
159 
160  if (tb[IFLA_VXLAN_AGEING]) {
161  vxi->vxi_ageing = nla_get_u32(tb[IFLA_VXLAN_AGEING]);
162  vxi->vxi_mask |= VXLAN_HAS_AGEING;
163  }
164 
165  if (tb[IFLA_VXLAN_LIMIT]) {
166  vxi->vxi_limit = nla_get_u32(tb[IFLA_VXLAN_LIMIT]);
167  vxi->vxi_mask |= VXLAN_HAS_LIMIT;
168  }
169 
170  if (tb[IFLA_VXLAN_PORT_RANGE]) {
171  nla_memcpy(&vxi->vxi_port_range, tb[IFLA_VXLAN_PORT_RANGE],
172  sizeof(vxi->vxi_port_range));
173  vxi->vxi_mask |= VXLAN_HAS_PORT_RANGE;
174  }
175 
176  if (tb[IFLA_VXLAN_PROXY]) {
177  vxi->vxi_proxy = nla_get_u8(tb[IFLA_VXLAN_PROXY]);
178  vxi->vxi_mask |= VXLAN_HAS_PROXY;
179  }
180 
181  if (tb[IFLA_VXLAN_RSC]) {
182  vxi->vxi_rsc = nla_get_u8(tb[IFLA_VXLAN_RSC]);
183  vxi->vxi_mask |= VXLAN_HAS_RSC;
184  }
185 
186  if (tb[IFLA_VXLAN_L2MISS]) {
187  vxi->vxi_l2miss = nla_get_u8(tb[IFLA_VXLAN_L2MISS]);
188  vxi->vxi_mask |= VXLAN_HAS_L2MISS;
189  }
190 
191  if (tb[IFLA_VXLAN_L3MISS]) {
192  vxi->vxi_l3miss = nla_get_u8(tb[IFLA_VXLAN_L3MISS]);
193  vxi->vxi_mask |= VXLAN_HAS_L3MISS;
194  }
195 
196  err = 0;
197 
198 errout:
199  return err;
200 }
201 
202 static void vxlan_free(struct rtnl_link *link)
203 {
204  struct vxlan_info *vxi = link->l_info;
205 
206  free(vxi);
207  link->l_info = NULL;
208 }
209 
210 static void vxlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
211 {
212  struct vxlan_info *vxi = link->l_info;
213 
214  nl_dump(p, "vxlan-id %u", vxi->vxi_id);
215 }
216 
217 static void vxlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
218 {
219  struct vxlan_info *vxi = link->l_info;
220  char *name, addr[INET_ADDRSTRLEN];
221 
222  nl_dump_line(p, " vxlan-id %u\n", vxi->vxi_id);
223 
224  if (vxi->vxi_mask & VXLAN_HAS_GROUP) {
225  nl_dump(p, " group ");
226  if(inet_ntop(AF_INET, &vxi->vxi_group, addr, sizeof(addr)))
227  nl_dump_line(p, "%s\n", addr);
228  else
229  nl_dump_line(p, "%#x\n", ntohs(vxi->vxi_group));
230  }
231 
232  if (vxi->vxi_mask & VXLAN_HAS_LINK) {
233  nl_dump(p, " link ");
234  name = rtnl_link_get_name(link);
235  if (name)
236  nl_dump_line(p, "%s\n", name);
237  else
238  nl_dump_line(p, "%u\n", vxi->vxi_link);
239  }
240 
241  if (vxi->vxi_mask & VXLAN_HAS_LOCAL) {
242  nl_dump(p, " local ");
243  if(inet_ntop(AF_INET, &vxi->vxi_local, addr, sizeof(addr)))
244  nl_dump_line(p, "%s\n", addr);
245  else
246  nl_dump_line(p, "%#x\n", ntohs(vxi->vxi_local));
247  }
248 
249  if (vxi->vxi_mask & VXLAN_HAS_TTL) {
250  nl_dump(p, " ttl ");
251  if(vxi->vxi_ttl)
252  nl_dump_line(p, "%u\n", vxi->vxi_ttl);
253  else
254  nl_dump_line(p, "inherit\n");
255  }
256 
257  if (vxi->vxi_mask & VXLAN_HAS_TOS) {
258  nl_dump(p, " tos ");
259  if (vxi->vxi_tos == 1)
260  nl_dump_line(p, "inherit\n", vxi->vxi_tos);
261  else
262  nl_dump_line(p, "%#x\n", vxi->vxi_tos);
263  }
264 
265  if (vxi->vxi_mask & VXLAN_HAS_LEARNING) {
266  nl_dump(p, " learning ");
267  if (vxi->vxi_learning)
268  nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_learning);
269  else
270  nl_dump_line(p, "disabled\n");
271  }
272 
273  if (vxi->vxi_mask & VXLAN_HAS_AGEING) {
274  nl_dump(p, " ageing ");
275  if (vxi->vxi_ageing)
276  nl_dump_line(p, "%u seconds\n", vxi->vxi_ageing);
277  else
278  nl_dump_line(p, "disabled\n");
279  }
280 
281  if (vxi->vxi_mask & VXLAN_HAS_LIMIT) {
282  nl_dump(p, " limit ");
283  if (vxi->vxi_limit)
284  nl_dump_line(p, "%u\n", vxi->vxi_limit);
285  else
286  nl_dump_line(p, "unlimited\n");
287  }
288 
289  if (vxi->vxi_mask & VXLAN_HAS_PORT_RANGE)
290  nl_dump_line(p, " port range %u - %u\n",
291  ntohs(vxi->vxi_port_range.low),
292  ntohs(vxi->vxi_port_range.high));
293 
294  if (vxi->vxi_mask & VXLAN_HAS_PROXY) {
295  nl_dump(p, " proxy ");
296  if (vxi->vxi_proxy)
297  nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_proxy);
298  else
299  nl_dump_line(p, "disabled\n");
300  }
301 
302  if (vxi->vxi_mask & VXLAN_HAS_RSC) {
303  nl_dump(p, " rsc ");
304  if (vxi->vxi_rsc)
305  nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_rsc);
306  else
307  nl_dump_line(p, "disabled\n");
308  }
309 
310  if (vxi->vxi_mask & VXLAN_HAS_L2MISS) {
311  nl_dump(p, " l2miss ");
312  if (vxi->vxi_l2miss)
313  nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_l2miss);
314  else
315  nl_dump_line(p, "disabled\n");
316  }
317 
318  if (vxi->vxi_mask & VXLAN_HAS_L3MISS) {
319  nl_dump(p, " l3miss ");
320  if (vxi->vxi_l3miss)
321  nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_l3miss);
322  else
323  nl_dump_line(p, "disabled\n");
324  }
325 }
326 
327 static int vxlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
328 {
329  struct vxlan_info *vdst, *vsrc = src->l_info;
330  int err;
331 
332  dst->l_info = NULL;
333  if ((err = rtnl_link_set_type(dst, "vxlan")) < 0)
334  return err;
335  vdst = dst->l_info;
336 
337  if (!vdst || !vsrc)
338  return -NLE_NOMEM;
339 
340  memcpy(vdst, vsrc, sizeof(struct vxlan_info));
341 
342  return 0;
343 }
344 
345 static int vxlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
346 {
347  struct vxlan_info *vxi = link->l_info;
348  struct nlattr *data;
349 
350  if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
351  return -NLE_MSGSIZE;
352 
353  if (vxi->vxi_mask & VXLAN_HAS_ID)
354  NLA_PUT_U32(msg, IFLA_VXLAN_ID, vxi->vxi_id);
355 
356  if (vxi->vxi_mask & VXLAN_HAS_GROUP)
357  NLA_PUT(msg, IFLA_VXLAN_GROUP, sizeof(vxi->vxi_group), &vxi->vxi_group);
358 
359  if (vxi->vxi_mask & VXLAN_HAS_LINK)
360  NLA_PUT_U32(msg, IFLA_VXLAN_LINK, vxi->vxi_link);
361 
362  if (vxi->vxi_mask & VXLAN_HAS_LOCAL)
363  NLA_PUT(msg, IFLA_VXLAN_LOCAL, sizeof(vxi->vxi_local), &vxi->vxi_local);
364 
365  if (vxi->vxi_mask & VXLAN_HAS_TTL)
366  NLA_PUT_U8(msg, IFLA_VXLAN_TTL, vxi->vxi_ttl);
367 
368  if (vxi->vxi_mask & VXLAN_HAS_TOS)
369  NLA_PUT_U8(msg, IFLA_VXLAN_TOS, vxi->vxi_tos);
370 
371  if (vxi->vxi_mask & VXLAN_HAS_LEARNING)
372  NLA_PUT_U8(msg, IFLA_VXLAN_LEARNING, vxi->vxi_learning);
373 
374  if (vxi->vxi_mask & VXLAN_HAS_AGEING)
375  NLA_PUT_U32(msg, IFLA_VXLAN_AGEING, vxi->vxi_ageing);
376 
377  if (vxi->vxi_mask & VXLAN_HAS_LIMIT)
378  NLA_PUT_U32(msg, IFLA_VXLAN_LIMIT, vxi->vxi_limit);
379 
380  if (vxi->vxi_mask & VXLAN_HAS_PORT_RANGE)
381  NLA_PUT(msg, IFLA_VXLAN_PORT_RANGE, sizeof(vxi->vxi_port_range),
382  &vxi->vxi_port_range);
383 
384  if (vxi->vxi_mask & VXLAN_HAS_PROXY)
385  NLA_PUT_U8(msg, IFLA_VXLAN_PROXY, vxi->vxi_proxy);
386 
387  if (vxi->vxi_mask & VXLAN_HAS_RSC)
388  NLA_PUT_U8(msg, IFLA_VXLAN_RSC, vxi->vxi_rsc);
389 
390  if (vxi->vxi_mask & VXLAN_HAS_L2MISS)
391  NLA_PUT_U8(msg, IFLA_VXLAN_L2MISS, vxi->vxi_l2miss);
392 
393  if (vxi->vxi_mask & VXLAN_HAS_L3MISS)
394  NLA_PUT_U8(msg, IFLA_VXLAN_L3MISS, vxi->vxi_l3miss);
395 
396  nla_nest_end(msg, data);
397 
398 nla_put_failure:
399 
400  return 0;
401 }
402 
403 static struct rtnl_link_info_ops vxlan_info_ops = {
404  .io_name = "vxlan",
405  .io_alloc = vxlan_alloc,
406  .io_parse = vxlan_parse,
407  .io_dump = {
408  [NL_DUMP_LINE] = vxlan_dump_line,
409  [NL_DUMP_DETAILS] = vxlan_dump_details,
410  },
411  .io_clone = vxlan_clone,
412  .io_put_attrs = vxlan_put_attrs,
413  .io_free = vxlan_free,
414 };
415 
416 /** @cond SKIP */
417 #define IS_VXLAN_LINK_ASSERT(link) \
418  if ((link)->l_info_ops != &vxlan_info_ops) { \
419  APPBUG("Link is not a vxlan link. set type \"vxlan\" first."); \
420  return -NLE_OPNOTSUPP; \
421  }
422 /** @endcond */
423 
424 /**
425  * @name VXLAN Object
426  * @{
427  */
428 
429 /**
430  * Allocate link object of type VXLAN
431  *
432  * @return Allocated link object or NULL.
433  */
435 {
436  struct rtnl_link *link;
437  int err;
438 
439  if (!(link = rtnl_link_alloc()))
440  return NULL;
441 
442  if ((err = rtnl_link_set_type(link, "vxlan")) < 0) {
443  rtnl_link_put(link);
444  return NULL;
445  }
446 
447  return link;
448 }
449 
450 /**
451  * Check if link is a VXLAN link
452  * @arg link Link object
453  *
454  * @return True if link is a VXLAN link, otherwise false is returned.
455  */
456 int rtnl_link_is_vxlan(struct rtnl_link *link)
457 {
458  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vxlan");
459 }
460 
461 /**
462  * Set VXLAN Network Identifier
463  * @arg link Link object
464  * @arg id VXLAN network identifier (or VXLAN segment identifier)
465  *
466  * @return 0 on success or a negative error code
467  */
468 int rtnl_link_vxlan_set_id(struct rtnl_link *link, uint32_t id)
469 {
470  struct vxlan_info *vxi = link->l_info;
471 
472  IS_VXLAN_LINK_ASSERT(link);
473 
474  if (id > VXLAN_ID_MAX)
475  return -NLE_INVAL;
476 
477  vxi->vxi_id = id;
478  vxi->vxi_mask |= VXLAN_HAS_ID;
479 
480  return 0;
481 }
482 
483 /**
484  * Get VXLAN Network Identifier
485  * @arg link Link object
486  * @arg id Pointer to store network identifier
487  *
488  * @return 0 on success or a negative error code
489  */
490 int rtnl_link_vxlan_get_id(struct rtnl_link *link, uint32_t *id)
491 {
492  struct vxlan_info *vxi = link->l_info;
493 
494  IS_VXLAN_LINK_ASSERT(link);
495 
496  if(!id)
497  return -NLE_INVAL;
498 
499  if (vxi->vxi_mask & VXLAN_HAS_ID)
500  *id = vxi->vxi_id;
501  else
502  return -NLE_AGAIN;
503 
504  return 0;
505 }
506 
507 /**
508  * Set VXLAN multicast IP address
509  * @arg link Link object
510  * @arg addr Multicast IP address to join
511  *
512  * @return 0 on success or a negative error code
513  */
514 int rtnl_link_vxlan_set_group(struct rtnl_link *link, struct nl_addr *addr)
515 {
516  struct vxlan_info *vxi = link->l_info;
517 
518  IS_VXLAN_LINK_ASSERT(link);
519 
520  if ((nl_addr_get_family(addr) != AF_INET) ||
521  (nl_addr_get_len(addr) != sizeof(vxi->vxi_group)))
522  return -NLE_INVAL;
523 
524  memcpy(&vxi->vxi_group, nl_addr_get_binary_addr(addr),
525  sizeof(vxi->vxi_group));
526  vxi->vxi_mask |= VXLAN_HAS_GROUP;
527 
528  return 0;
529 }
530 
531 /**
532  * Get VXLAN multicast IP address
533  * @arg link Link object
534  * @arg addr Pointer to store multicast IP address
535  *
536  * @return 0 on success or a negative error code
537  */
538 int rtnl_link_vxlan_get_group(struct rtnl_link *link, struct nl_addr **addr)
539 {
540  struct vxlan_info *vxi = link->l_info;
541 
542  IS_VXLAN_LINK_ASSERT(link);
543 
544  if (!addr)
545  return -NLE_INVAL;
546 
547  if (!(vxi->vxi_mask & VXLAN_HAS_GROUP))
548  return -NLE_AGAIN;
549 
550  *addr = nl_addr_build(AF_INET, &vxi->vxi_group, sizeof(vxi->vxi_group));
551 
552  return 0;
553 }
554 
555 /**
556  * Set physical device to use for VXLAN
557  * @arg link Link object
558  * @arg index Interface index
559  *
560  * @return 0 on success or a negative error code
561  */
562 int rtnl_link_vxlan_set_link(struct rtnl_link *link, uint32_t index)
563 {
564  struct vxlan_info *vxi = link->l_info;
565 
566  IS_VXLAN_LINK_ASSERT(link);
567 
568  vxi->vxi_link = index;
569  vxi->vxi_mask |= VXLAN_HAS_LINK;
570 
571  return 0;
572 }
573 
574 /**
575  * Get physical device to use for VXLAN
576  * @arg link Link object
577  * @arg index Pointer to store interface index
578  *
579  * @return 0 on success or a negative error code
580  */
581 int rtnl_link_vxlan_get_link(struct rtnl_link *link, uint32_t *index)
582 {
583  struct vxlan_info *vxi = link->l_info;
584 
585  IS_VXLAN_LINK_ASSERT(link);
586 
587  if (!index)
588  return -NLE_INVAL;
589 
590  if (!(vxi->vxi_mask & VXLAN_HAS_LINK))
591  return -NLE_AGAIN;
592 
593  *index = vxi->vxi_link;
594 
595  return 0;
596 }
597 
598 /**
599  * Set source address to use for VXLAN
600  * @arg link Link object
601  * @arg addr Local address
602  *
603  * @return 0 on success or a negative error code
604  */
605 int rtnl_link_vxlan_set_local(struct rtnl_link *link, struct nl_addr *addr)
606 {
607  struct vxlan_info *vxi = link->l_info;
608 
609  IS_VXLAN_LINK_ASSERT(link);
610 
611  if ((nl_addr_get_family(addr) != AF_INET) ||
612  (nl_addr_get_len(addr) != sizeof(vxi->vxi_local)))
613  return -NLE_INVAL;
614 
615  memcpy(&vxi->vxi_local, nl_addr_get_binary_addr(addr),
616  sizeof(vxi->vxi_local));
617  vxi->vxi_mask |= VXLAN_HAS_LOCAL;
618 
619  return 0;
620 }
621 
622 /**
623  * Get source address to use for VXLAN
624  * @arg link Link object
625  * @arg addr Pointer to store local address
626  *
627  * @return 0 on success or a negative error code
628  */
629 int rtnl_link_vxlan_get_local(struct rtnl_link *link, struct nl_addr **addr)
630 {
631  struct vxlan_info *vxi = link->l_info;
632 
633  IS_VXLAN_LINK_ASSERT(link);
634 
635  if (!addr)
636  return -NLE_INVAL;
637 
638  if (!(vxi->vxi_mask & VXLAN_HAS_LOCAL))
639  return -NLE_AGAIN;
640 
641  *addr = nl_addr_build(AF_INET, &vxi->vxi_local, sizeof(vxi->vxi_local));
642 
643  return 0;
644 }
645 
646 /**
647  * Set IP TTL value to use for VXLAN
648  * @arg link Link object
649  * @arg ttl TTL value
650  *
651  * @return 0 on success or a negative error code
652  */
653 int rtnl_link_vxlan_set_ttl(struct rtnl_link *link, uint8_t ttl)
654 {
655  struct vxlan_info *vxi = link->l_info;
656 
657  IS_VXLAN_LINK_ASSERT(link);
658 
659  vxi->vxi_ttl = ttl;
660  vxi->vxi_mask |= VXLAN_HAS_TTL;
661 
662  return 0;
663 }
664 
665 /**
666  * Get IP TTL value to use for VXLAN
667  * @arg link Link object
668  *
669  * @return TTL value on success or a negative error code
670  */
672 {
673  struct vxlan_info *vxi = link->l_info;
674 
675  IS_VXLAN_LINK_ASSERT(link);
676 
677  if (!(vxi->vxi_mask & VXLAN_HAS_TTL))
678  return -NLE_AGAIN;
679 
680  return vxi->vxi_ttl;
681 }
682 
683 /**
684  * Set IP ToS value to use for VXLAN
685  * @arg link Link object
686  * @arg tos ToS value
687  *
688  * @return 0 on success or a negative error code
689  */
690 int rtnl_link_vxlan_set_tos(struct rtnl_link *link, uint8_t tos)
691 {
692  struct vxlan_info *vxi = link->l_info;
693 
694  IS_VXLAN_LINK_ASSERT(link);
695 
696  vxi->vxi_tos = tos;
697  vxi->vxi_mask |= VXLAN_HAS_TOS;
698 
699  return 0;
700 }
701 
702 /**
703  * Get IP ToS value to use for VXLAN
704  * @arg link Link object
705  *
706  * @return ToS value on success or a negative error code
707  */
709 {
710  struct vxlan_info *vxi = link->l_info;
711 
712  IS_VXLAN_LINK_ASSERT(link);
713 
714  if (!(vxi->vxi_mask & VXLAN_HAS_TOS))
715  return -NLE_AGAIN;
716 
717  return vxi->vxi_tos;
718 }
719 
720 /**
721  * Set VXLAN learning status
722  * @arg link Link object
723  * @arg learning Learning status value
724  *
725  * @return 0 on success or a negative error code
726  */
727 int rtnl_link_vxlan_set_learning(struct rtnl_link *link, uint8_t learning)
728 {
729  struct vxlan_info *vxi = link->l_info;
730 
731  IS_VXLAN_LINK_ASSERT(link);
732 
733  vxi->vxi_learning = learning;
734  vxi->vxi_mask |= VXLAN_HAS_LEARNING;
735 
736  return 0;
737 }
738 
739 /**
740  * Get VXLAN learning status
741  * @arg link Link object
742  *
743  * @return Learning status value on success or a negative error code
744  */
746 {
747  struct vxlan_info *vxi = link->l_info;
748 
749  IS_VXLAN_LINK_ASSERT(link);
750 
751  if (!(vxi->vxi_mask & VXLAN_HAS_LEARNING))
752  return -NLE_AGAIN;
753 
754  return vxi->vxi_learning;
755 }
756 
757 /**
758  * Enable VXLAN address learning
759  * @arg link Link object
760  *
761  * @return 0 on success or a negative error code
762  */
764 {
765  return rtnl_link_vxlan_set_learning(link, 1);
766 }
767 
768 /**
769  * Disable VXLAN address learning
770  * @arg link Link object
771  *
772  * @return 0 on success or a negative error code
773  */
775 {
776  return rtnl_link_vxlan_set_learning(link, 0);
777 }
778 
779 /**
780  * Set expiration timer value to use for VXLAN
781  * @arg link Link object
782  * @arg expiry Expiration timer value
783  *
784  * @return 0 on success or a negative error code
785  */
786 int rtnl_link_vxlan_set_ageing(struct rtnl_link *link, uint32_t expiry)
787 {
788  struct vxlan_info *vxi = link->l_info;
789 
790  IS_VXLAN_LINK_ASSERT(link);
791 
792  vxi->vxi_ageing = expiry;
793  vxi->vxi_mask |= VXLAN_HAS_AGEING;
794 
795  return 0;
796 }
797 
798 /**
799  * Get expiration timer value to use for VXLAN
800  * @arg link Link object
801  * @arg expiry Pointer to store expiration timer value
802  *
803  * @return 0 on success or a negative error code
804  */
805 int rtnl_link_vxlan_get_ageing(struct rtnl_link *link, uint32_t *expiry)
806 {
807  struct vxlan_info *vxi = link->l_info;
808 
809  IS_VXLAN_LINK_ASSERT(link);
810 
811  if (!expiry)
812  return -NLE_INVAL;
813 
814  if (vxi->vxi_mask & VXLAN_HAS_AGEING)
815  *expiry = vxi->vxi_ageing;
816  else
817  return -NLE_AGAIN;
818 
819  return 0;
820 }
821 
822 /**
823  * Set maximum number of forwarding database entries to use for VXLAN
824  * @arg link Link object
825  * @arg limit Maximum number
826  *
827  * @return 0 on success or a negative error code
828  */
829 int rtnl_link_vxlan_set_limit(struct rtnl_link *link, uint32_t limit)
830 {
831  struct vxlan_info *vxi = link->l_info;
832 
833  IS_VXLAN_LINK_ASSERT(link);
834 
835  vxi->vxi_limit = limit;
836  vxi->vxi_mask |= VXLAN_HAS_LIMIT;
837 
838  return 0;
839 }
840 
841 /**
842  * Get maximum number of forwarding database entries to use for VXLAN
843  * @arg link Link object
844  * @arg limit Pointer to store maximum number
845  *
846  * @return 0 on success or a negative error code
847  */
848 int rtnl_link_vxlan_get_limit(struct rtnl_link *link, uint32_t *limit)
849 {
850  struct vxlan_info *vxi = link->l_info;
851 
852  IS_VXLAN_LINK_ASSERT(link);
853 
854  if (!limit)
855  return -NLE_INVAL;
856 
857  if (vxi->vxi_mask & VXLAN_HAS_LIMIT)
858  *limit = vxi->vxi_limit;
859  else
860  return -NLE_AGAIN;
861 
862  return 0;
863 }
864 
865 /**
866  * Set range of UDP port numbers to use for VXLAN
867  * @arg link Link object
868  * @arg range Port number range
869  *
870  * @return 0 on success or a negative error code
871  */
873  struct ifla_vxlan_port_range *range)
874 {
875  struct vxlan_info *vxi = link->l_info;
876 
877  IS_VXLAN_LINK_ASSERT(link);
878 
879  if (!range)
880  return -NLE_INVAL;
881 
882  memcpy(&vxi->vxi_port_range, range, sizeof(vxi->vxi_port_range));
883  vxi->vxi_mask |= VXLAN_HAS_PORT_RANGE;
884 
885  return 0;
886 }
887 
888 /**
889  * Get range of UDP port numbers to use for VXLAN
890  * @arg link Link object
891  * @arg range Pointer to store port range
892  *
893  * @return 0 on success or a negative error code
894  */
896  struct ifla_vxlan_port_range *range)
897 {
898  struct vxlan_info *vxi = link->l_info;
899 
900  IS_VXLAN_LINK_ASSERT(link);
901 
902  if (!range)
903  return -NLE_INVAL;
904 
905  if (vxi->vxi_mask & VXLAN_HAS_PORT_RANGE)
906  memcpy(range, &vxi->vxi_port_range, sizeof(*range));
907  else
908  return -NLE_AGAIN;
909 
910  return 0;
911 }
912 
913 /**
914  * Set ARP proxy status to use for VXLAN
915  * @arg link Link object
916  * @arg proxy Status value
917  *
918  * @return 0 on success or a negative error code
919  */
920 int rtnl_link_vxlan_set_proxy(struct rtnl_link *link, uint8_t proxy)
921 {
922  struct vxlan_info *vxi = link->l_info;
923 
924  IS_VXLAN_LINK_ASSERT(link);
925 
926  vxi->vxi_proxy = proxy;
927  vxi->vxi_mask |= VXLAN_HAS_PROXY;
928 
929  return 0;
930 }
931 
932 /**
933  * Get ARP proxy status to use for VXLAN
934  * @arg link Link object
935  *
936  * @return Status value on success or a negative error code
937  */
939 {
940  struct vxlan_info *vxi = link->l_info;
941 
942  IS_VXLAN_LINK_ASSERT(link);
943 
944  if (!(vxi->vxi_mask & VXLAN_HAS_PROXY))
945  return -NLE_AGAIN;
946 
947  return vxi->vxi_proxy;
948 }
949 
950 /**
951  * Enable ARP proxy
952  * @arg link Link object
953  *
954  * @return 0 on success or a negative error code
955  */
957 {
958  return rtnl_link_vxlan_set_proxy(link, 1);
959 }
960 
961 /**
962  * Disable ARP proxy
963  * @arg link Link object
964  *
965  * @return 0 on success or a negative error code
966  */
968 {
969  return rtnl_link_vxlan_set_proxy(link, 0);
970 }
971 
972 /**
973  * Set Route Short Circuit status to use for VXLAN
974  * @arg link Link object
975  * @arg rsc Status value
976  *
977  * @return 0 on success or a negative error code
978  */
979 int rtnl_link_vxlan_set_rsc(struct rtnl_link *link, uint8_t rsc)
980 {
981  struct vxlan_info *vxi = link->l_info;
982 
983  IS_VXLAN_LINK_ASSERT(link);
984 
985  vxi->vxi_rsc = rsc;
986  vxi->vxi_mask |= VXLAN_HAS_RSC;
987 
988  return 0;
989 }
990 
991 /**
992  * Get Route Short Circuit status to use for VXLAN
993  * @arg link Link object
994  *
995  * @return Status value on success or a negative error code
996  */
998 {
999  struct vxlan_info *vxi = link->l_info;
1000 
1001  IS_VXLAN_LINK_ASSERT(link);
1002 
1003  if (!(vxi->vxi_mask & VXLAN_HAS_RSC))
1004  return -NLE_AGAIN;
1005 
1006  return vxi->vxi_rsc;
1007 }
1008 
1009 /**
1010  * Enable Route Short Circuit
1011  * @arg link Link object
1012  *
1013  * @return 0 on success or a negative error code
1014  */
1016 {
1017  return rtnl_link_vxlan_set_rsc(link, 1);
1018 }
1019 
1020 /**
1021  * Disable Route Short Circuit
1022  * @arg link Link object
1023  *
1024  * @return 0 on success or a negative error code
1025  */
1027 {
1028  return rtnl_link_vxlan_set_rsc(link, 0);
1029 }
1030 
1031 /**
1032  * Set netlink LLADDR miss notification status to use for VXLAN
1033  * @arg link Link object
1034  * @arg miss Status value
1035  *
1036  * @return 0 on success or a negative error code
1037  */
1038 int rtnl_link_vxlan_set_l2miss(struct rtnl_link *link, uint8_t miss)
1039 {
1040  struct vxlan_info *vxi = link->l_info;
1041 
1042  IS_VXLAN_LINK_ASSERT(link);
1043 
1044  vxi->vxi_l2miss = miss;
1045  vxi->vxi_mask |= VXLAN_HAS_L2MISS;
1046 
1047  return 0;
1048 }
1049 
1050 /**
1051  * Get netlink LLADDR miss notification status to use for VXLAN
1052  * @arg link Link object
1053  *
1054  * @return Status value on success or a negative error code
1055  */
1057 {
1058  struct vxlan_info *vxi = link->l_info;
1059 
1060  IS_VXLAN_LINK_ASSERT(link);
1061 
1062  if (!(vxi->vxi_mask & VXLAN_HAS_L2MISS))
1063  return -NLE_AGAIN;
1064 
1065  return vxi->vxi_l2miss;
1066 }
1067 
1068 /**
1069  * Enable netlink LLADDR miss notifications
1070  * @arg link Link object
1071  *
1072  * @return 0 on success or a negative error code
1073  */
1075 {
1076  return rtnl_link_vxlan_set_l2miss(link, 1);
1077 }
1078 
1079 /**
1080  * Disable netlink LLADDR miss notifications
1081  * @arg link Link object
1082  *
1083  * @return 0 on success or a negative error code
1084  */
1086 {
1087  return rtnl_link_vxlan_set_l2miss(link, 0);
1088 }
1089 
1090 /**
1091  * Set netlink IP ADDR miss notification status to use for VXLAN
1092  * @arg link Link object
1093  * @arg miss Status value
1094  *
1095  * @return 0 on success or a negative error code
1096  */
1097 int rtnl_link_vxlan_set_l3miss(struct rtnl_link *link, uint8_t miss)
1098 {
1099  struct vxlan_info *vxi = link->l_info;
1100 
1101  IS_VXLAN_LINK_ASSERT(link);
1102 
1103  vxi->vxi_l3miss = miss;
1104  vxi->vxi_mask |= VXLAN_HAS_L3MISS;
1105 
1106  return 0;
1107 }
1108 
1109 /**
1110  * Get netlink IP ADDR miss notification status to use for VXLAN
1111  * @arg link Link object
1112  *
1113  * @return Status value on success or a negative error code
1114  */
1116 {
1117  struct vxlan_info *vxi = link->l_info;
1118 
1119  IS_VXLAN_LINK_ASSERT(link);
1120 
1121  if (!(vxi->vxi_mask & VXLAN_HAS_L3MISS))
1122  return -NLE_AGAIN;
1123 
1124  return vxi->vxi_l3miss;
1125 }
1126 
1127 /**
1128  * Enable netlink IP DDR miss notifications
1129  * @arg link Link object
1130  *
1131  * @return 0 on success or a negative error code
1132  */
1134 {
1135  return rtnl_link_vxlan_set_l3miss(link, 1);
1136 }
1137 
1138 /**
1139  * Disable netlink IP ADDR miss notifications
1140  * @arg link Link object
1141  *
1142  * @return 0 on success or a negative error code
1143  */
1145 {
1146  return rtnl_link_vxlan_set_l3miss(link, 0);
1147 }
1148 
1149 /** @} */
1150 
1151 static void __init vxlan_init(void)
1152 {
1153  rtnl_link_register_info(&vxlan_info_ops);
1154 }
1155 
1156 static void __exit vxlan_exit(void)
1157 {
1158  rtnl_link_unregister_info(&vxlan_info_ops);
1159 }
1160 
1161 /** @} */
Dump object briefly on one line.
Definition: types.h:22
8 bit integer
Definition: attr.h:39
int rtnl_link_vxlan_disable_rsc(struct rtnl_link *link)
Disable Route Short Circuit.
Definition: vxlan.c:1026
int rtnl_link_vxlan_set_proxy(struct rtnl_link *link, uint8_t proxy)
Set ARP proxy status to use for VXLAN.
Definition: vxlan.c:920
Attribute validation policy.
Definition: attr.h:67
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:599
int rtnl_link_vxlan_enable_l3miss(struct rtnl_link *link)
Enable netlink IP DDR miss notifications.
Definition: vxlan.c:1133
int rtnl_link_vxlan_get_id(struct rtnl_link *link, uint32_t *id)
Get VXLAN Network Identifier.
Definition: vxlan.c:490
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
Definition: addr.c:216
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
int rtnl_link_vxlan_set_tos(struct rtnl_link *link, uint8_t tos)
Set IP ToS value to use for VXLAN.
Definition: vxlan.c:690
int rtnl_link_vxlan_disable_l3miss(struct rtnl_link *link)
Disable netlink IP ADDR miss notifications.
Definition: vxlan.c:1144
int rtnl_link_vxlan_set_local(struct rtnl_link *link, struct nl_addr *addr)
Set source address to use for VXLAN.
Definition: vxlan.c:605
int rtnl_link_vxlan_get_rsc(struct rtnl_link *link)
Get Route Short Circuit status to use for VXLAN.
Definition: vxlan.c:997
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:197
int rtnl_link_vxlan_enable_l2miss(struct rtnl_link *link)
Enable netlink LLADDR miss notifications.
Definition: vxlan.c:1074
int rtnl_link_vxlan_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP TTL value to use for VXLAN.
Definition: vxlan.c:653
Dump all attributes but no statistics.
Definition: types.h:23
int rtnl_link_vxlan_enable_learning(struct rtnl_link *link)
Enable VXLAN address learning.
Definition: vxlan.c:763
int rtnl_link_vxlan_set_rsc(struct rtnl_link *link, uint8_t rsc)
Set Route Short Circuit status to use for VXLAN.
Definition: vxlan.c:979
int rtnl_link_vxlan_set_l3miss(struct rtnl_link *link, uint8_t miss)
Set netlink IP ADDR miss notification status to use for VXLAN.
Definition: vxlan.c:1097
int rtnl_link_vxlan_get_limit(struct rtnl_link *link, uint32_t *limit)
Get maximum number of forwarding database entries to use for VXLAN.
Definition: vxlan.c:848
int rtnl_link_vxlan_get_group(struct rtnl_link *link, struct nl_addr **addr)
Get VXLAN multicast IP address.
Definition: vxlan.c:538
int rtnl_link_vxlan_set_learning(struct rtnl_link *link, uint8_t learning)
Set VXLAN learning status.
Definition: vxlan.c:727
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:917
int rtnl_link_vxlan_get_local(struct rtnl_link *link, struct nl_addr **addr)
Get source address to use for VXLAN.
Definition: vxlan.c:629
int rtnl_link_vxlan_get_learning(struct rtnl_link *link)
Get VXLAN learning status.
Definition: vxlan.c:745
int rtnl_link_vxlan_get_l3miss(struct rtnl_link *link)
Get netlink IP ADDR miss notification status to use for VXLAN.
Definition: vxlan.c:1115
int rtnl_link_vxlan_set_l2miss(struct rtnl_link *link, uint8_t miss)
Set netlink LLADDR miss notification status to use for VXLAN.
Definition: vxlan.c:1038
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition: attr.c:353
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:162
int rtnl_link_vxlan_get_link(struct rtnl_link *link, uint32_t *index)
Get physical device to use for VXLAN.
Definition: vxlan.c:581
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:991
int rtnl_link_vxlan_get_tos(struct rtnl_link *link)
Get IP ToS value to use for VXLAN.
Definition: vxlan.c:708
int rtnl_link_vxlan_disable_learning(struct rtnl_link *link)
Disable VXLAN address learning.
Definition: vxlan.c:774
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:233
int rtnl_link_vxlan_disable_l2miss(struct rtnl_link *link)
Disable netlink LLADDR miss notifications.
Definition: vxlan.c:1085
int rtnl_link_vxlan_get_l2miss(struct rtnl_link *link)
Get netlink LLADDR miss notification status to use for VXLAN.
Definition: vxlan.c:1056
int rtnl_link_vxlan_enable_rsc(struct rtnl_link *link)
Enable Route Short Circuit.
Definition: vxlan.c:1015
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:69
32 bit integer
Definition: attr.h:41
int rtnl_link_is_vxlan(struct rtnl_link *link)
Check if link is a VXLAN link.
Definition: vxlan.c:456
int rtnl_link_vxlan_get_ageing(struct rtnl_link *link, uint32_t *expiry)
Get expiration timer value to use for VXLAN.
Definition: vxlan.c:805
int rtnl_link_vxlan_set_id(struct rtnl_link *link, uint32_t id)
Set VXLAN Network Identifier.
Definition: vxlan.c:468
Dumping parameters.
Definition: types.h:33
struct rtnl_link * rtnl_link_vxlan_alloc(void)
Allocate link object of type VXLAN.
Definition: vxlan.c:434
int rtnl_link_vxlan_get_proxy(struct rtnl_link *link)
Get ARP proxy status to use for VXLAN.
Definition: vxlan.c:938
int rtnl_link_vxlan_get_port_range(struct rtnl_link *link, struct ifla_vxlan_port_range *range)
Get range of UDP port numbers to use for VXLAN.
Definition: vxlan.c:895
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:914
int rtnl_link_vxlan_disable_proxy(struct rtnl_link *link)
Disable ARP proxy.
Definition: vxlan.c:967
int rtnl_link_vxlan_set_group(struct rtnl_link *link, struct nl_addr *addr)
Set VXLAN multicast IP address.
Definition: vxlan.c:514
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition: addr.c:905
int rtnl_link_vxlan_get_ttl(struct rtnl_link *link)
Get IP TTL value to use for VXLAN.
Definition: vxlan.c:671
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition: addr.c:893
int rtnl_link_vxlan_set_limit(struct rtnl_link *link, uint32_t limit)
Set maximum number of forwarding database entries to use for VXLAN.
Definition: vxlan.c:829
int rtnl_link_vxlan_set_ageing(struct rtnl_link *link, uint32_t expiry)
Set expiration timer value to use for VXLAN.
Definition: vxlan.c:786
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
int rtnl_link_vxlan_enable_proxy(struct rtnl_link *link)
Enable ARP proxy.
Definition: vxlan.c:956
int rtnl_link_vxlan_set_port_range(struct rtnl_link *link, struct ifla_vxlan_port_range *range)
Set range of UDP port numbers to use for VXLAN.
Definition: vxlan.c:872
int rtnl_link_vxlan_set_link(struct rtnl_link *link, uint32_t index)
Set physical device to use for VXLAN.
Definition: vxlan.c:562
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition: addr.c:845