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>
34 #include <linux/if_link.h>
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)
63 struct ifla_vxlan_port_range vxi_port_range;
73 static struct nla_policy vxlan_policy[IFLA_VXLAN_MAX+1] = {
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 },
90 static int vxlan_alloc(
struct rtnl_link *link)
92 struct vxlan_info *vxi;
94 if ((vxi = calloc(1,
sizeof(*vxi))) == NULL)
102 static int vxlan_parse(
struct rtnl_link *link,
struct nlattr *data,
103 struct nlattr *xstats)
105 struct nlattr *tb[IFLA_VXLAN_MAX+1];
106 struct vxlan_info *vxi;
109 NL_DBG(3,
"Parsing VXLAN link info");
114 if ((err = vxlan_alloc(link)) < 0)
119 if (tb[IFLA_VXLAN_ID]) {
121 vxi->vxi_mask |= VXLAN_HAS_ID;
124 if (tb[IFLA_VXLAN_GROUP]) {
125 nla_memcpy(&vxi->vxi_group, tb[IFLA_VXLAN_GROUP],
126 sizeof(vxi->vxi_group));
127 vxi->vxi_mask |= VXLAN_HAS_GROUP;
130 if (tb[IFLA_VXLAN_LINK]) {
132 vxi->vxi_mask |= VXLAN_HAS_LINK;
135 if (tb[IFLA_VXLAN_LOCAL]) {
136 nla_memcpy(&vxi->vxi_local, tb[IFLA_VXLAN_LOCAL],
137 sizeof(vxi->vxi_local));
138 vxi->vxi_mask |= VXLAN_HAS_LOCAL;
141 if (tb[IFLA_VXLAN_TTL]) {
142 vxi->vxi_ttl =
nla_get_u8(tb[IFLA_VXLAN_TTL]);
143 vxi->vxi_mask |= VXLAN_HAS_TTL;
146 if (tb[IFLA_VXLAN_TOS]) {
147 vxi->vxi_tos =
nla_get_u8(tb[IFLA_VXLAN_TOS]);
148 vxi->vxi_mask |= VXLAN_HAS_TOS;
151 if (tb[IFLA_VXLAN_LEARNING]) {
152 vxi->vxi_learning =
nla_get_u8(tb[IFLA_VXLAN_LEARNING]);
153 vxi->vxi_mask |= VXLAN_HAS_LEARNING;
156 if (tb[IFLA_VXLAN_AGEING]) {
157 vxi->vxi_ageing =
nla_get_u32(tb[IFLA_VXLAN_AGEING]);
158 vxi->vxi_mask |= VXLAN_HAS_AGEING;
161 if (tb[IFLA_VXLAN_LIMIT]) {
162 vxi->vxi_limit =
nla_get_u32(tb[IFLA_VXLAN_LIMIT]);
163 vxi->vxi_mask |= VXLAN_HAS_LIMIT;
166 if (tb[IFLA_VXLAN_PORT_RANGE]) {
167 nla_memcpy(&vxi->vxi_port_range, tb[IFLA_VXLAN_PORT_RANGE],
168 sizeof(vxi->vxi_port_range));
169 vxi->vxi_mask |= VXLAN_HAS_PORT_RANGE;
172 if (tb[IFLA_VXLAN_PROXY]) {
173 vxi->vxi_proxy =
nla_get_u8(tb[IFLA_VXLAN_PROXY]);
174 vxi->vxi_mask |= VXLAN_HAS_PROXY;
177 if (tb[IFLA_VXLAN_RSC]) {
178 vxi->vxi_rsc =
nla_get_u8(tb[IFLA_VXLAN_RSC]);
179 vxi->vxi_mask |= VXLAN_HAS_RSC;
182 if (tb[IFLA_VXLAN_L2MISS]) {
183 vxi->vxi_l2miss =
nla_get_u8(tb[IFLA_VXLAN_L2MISS]);
184 vxi->vxi_mask |= VXLAN_HAS_L2MISS;
187 if (tb[IFLA_VXLAN_L3MISS]) {
188 vxi->vxi_l3miss =
nla_get_u8(tb[IFLA_VXLAN_L3MISS]);
189 vxi->vxi_mask |= VXLAN_HAS_L3MISS;
198 static void vxlan_free(
struct rtnl_link *link)
200 struct vxlan_info *vxi = link->l_info;
208 struct vxlan_info *vxi = link->l_info;
210 nl_dump(p,
"vxlan-id %u", vxi->vxi_id);
215 struct vxlan_info *vxi = link->l_info;
216 char *name, addr[INET_ADDRSTRLEN];
218 nl_dump_line(p,
" vxlan-id %u\n", vxi->vxi_id);
220 if (vxi->vxi_mask & VXLAN_HAS_GROUP) {
222 if(inet_ntop(AF_INET, &vxi->vxi_group, addr,
sizeof(addr)))
223 nl_dump_line(p,
"%s\n", addr);
225 nl_dump_line(p,
"%#x\n", ntohs(vxi->vxi_group));
228 if (vxi->vxi_mask & VXLAN_HAS_LINK) {
232 nl_dump_line(p,
"%s\n", name);
234 nl_dump_line(p,
"%u\n", vxi->vxi_link);
237 if (vxi->vxi_mask & VXLAN_HAS_LOCAL) {
239 if(inet_ntop(AF_INET, &vxi->vxi_local, addr,
sizeof(addr)))
240 nl_dump_line(p,
"%s\n", addr);
242 nl_dump_line(p,
"%#x\n", ntohs(vxi->vxi_local));
245 if (vxi->vxi_mask & VXLAN_HAS_TTL) {
248 nl_dump_line(p,
"%u\n", vxi->vxi_ttl);
250 nl_dump_line(p,
"inherit\n");
253 if (vxi->vxi_mask & VXLAN_HAS_TOS) {
255 if (vxi->vxi_tos == 1)
256 nl_dump_line(p,
"inherit\n", vxi->vxi_tos);
258 nl_dump_line(p,
"%#x\n", vxi->vxi_tos);
261 if (vxi->vxi_mask & VXLAN_HAS_LEARNING) {
263 if (vxi->vxi_learning)
264 nl_dump_line(p,
"enabled (%#x)\n", vxi->vxi_learning);
266 nl_dump_line(p,
"disabled\n");
269 if (vxi->vxi_mask & VXLAN_HAS_AGEING) {
272 nl_dump_line(p,
"%u seconds\n", vxi->vxi_ageing);
274 nl_dump_line(p,
"disabled\n");
277 if (vxi->vxi_mask & VXLAN_HAS_LIMIT) {
280 nl_dump_line(p,
"%u\n", vxi->vxi_limit);
282 nl_dump_line(p,
"unlimited\n");
285 if (vxi->vxi_mask & VXLAN_HAS_PORT_RANGE)
286 nl_dump_line(p,
" port range %u - %u\n",
287 ntohs(vxi->vxi_port_range.low),
288 ntohs(vxi->vxi_port_range.high));
290 if (vxi->vxi_mask & VXLAN_HAS_PROXY) {
293 nl_dump_line(p,
"enabled (%#x)\n", vxi->vxi_proxy);
295 nl_dump_line(p,
"disabled\n");
298 if (vxi->vxi_mask & VXLAN_HAS_RSC) {
301 nl_dump_line(p,
"enabled (%#x)\n", vxi->vxi_rsc);
303 nl_dump_line(p,
"disabled\n");
306 if (vxi->vxi_mask & VXLAN_HAS_L2MISS) {
309 nl_dump_line(p,
"enabled (%#x)\n", vxi->vxi_l2miss);
311 nl_dump_line(p,
"disabled\n");
314 if (vxi->vxi_mask & VXLAN_HAS_L3MISS) {
317 nl_dump_line(p,
"enabled (%#x)\n", vxi->vxi_l3miss);
319 nl_dump_line(p,
"disabled\n");
325 struct vxlan_info *vdst, *vsrc = src->l_info;
336 memcpy(vdst, vsrc,
sizeof(
struct vxlan_info));
341 static int vxlan_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
343 struct vxlan_info *vxi = link->l_info;
349 if (vxi->vxi_mask & VXLAN_HAS_ID)
352 if (vxi->vxi_mask & VXLAN_HAS_GROUP)
353 NLA_PUT(msg, IFLA_VXLAN_GROUP,
sizeof(vxi->vxi_group), &vxi->vxi_group);
355 if (vxi->vxi_mask & VXLAN_HAS_LINK)
358 if (vxi->vxi_mask & VXLAN_HAS_LOCAL)
359 NLA_PUT(msg, IFLA_VXLAN_LOCAL,
sizeof(vxi->vxi_local), &vxi->vxi_local);
361 if (vxi->vxi_mask & VXLAN_HAS_TTL)
362 NLA_PUT_U8(msg, IFLA_VXLAN_TTL, vxi->vxi_ttl);
364 if (vxi->vxi_mask & VXLAN_HAS_TOS)
365 NLA_PUT_U8(msg, IFLA_VXLAN_TOS, vxi->vxi_tos);
367 if (vxi->vxi_mask & VXLAN_HAS_LEARNING)
368 NLA_PUT_U8(msg, IFLA_VXLAN_LEARNING, vxi->vxi_learning);
370 if (vxi->vxi_mask & VXLAN_HAS_AGEING)
371 NLA_PUT_U32(msg, IFLA_VXLAN_AGEING, vxi->vxi_ageing);
373 if (vxi->vxi_mask & VXLAN_HAS_LIMIT)
374 NLA_PUT_U32(msg, IFLA_VXLAN_LIMIT, vxi->vxi_limit);
376 if (vxi->vxi_mask & VXLAN_HAS_PORT_RANGE)
377 NLA_PUT(msg, IFLA_VXLAN_PORT_RANGE,
sizeof(vxi->vxi_port_range),
378 &vxi->vxi_port_range);
380 if (vxi->vxi_mask & VXLAN_HAS_PROXY)
381 NLA_PUT_U8(msg, IFLA_VXLAN_PROXY, vxi->vxi_proxy);
383 if (vxi->vxi_mask & VXLAN_HAS_RSC)
384 NLA_PUT_U8(msg, IFLA_VXLAN_RSC, vxi->vxi_rsc);
386 if (vxi->vxi_mask & VXLAN_HAS_L2MISS)
387 NLA_PUT_U8(msg, IFLA_VXLAN_L2MISS, vxi->vxi_l2miss);
389 if (vxi->vxi_mask & VXLAN_HAS_L3MISS)
390 NLA_PUT_U8(msg, IFLA_VXLAN_L3MISS, vxi->vxi_l3miss);
399 static struct rtnl_link_info_ops vxlan_info_ops = {
401 .io_alloc = vxlan_alloc,
402 .io_parse = vxlan_parse,
407 .io_clone = vxlan_clone,
408 .io_put_attrs = vxlan_put_attrs,
409 .io_free = vxlan_free,
413 #define IS_VXLAN_LINK_ASSERT(link) \
414 if ((link)->l_info_ops != &vxlan_info_ops) { \
415 APPBUG("Link is not a vxlan link. set type \"vxlan\" first."); \
416 return -NLE_OPNOTSUPP; \
454 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"vxlan");
466 struct vxlan_info *vxi = link->l_info;
468 IS_VXLAN_LINK_ASSERT(link);
470 if (
id > VXLAN_ID_MAX)
474 vxi->vxi_mask |= VXLAN_HAS_ID;
488 struct vxlan_info *vxi = link->l_info;
490 IS_VXLAN_LINK_ASSERT(link);
495 if (vxi->vxi_mask & VXLAN_HAS_ID)
512 struct vxlan_info *vxi = link->l_info;
514 IS_VXLAN_LINK_ASSERT(link);
521 sizeof(vxi->vxi_group));
522 vxi->vxi_mask |= VXLAN_HAS_GROUP;
536 struct vxlan_info *vxi = link->l_info;
538 IS_VXLAN_LINK_ASSERT(link);
543 if (!(vxi->vxi_mask & VXLAN_HAS_GROUP))
546 *addr =
nl_addr_build(AF_INET, &vxi->vxi_group,
sizeof(vxi->vxi_group));
560 struct vxlan_info *vxi = link->l_info;
562 IS_VXLAN_LINK_ASSERT(link);
564 vxi->vxi_link = index;
565 vxi->vxi_mask |= VXLAN_HAS_LINK;
579 struct vxlan_info *vxi = link->l_info;
581 IS_VXLAN_LINK_ASSERT(link);
586 if (!(vxi->vxi_mask & VXLAN_HAS_LINK))
589 *index = vxi->vxi_link;
603 struct vxlan_info *vxi = link->l_info;
605 IS_VXLAN_LINK_ASSERT(link);
612 sizeof(vxi->vxi_local));
613 vxi->vxi_mask |= VXLAN_HAS_LOCAL;
627 struct vxlan_info *vxi = link->l_info;
629 IS_VXLAN_LINK_ASSERT(link);
634 if (!(vxi->vxi_mask & VXLAN_HAS_LOCAL))
637 *addr =
nl_addr_build(AF_INET, &vxi->vxi_local,
sizeof(vxi->vxi_local));
651 struct vxlan_info *vxi = link->l_info;
653 IS_VXLAN_LINK_ASSERT(link);
656 vxi->vxi_mask |= VXLAN_HAS_TTL;
669 struct vxlan_info *vxi = link->l_info;
671 IS_VXLAN_LINK_ASSERT(link);
673 if (!(vxi->vxi_mask & VXLAN_HAS_TTL))
688 struct vxlan_info *vxi = link->l_info;
690 IS_VXLAN_LINK_ASSERT(link);
693 vxi->vxi_mask |= VXLAN_HAS_TOS;
706 struct vxlan_info *vxi = link->l_info;
708 IS_VXLAN_LINK_ASSERT(link);
710 if (!(vxi->vxi_mask & VXLAN_HAS_TOS))
725 struct vxlan_info *vxi = link->l_info;
727 IS_VXLAN_LINK_ASSERT(link);
729 vxi->vxi_learning = learning;
730 vxi->vxi_mask |= VXLAN_HAS_LEARNING;
743 struct vxlan_info *vxi = link->l_info;
745 IS_VXLAN_LINK_ASSERT(link);
747 if (!(vxi->vxi_mask & VXLAN_HAS_LEARNING))
750 return vxi->vxi_learning;
784 struct vxlan_info *vxi = link->l_info;
786 IS_VXLAN_LINK_ASSERT(link);
788 vxi->vxi_ageing = expiry;
789 vxi->vxi_mask |= VXLAN_HAS_AGEING;
803 struct vxlan_info *vxi = link->l_info;
805 IS_VXLAN_LINK_ASSERT(link);
810 if (vxi->vxi_mask & VXLAN_HAS_AGEING)
811 *expiry = vxi->vxi_ageing;
827 struct vxlan_info *vxi = link->l_info;
829 IS_VXLAN_LINK_ASSERT(link);
831 vxi->vxi_limit = limit;
832 vxi->vxi_mask |= VXLAN_HAS_LIMIT;
846 struct vxlan_info *vxi = link->l_info;
848 IS_VXLAN_LINK_ASSERT(link);
853 if (vxi->vxi_mask & VXLAN_HAS_LIMIT)
854 *limit = vxi->vxi_limit;
869 struct ifla_vxlan_port_range *range)
871 struct vxlan_info *vxi = link->l_info;
873 IS_VXLAN_LINK_ASSERT(link);
878 memcpy(&vxi->vxi_port_range, range,
sizeof(vxi->vxi_port_range));
879 vxi->vxi_mask |= VXLAN_HAS_PORT_RANGE;
892 struct ifla_vxlan_port_range *range)
894 struct vxlan_info *vxi = link->l_info;
896 IS_VXLAN_LINK_ASSERT(link);
901 if (vxi->vxi_mask & VXLAN_HAS_PORT_RANGE)
902 memcpy(range, &vxi->vxi_port_range,
sizeof(*range));
918 struct vxlan_info *vxi = link->l_info;
920 IS_VXLAN_LINK_ASSERT(link);
922 vxi->vxi_proxy = proxy;
923 vxi->vxi_mask |= VXLAN_HAS_PROXY;
936 struct vxlan_info *vxi = link->l_info;
938 IS_VXLAN_LINK_ASSERT(link);
940 if (!(vxi->vxi_mask & VXLAN_HAS_PROXY))
943 return vxi->vxi_proxy;
977 struct vxlan_info *vxi = link->l_info;
979 IS_VXLAN_LINK_ASSERT(link);
982 vxi->vxi_mask |= VXLAN_HAS_RSC;
995 struct vxlan_info *vxi = link->l_info;
997 IS_VXLAN_LINK_ASSERT(link);
999 if (!(vxi->vxi_mask & VXLAN_HAS_RSC))
1002 return vxi->vxi_rsc;
1036 struct vxlan_info *vxi = link->l_info;
1038 IS_VXLAN_LINK_ASSERT(link);
1040 vxi->vxi_l2miss = miss;
1041 vxi->vxi_mask |= VXLAN_HAS_L2MISS;
1054 struct vxlan_info *vxi = link->l_info;
1056 IS_VXLAN_LINK_ASSERT(link);
1058 if (!(vxi->vxi_mask & VXLAN_HAS_L2MISS))
1061 return vxi->vxi_l2miss;
1095 struct vxlan_info *vxi = link->l_info;
1097 IS_VXLAN_LINK_ASSERT(link);
1099 vxi->vxi_l3miss = miss;
1100 vxi->vxi_mask |= VXLAN_HAS_L3MISS;
1113 struct vxlan_info *vxi = link->l_info;
1115 IS_VXLAN_LINK_ASSERT(link);
1117 if (!(vxi->vxi_mask & VXLAN_HAS_L3MISS))
1120 return vxi->vxi_l3miss;
1147 static void __init vxlan_init(
void)
1152 static void __exit vxlan_exit(
void)