1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2013 Yasunobu Chiba <yasu@dsl.gr.jp>
4 */
5
6 /**
7 * @ingroup link
8 * @defgroup vxlan VXLAN
9 * Virtual eXtensible Local Area Network link module
10 *
11 * @details
12 * \b Link Type Name: "vxlan"
13 *
14 * @route_doc{link_vxlan, VXLAN Documentation}
15 *
16 * @{
17 */
18
19 #include <netlink-private/netlink.h>
20 #include <netlink/netlink.h>
21 #include <netlink/attr.h>
22 #include <netlink/utils.h>
23 #include <netlink/object.h>
24 #include <netlink/route/rtnl.h>
25 #include <netlink-private/route/link/api.h>
26 #include <netlink/route/link/vxlan.h>
27
28 #include <linux/if_link.h>
29
30 /** @cond SKIP */
31 #define VXLAN_ATTR_ID (1<<0)
32 #define VXLAN_ATTR_GROUP (1<<1)
33 #define VXLAN_ATTR_LINK (1<<2)
34 #define VXLAN_ATTR_LOCAL (1<<3)
35 #define VXLAN_ATTR_TTL (1<<4)
36 #define VXLAN_ATTR_TOS (1<<5)
37 #define VXLAN_ATTR_LEARNING (1<<6)
38 #define VXLAN_ATTR_AGEING (1<<7)
39 #define VXLAN_ATTR_LIMIT (1<<8)
40 #define VXLAN_ATTR_PORT_RANGE (1<<9)
41 #define VXLAN_ATTR_PROXY (1<<10)
42 #define VXLAN_ATTR_RSC (1<<11)
43 #define VXLAN_ATTR_L2MISS (1<<12)
44 #define VXLAN_ATTR_L3MISS (1<<13)
45 #define VXLAN_ATTR_GROUP6 (1<<14)
46 #define VXLAN_ATTR_LOCAL6 (1<<15)
47 #define VXLAN_ATTR_PORT (1<<16)
48 #define VXLAN_ATTR_UDP_CSUM (1<<17)
49 #define VXLAN_ATTR_UDP_ZERO_CSUM6_TX (1<<18)
50 #define VXLAN_ATTR_UDP_ZERO_CSUM6_RX (1<<19)
51 #define VXLAN_ATTR_REMCSUM_TX (1<<20)
52 #define VXLAN_ATTR_REMCSUM_RX (1<<21)
53 #define VXLAN_ATTR_COLLECT_METADATA (1<<22)
54 #define VXLAN_ATTR_LABEL (1<<23)
55 #define VXLAN_ATTR_FLAGS (1<<24)
56
57 struct vxlan_info
58 {
59 uint32_t vxi_id;
60 uint32_t vxi_group;
61 struct in6_addr vxi_group6;
62 uint32_t vxi_link;
63 uint32_t vxi_local;
64 struct in6_addr vxi_local6;
65 uint8_t vxi_ttl;
66 uint8_t vxi_tos;
67 uint8_t vxi_learning;
68 uint8_t vxi_flags;
69 uint32_t vxi_ageing;
70 uint32_t vxi_limit;
71 struct ifla_vxlan_port_range vxi_port_range;
72 uint8_t vxi_proxy;
73 uint8_t vxi_rsc;
74 uint8_t vxi_l2miss;
75 uint8_t vxi_l3miss;
76 uint16_t vxi_port;
77 uint8_t vxi_udp_csum;
78 uint8_t vxi_udp_zero_csum6_tx;
79 uint8_t vxi_udp_zero_csum6_rx;
80 uint8_t vxi_remcsum_tx;
81 uint8_t vxi_remcsum_rx;
82 uint8_t vxi_collect_metadata;
83 uint32_t vxi_label;
84 uint32_t ce_mask;
85 };
86
87 /** @endcond */
88
89 static struct nla_policy vxlan_policy[IFLA_VXLAN_MAX+1] = {
90 [IFLA_VXLAN_ID] = { .type = NLA_U32 },
91 [IFLA_VXLAN_GROUP] = { .minlen = sizeof(uint32_t) },
92 [IFLA_VXLAN_GROUP6] = { .minlen = sizeof(struct in6_addr) },
93 [IFLA_VXLAN_LINK] = { .type = NLA_U32 },
94 [IFLA_VXLAN_LOCAL] = { .minlen = sizeof(uint32_t) },
95 [IFLA_VXLAN_LOCAL6] = { .minlen = sizeof(struct in6_addr) },
96 [IFLA_VXLAN_TTL] = { .type = NLA_U8 },
97 [IFLA_VXLAN_TOS] = { .type = NLA_U8 },
98 [IFLA_VXLAN_LABEL] = { .type = NLA_U32 },
99 [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 },
100 [IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
101 [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
102 [IFLA_VXLAN_PORT_RANGE] = { .minlen = sizeof(struct ifla_vxlan_port_range) },
103 [IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
104 [IFLA_VXLAN_RSC] = { .type = NLA_U8 },
105 [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
106 [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
107 [IFLA_VXLAN_COLLECT_METADATA] = { .type = NLA_U8 },
108 [IFLA_VXLAN_PORT] = { .type = NLA_U16 },
109 [IFLA_VXLAN_UDP_CSUM] = { .type = NLA_U8 },
110 [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
111 [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
112 [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 },
113 [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 },
114 [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, },
115 [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, },
116 [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG },
117 };
118
vxlan_alloc(struct rtnl_link * link)119 static int vxlan_alloc(struct rtnl_link *link)
120 {
121 struct vxlan_info *vxi;
122
123 if (link->l_info)
124 memset(link->l_info, 0, sizeof(*vxi));
125 else {
126 if ((vxi = calloc(1, sizeof(*vxi))) == NULL)
127 return -NLE_NOMEM;
128
129 link->l_info = vxi;
130 }
131
132 return 0;
133 }
134
vxlan_parse(struct rtnl_link * link,struct nlattr * data,struct nlattr * xstats)135 static int vxlan_parse(struct rtnl_link *link, struct nlattr *data,
136 struct nlattr *xstats)
137 {
138 struct nlattr *tb[IFLA_VXLAN_MAX+1];
139 struct vxlan_info *vxi;
140 int err;
141
142 NL_DBG(3, "Parsing VXLAN link info\n");
143
144 if ((err = nla_parse_nested(tb, IFLA_VXLAN_MAX, data, vxlan_policy)) < 0)
145 goto errout;
146
147 if ((err = vxlan_alloc(link)) < 0)
148 goto errout;
149
150 vxi = link->l_info;
151
152 if (tb[IFLA_VXLAN_ID]) {
153 vxi->vxi_id = nla_get_u32(tb[IFLA_VXLAN_ID]);
154 vxi->ce_mask |= VXLAN_ATTR_ID;
155 }
156
157 if (tb[IFLA_VXLAN_GROUP6]) {
158 nla_memcpy(&vxi->vxi_group6, tb[IFLA_VXLAN_GROUP6],
159 sizeof(vxi->vxi_group6));
160 vxi->ce_mask |= VXLAN_ATTR_GROUP6;
161 }
162
163 if (tb[IFLA_VXLAN_GROUP]) {
164 nla_memcpy(&vxi->vxi_group, tb[IFLA_VXLAN_GROUP],
165 sizeof(vxi->vxi_group));
166 vxi->ce_mask |= VXLAN_ATTR_GROUP;
167 vxi->ce_mask &= ~VXLAN_ATTR_GROUP6;
168 }
169
170 if (tb[IFLA_VXLAN_LINK]) {
171 vxi->vxi_link = nla_get_u32(tb[IFLA_VXLAN_LINK]);
172 vxi->ce_mask |= VXLAN_ATTR_LINK;
173 }
174
175 if (tb[IFLA_VXLAN_LOCAL6]) {
176 nla_memcpy(&vxi->vxi_local6, tb[IFLA_VXLAN_LOCAL6],
177 sizeof(vxi->vxi_local6));
178 vxi->ce_mask |= VXLAN_ATTR_LOCAL6;
179 }
180
181 if (tb[IFLA_VXLAN_LOCAL]) {
182 nla_memcpy(&vxi->vxi_local, tb[IFLA_VXLAN_LOCAL],
183 sizeof(vxi->vxi_local));
184 vxi->ce_mask |= VXLAN_ATTR_LOCAL;
185 vxi->ce_mask &= ~VXLAN_ATTR_LOCAL6;
186 }
187
188 if (tb[IFLA_VXLAN_TTL]) {
189 vxi->vxi_ttl = nla_get_u8(tb[IFLA_VXLAN_TTL]);
190 vxi->ce_mask |= VXLAN_ATTR_TTL;
191 }
192
193 if (tb[IFLA_VXLAN_TOS]) {
194 vxi->vxi_tos = nla_get_u8(tb[IFLA_VXLAN_TOS]);
195 vxi->ce_mask |= VXLAN_ATTR_TOS;
196 }
197
198 if (tb[IFLA_VXLAN_LEARNING]) {
199 vxi->vxi_learning = nla_get_u8(tb[IFLA_VXLAN_LEARNING]);
200 vxi->ce_mask |= VXLAN_ATTR_LEARNING;
201 }
202
203 if (tb[IFLA_VXLAN_AGEING]) {
204 vxi->vxi_ageing = nla_get_u32(tb[IFLA_VXLAN_AGEING]);
205 vxi->ce_mask |= VXLAN_ATTR_AGEING;
206 }
207
208 if (tb[IFLA_VXLAN_LIMIT]) {
209 vxi->vxi_limit = nla_get_u32(tb[IFLA_VXLAN_LIMIT]);
210 vxi->ce_mask |= VXLAN_ATTR_LIMIT;
211 }
212
213 if (tb[IFLA_VXLAN_PORT_RANGE]) {
214 nla_memcpy(&vxi->vxi_port_range, tb[IFLA_VXLAN_PORT_RANGE],
215 sizeof(vxi->vxi_port_range));
216 vxi->ce_mask |= VXLAN_ATTR_PORT_RANGE;
217 }
218
219 if (tb[IFLA_VXLAN_PROXY]) {
220 vxi->vxi_proxy = nla_get_u8(tb[IFLA_VXLAN_PROXY]);
221 vxi->ce_mask |= VXLAN_ATTR_PROXY;
222 }
223
224 if (tb[IFLA_VXLAN_RSC]) {
225 vxi->vxi_rsc = nla_get_u8(tb[IFLA_VXLAN_RSC]);
226 vxi->ce_mask |= VXLAN_ATTR_RSC;
227 }
228
229 if (tb[IFLA_VXLAN_L2MISS]) {
230 vxi->vxi_l2miss = nla_get_u8(tb[IFLA_VXLAN_L2MISS]);
231 vxi->ce_mask |= VXLAN_ATTR_L2MISS;
232 }
233
234 if (tb[IFLA_VXLAN_L3MISS]) {
235 vxi->vxi_l3miss = nla_get_u8(tb[IFLA_VXLAN_L3MISS]);
236 vxi->ce_mask |= VXLAN_ATTR_L3MISS;
237 }
238
239 if (tb[IFLA_VXLAN_PORT]) {
240 vxi->vxi_port = nla_get_u16(tb[IFLA_VXLAN_PORT]);
241 vxi->ce_mask |= VXLAN_ATTR_PORT;
242 }
243
244 if (tb[IFLA_VXLAN_UDP_CSUM]) {
245 vxi->vxi_udp_csum = nla_get_u8(tb[IFLA_VXLAN_UDP_CSUM]);
246 vxi->ce_mask |= VXLAN_ATTR_UDP_CSUM;
247 }
248
249 if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
250 vxi->vxi_udp_zero_csum6_tx = nla_get_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]);
251 vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_TX;
252 }
253
254 if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) {
255 vxi->vxi_udp_zero_csum6_rx = nla_get_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]);
256 vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_RX;
257 }
258
259 if (tb[IFLA_VXLAN_REMCSUM_TX]) {
260 vxi->vxi_remcsum_tx = nla_get_u8(tb[IFLA_VXLAN_REMCSUM_TX]);
261 vxi->ce_mask |= VXLAN_ATTR_REMCSUM_TX;
262 }
263
264 if (tb[IFLA_VXLAN_REMCSUM_RX]) {
265 vxi->vxi_remcsum_rx = nla_get_u8(tb[IFLA_VXLAN_REMCSUM_RX]);
266 vxi->ce_mask |= VXLAN_ATTR_REMCSUM_RX;
267 }
268
269 if (tb[IFLA_VXLAN_GBP])
270 vxi->vxi_flags |= RTNL_LINK_VXLAN_F_GBP;
271
272 if (tb[IFLA_VXLAN_REMCSUM_NOPARTIAL])
273 vxi->vxi_flags |= RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL;
274
275 if (tb[IFLA_VXLAN_COLLECT_METADATA]) {
276 vxi->vxi_collect_metadata = nla_get_u8(tb[IFLA_VXLAN_COLLECT_METADATA]);
277 vxi->ce_mask |= VXLAN_ATTR_COLLECT_METADATA;
278 }
279
280 if (tb[IFLA_VXLAN_LABEL]) {
281 vxi->vxi_label = nla_get_u32(tb[IFLA_VXLAN_LABEL]);
282 vxi->ce_mask |= VXLAN_ATTR_LABEL;
283 }
284
285 if (tb[IFLA_VXLAN_GPE])
286 vxi->vxi_flags |= RTNL_LINK_VXLAN_F_GPE;
287
288 err = 0;
289
290 errout:
291 return err;
292 }
293
vxlan_free(struct rtnl_link * link)294 static void vxlan_free(struct rtnl_link *link)
295 {
296 struct vxlan_info *vxi = link->l_info;
297
298 free(vxi);
299 link->l_info = NULL;
300 }
301
vxlan_dump_line(struct rtnl_link * link,struct nl_dump_params * p)302 static void vxlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
303 {
304 struct vxlan_info *vxi = link->l_info;
305
306 nl_dump(p, "vxlan-id %u", vxi->vxi_id);
307 }
308
vxlan_dump_details(struct rtnl_link * link,struct nl_dump_params * p)309 static void vxlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
310 {
311 struct vxlan_info *vxi = link->l_info;
312 char *name, addr[INET6_ADDRSTRLEN];
313 struct rtnl_link *parent;
314
315 nl_dump_line(p, " vxlan-id %u\n", vxi->vxi_id);
316
317 if (vxi->ce_mask & VXLAN_ATTR_GROUP) {
318 nl_dump(p, " group ");
319 nl_dump_line(p, "%s\n",
320 _nl_inet_ntop(AF_INET, &vxi->vxi_group, addr));
321 } else if (vxi->ce_mask & VXLAN_ATTR_GROUP6) {
322 nl_dump(p, " group ");
323 nl_dump_line(p, "%s\n",
324 _nl_inet_ntop(AF_INET6, &vxi->vxi_group6, addr));
325 }
326
327 if (vxi->ce_mask & VXLAN_ATTR_LINK) {
328 nl_dump(p, " link ");
329
330 name = NULL;
331 parent = link_lookup(link->ce_cache, vxi->vxi_link);
332 if (parent)
333 name = rtnl_link_get_name(parent);
334
335 if (name)
336 nl_dump_line(p, "%s\n", name);
337 else
338 nl_dump_line(p, "%u\n", vxi->vxi_link);
339 }
340
341 if (vxi->ce_mask & VXLAN_ATTR_LOCAL) {
342 nl_dump(p, " local ");
343 nl_dump_line(p, "%s\n",
344 _nl_inet_ntop(AF_INET, &vxi->vxi_local, addr));
345 } else if (vxi->ce_mask & VXLAN_ATTR_LOCAL6) {
346 nl_dump(p, " local ");
347 nl_dump_line(p, "%s\n",
348 _nl_inet_ntop(AF_INET6, &vxi->vxi_local6, addr));
349 }
350
351 if (vxi->ce_mask & VXLAN_ATTR_TTL) {
352 nl_dump(p, " ttl ");
353 if(vxi->vxi_ttl)
354 nl_dump_line(p, "%u\n", vxi->vxi_ttl);
355 else
356 nl_dump_line(p, "inherit\n");
357 }
358
359 if (vxi->ce_mask & VXLAN_ATTR_TOS) {
360 nl_dump(p, " tos ");
361 if (vxi->vxi_tos == 1)
362 nl_dump_line(p, "inherit\n");
363 else
364 nl_dump_line(p, "%#x\n", vxi->vxi_tos);
365 }
366
367 if (vxi->ce_mask & VXLAN_ATTR_LEARNING) {
368 nl_dump(p, " learning ");
369 if (vxi->vxi_learning)
370 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_learning);
371 else
372 nl_dump_line(p, "disabled\n");
373 }
374
375 if (vxi->ce_mask & VXLAN_ATTR_AGEING) {
376 nl_dump(p, " ageing ");
377 if (vxi->vxi_ageing)
378 nl_dump_line(p, "%u seconds\n", vxi->vxi_ageing);
379 else
380 nl_dump_line(p, "disabled\n");
381 }
382
383 if (vxi->ce_mask & VXLAN_ATTR_LIMIT) {
384 nl_dump(p, " limit ");
385 if (vxi->vxi_limit)
386 nl_dump_line(p, "%u\n", vxi->vxi_limit);
387 else
388 nl_dump_line(p, "unlimited\n");
389 }
390
391 if (vxi->ce_mask & VXLAN_ATTR_PORT_RANGE)
392 nl_dump_line(p, " port range %u - %u\n",
393 ntohs(vxi->vxi_port_range.low),
394 ntohs(vxi->vxi_port_range.high));
395
396 if (vxi->ce_mask & VXLAN_ATTR_PROXY) {
397 nl_dump(p, " proxy ");
398 if (vxi->vxi_proxy)
399 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_proxy);
400 else
401 nl_dump_line(p, "disabled\n");
402 }
403
404 if (vxi->ce_mask & VXLAN_ATTR_RSC) {
405 nl_dump(p, " rsc ");
406 if (vxi->vxi_rsc)
407 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_rsc);
408 else
409 nl_dump_line(p, "disabled\n");
410 }
411
412 if (vxi->ce_mask & VXLAN_ATTR_L2MISS) {
413 nl_dump(p, " l2miss ");
414 if (vxi->vxi_l2miss)
415 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_l2miss);
416 else
417 nl_dump_line(p, "disabled\n");
418 }
419
420 if (vxi->ce_mask & VXLAN_ATTR_L3MISS) {
421 nl_dump(p, " l3miss ");
422 if (vxi->vxi_l3miss)
423 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_l3miss);
424 else
425 nl_dump_line(p, "disabled\n");
426 }
427
428 if (vxi->ce_mask & VXLAN_ATTR_PORT) {
429 nl_dump(p, " port ");
430 nl_dump_line(p, "%u\n", ntohs(vxi->vxi_port));
431 }
432
433 if (vxi->ce_mask & VXLAN_ATTR_UDP_CSUM) {
434 nl_dump(p, " UDP checksums ");
435 if (vxi->vxi_udp_csum)
436 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_udp_csum);
437 else
438 nl_dump_line(p, "disabled\n");
439 }
440
441 if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_TX) {
442 nl_dump(p, " udp-zero-csum6-tx ");
443 if (vxi->vxi_udp_zero_csum6_tx)
444 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_udp_zero_csum6_tx);
445 else
446 nl_dump_line(p, "disabled\n");
447 }
448
449 if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_RX) {
450 nl_dump(p, " udp-zero-csum6-rx ");
451 if (vxi->vxi_udp_zero_csum6_rx)
452 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_udp_zero_csum6_rx);
453 else
454 nl_dump_line(p, "disabled\n");
455 }
456
457 if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_TX) {
458 nl_dump(p, " remcsum-tx ");
459 if (vxi->vxi_remcsum_tx)
460 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_remcsum_tx);
461 else
462 nl_dump_line(p, "disabled\n");
463 }
464
465 if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_RX) {
466 nl_dump(p, " remcsum-rx ");
467 if (vxi->vxi_remcsum_rx)
468 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_remcsum_rx);
469 else
470 nl_dump_line(p, "disabled\n");
471 }
472
473 if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GBP)
474 nl_dump(p, " gbp\n");
475
476 if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL)
477 nl_dump(p, " rncsum-nopartial\n");
478
479 if (vxi->ce_mask & VXLAN_ATTR_COLLECT_METADATA) {
480 nl_dump(p, " remcsum-rx ");
481 if (vxi->vxi_collect_metadata)
482 nl_dump_line(p, "enabled (%#x)\n", vxi->vxi_collect_metadata);
483 else
484 nl_dump_line(p, "disabled\n");
485 }
486
487 if (vxi->ce_mask & VXLAN_ATTR_LABEL) {
488 nl_dump(p, " label ");
489 nl_dump_line(p, "%u\n", ntohl(vxi->vxi_label));
490 }
491
492 if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GPE)
493 nl_dump(p, " gpe\n");
494 }
495
vxlan_clone(struct rtnl_link * dst,struct rtnl_link * src)496 static int vxlan_clone(struct rtnl_link *dst, struct rtnl_link *src)
497 {
498 struct vxlan_info *vdst, *vsrc = src->l_info;
499 int err;
500
501 dst->l_info = NULL;
502 if ((err = rtnl_link_set_type(dst, "vxlan")) < 0)
503 return err;
504 vdst = dst->l_info;
505
506 if (!vdst || !vsrc)
507 return -NLE_NOMEM;
508
509 memcpy(vdst, vsrc, sizeof(struct vxlan_info));
510
511 return 0;
512 }
513
vxlan_put_attrs(struct nl_msg * msg,struct rtnl_link * link)514 static int vxlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
515 {
516 struct vxlan_info *vxi = link->l_info;
517 struct nlattr *data;
518
519 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
520 return -NLE_MSGSIZE;
521
522 if (vxi->ce_mask & VXLAN_ATTR_ID)
523 NLA_PUT_U32(msg, IFLA_VXLAN_ID, vxi->vxi_id);
524
525 if (vxi->ce_mask & VXLAN_ATTR_GROUP)
526 NLA_PUT(msg, IFLA_VXLAN_GROUP, sizeof(vxi->vxi_group), &vxi->vxi_group);
527
528 if (vxi->ce_mask & VXLAN_ATTR_GROUP6)
529 NLA_PUT(msg, IFLA_VXLAN_GROUP6, sizeof(vxi->vxi_group6), &vxi->vxi_group6);
530
531 if (vxi->ce_mask & VXLAN_ATTR_LINK)
532 NLA_PUT_U32(msg, IFLA_VXLAN_LINK, vxi->vxi_link);
533
534 if (vxi->ce_mask & VXLAN_ATTR_LOCAL)
535 NLA_PUT(msg, IFLA_VXLAN_LOCAL, sizeof(vxi->vxi_local), &vxi->vxi_local);
536
537 if (vxi->ce_mask & VXLAN_ATTR_LOCAL6)
538 NLA_PUT(msg, IFLA_VXLAN_LOCAL6, sizeof(vxi->vxi_local6), &vxi->vxi_local6);
539
540 if (vxi->ce_mask & VXLAN_ATTR_TTL)
541 NLA_PUT_U8(msg, IFLA_VXLAN_TTL, vxi->vxi_ttl);
542
543 if (vxi->ce_mask & VXLAN_ATTR_TOS)
544 NLA_PUT_U8(msg, IFLA_VXLAN_TOS, vxi->vxi_tos);
545
546 if (vxi->ce_mask & VXLAN_ATTR_LEARNING)
547 NLA_PUT_U8(msg, IFLA_VXLAN_LEARNING, vxi->vxi_learning);
548
549 if (vxi->ce_mask & VXLAN_ATTR_AGEING)
550 NLA_PUT_U32(msg, IFLA_VXLAN_AGEING, vxi->vxi_ageing);
551
552 if (vxi->ce_mask & VXLAN_ATTR_LIMIT)
553 NLA_PUT_U32(msg, IFLA_VXLAN_LIMIT, vxi->vxi_limit);
554
555 if (vxi->ce_mask & VXLAN_ATTR_PORT_RANGE)
556 NLA_PUT(msg, IFLA_VXLAN_PORT_RANGE, sizeof(vxi->vxi_port_range),
557 &vxi->vxi_port_range);
558
559 if (vxi->ce_mask & VXLAN_ATTR_PROXY)
560 NLA_PUT_U8(msg, IFLA_VXLAN_PROXY, vxi->vxi_proxy);
561
562 if (vxi->ce_mask & VXLAN_ATTR_RSC)
563 NLA_PUT_U8(msg, IFLA_VXLAN_RSC, vxi->vxi_rsc);
564
565 if (vxi->ce_mask & VXLAN_ATTR_L2MISS)
566 NLA_PUT_U8(msg, IFLA_VXLAN_L2MISS, vxi->vxi_l2miss);
567
568 if (vxi->ce_mask & VXLAN_ATTR_L3MISS)
569 NLA_PUT_U8(msg, IFLA_VXLAN_L3MISS, vxi->vxi_l3miss);
570
571 if (vxi->ce_mask & VXLAN_ATTR_PORT)
572 NLA_PUT_U32(msg, IFLA_VXLAN_PORT, vxi->vxi_port);
573
574 if (vxi->ce_mask & VXLAN_ATTR_UDP_CSUM)
575 NLA_PUT_U8(msg, IFLA_VXLAN_UDP_CSUM, vxi->vxi_udp_csum);
576
577 if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_TX)
578 NLA_PUT_U8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, vxi->vxi_udp_zero_csum6_tx);
579
580 if (vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_RX)
581 NLA_PUT_U8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, vxi->vxi_udp_zero_csum6_rx);
582
583 if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_TX)
584 NLA_PUT_U8(msg, IFLA_VXLAN_REMCSUM_TX, vxi->vxi_remcsum_tx);
585
586 if (vxi->ce_mask & VXLAN_ATTR_REMCSUM_RX)
587 NLA_PUT_U8(msg, IFLA_VXLAN_REMCSUM_RX, vxi->vxi_remcsum_rx);
588
589 if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GBP)
590 NLA_PUT_FLAG(msg, IFLA_VXLAN_GBP);
591
592 if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL)
593 NLA_PUT_FLAG(msg, IFLA_VXLAN_REMCSUM_NOPARTIAL);
594
595 if (vxi->ce_mask & VXLAN_ATTR_COLLECT_METADATA)
596 NLA_PUT_U8(msg, IFLA_VXLAN_COLLECT_METADATA, vxi->vxi_collect_metadata);
597
598 if (vxi->ce_mask & VXLAN_ATTR_LABEL)
599 NLA_PUT_U32(msg, IFLA_VXLAN_LABEL, vxi->vxi_label);
600
601 if (vxi->vxi_flags & RTNL_LINK_VXLAN_F_GPE)
602 NLA_PUT_FLAG(msg, IFLA_VXLAN_GPE);
603
604 nla_nest_end(msg, data);
605
606 nla_put_failure:
607
608 return 0;
609 }
610
vxlan_compare(struct rtnl_link * link_a,struct rtnl_link * link_b,int flags)611 static int vxlan_compare(struct rtnl_link *link_a, struct rtnl_link *link_b,
612 int flags)
613 {
614 struct vxlan_info *a = link_a->l_info;
615 struct vxlan_info *b = link_b->l_info;
616 int diff = 0;
617 uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
618
619 #define VXLAN_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, VXLAN_ATTR_##ATTR, a, b, EXPR)
620
621 diff |= VXLAN_DIFF(ID, a->vxi_id != b->vxi_id);
622 diff |= VXLAN_DIFF(GROUP, a->vxi_group != b->vxi_group);
623 diff |= VXLAN_DIFF(LINK, a->vxi_link != b->vxi_link);
624 diff |= VXLAN_DIFF(LOCAL, a->vxi_local != b->vxi_local);
625 diff |= VXLAN_DIFF(TOS, a->vxi_tos != b->vxi_tos);
626 diff |= VXLAN_DIFF(TTL, a->vxi_ttl != b->vxi_ttl);
627 diff |= VXLAN_DIFF(LEARNING, a->vxi_learning != b->vxi_learning);
628 diff |= VXLAN_DIFF(AGEING, a->vxi_ageing != b->vxi_ageing);
629 diff |= VXLAN_DIFF(LIMIT, a->vxi_limit != b->vxi_limit);
630 diff |= VXLAN_DIFF(PORT_RANGE,
631 a->vxi_port_range.low != b->vxi_port_range.low);
632 diff |= VXLAN_DIFF(PORT_RANGE,
633 a->vxi_port_range.high != b->vxi_port_range.high);
634 diff |= VXLAN_DIFF(PROXY, a->vxi_proxy != b->vxi_proxy);
635 diff |= VXLAN_DIFF(RSC, a->vxi_proxy != b->vxi_proxy);
636 diff |= VXLAN_DIFF(L2MISS, a->vxi_proxy != b->vxi_proxy);
637 diff |= VXLAN_DIFF(L3MISS, a->vxi_proxy != b->vxi_proxy);
638 diff |= VXLAN_DIFF(PORT, a->vxi_port != b->vxi_port);
639 diff |= VXLAN_DIFF(GROUP6, memcmp(&a->vxi_group6, &b->vxi_group6, sizeof(a->vxi_group6)) != 0);
640 diff |= VXLAN_DIFF(LOCAL6, memcmp(&a->vxi_local6, &b->vxi_local6, sizeof(a->vxi_local6)) != 0);
641 diff |= VXLAN_DIFF(UDP_CSUM, a->vxi_proxy != b->vxi_proxy);
642 diff |= VXLAN_DIFF(UDP_ZERO_CSUM6_TX, a->vxi_proxy != b->vxi_proxy);
643 diff |= VXLAN_DIFF(UDP_ZERO_CSUM6_RX, a->vxi_proxy != b->vxi_proxy);
644 diff |= VXLAN_DIFF(REMCSUM_TX, a->vxi_proxy != b->vxi_proxy);
645 diff |= VXLAN_DIFF(REMCSUM_RX, a->vxi_proxy != b->vxi_proxy);
646 diff |= VXLAN_DIFF(COLLECT_METADATA, a->vxi_collect_metadata != b->vxi_collect_metadata);
647 diff |= VXLAN_DIFF(LABEL, a->vxi_label != b->vxi_label);
648 diff |= VXLAN_DIFF(FLAGS, a->vxi_flags != b->vxi_flags);
649 #undef VXLAN_DIFF
650
651 return diff;
652 }
653
654 static struct rtnl_link_info_ops vxlan_info_ops = {
655 .io_name = "vxlan",
656 .io_alloc = vxlan_alloc,
657 .io_parse = vxlan_parse,
658 .io_dump = {
659 [NL_DUMP_LINE] = vxlan_dump_line,
660 [NL_DUMP_DETAILS] = vxlan_dump_details,
661 },
662 .io_clone = vxlan_clone,
663 .io_put_attrs = vxlan_put_attrs,
664 .io_free = vxlan_free,
665 .io_compare = vxlan_compare,
666 };
667
668 /** @cond SKIP */
669 #define IS_VXLAN_LINK_ASSERT(link) \
670 if ((link)->l_info_ops != &vxlan_info_ops) { \
671 APPBUG("Link is not a vxlan link. set type \"vxlan\" first."); \
672 return -NLE_OPNOTSUPP; \
673 }
674 /** @endcond */
675
676 /**
677 * @name VXLAN Object
678 * @{
679 */
680
681 /**
682 * Allocate link object of type VXLAN
683 *
684 * @return Allocated link object or NULL.
685 */
rtnl_link_vxlan_alloc(void)686 struct rtnl_link *rtnl_link_vxlan_alloc(void)
687 {
688 struct rtnl_link *link;
689
690 if (!(link = rtnl_link_alloc()))
691 return NULL;
692
693 if (rtnl_link_set_type(link, "vxlan") < 0) {
694 rtnl_link_put(link);
695 return NULL;
696 }
697
698 return link;
699 }
700
701 /**
702 * Check if link is a VXLAN link
703 * @arg link Link object
704 *
705 * @return True if link is a VXLAN link, otherwise false is returned.
706 */
rtnl_link_is_vxlan(struct rtnl_link * link)707 int rtnl_link_is_vxlan(struct rtnl_link *link)
708 {
709 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vxlan");
710 }
711
712 /**
713 * Set VXLAN Network Identifier
714 * @arg link Link object
715 * @arg id VXLAN network identifier (or VXLAN segment identifier)
716 *
717 * @return 0 on success or a negative error code
718 */
rtnl_link_vxlan_set_id(struct rtnl_link * link,uint32_t id)719 int rtnl_link_vxlan_set_id(struct rtnl_link *link, uint32_t id)
720 {
721 struct vxlan_info *vxi = link->l_info;
722
723 IS_VXLAN_LINK_ASSERT(link);
724
725 if (id > VXLAN_ID_MAX)
726 return -NLE_INVAL;
727
728 vxi->vxi_id = id;
729 vxi->ce_mask |= VXLAN_ATTR_ID;
730
731 return 0;
732 }
733
734 /**
735 * Get VXLAN Network Identifier
736 * @arg link Link object
737 * @arg id Pointer to store network identifier
738 *
739 * @return 0 on success or a negative error code
740 */
rtnl_link_vxlan_get_id(struct rtnl_link * link,uint32_t * id)741 int rtnl_link_vxlan_get_id(struct rtnl_link *link, uint32_t *id)
742 {
743 struct vxlan_info *vxi = link->l_info;
744
745 IS_VXLAN_LINK_ASSERT(link);
746
747 if(!id)
748 return -NLE_INVAL;
749
750 if (vxi->ce_mask & VXLAN_ATTR_ID)
751 *id = vxi->vxi_id;
752 else
753 return -NLE_AGAIN;
754
755 return 0;
756 }
757
758 /**
759 * Set VXLAN multicast IP address
760 * @arg link Link object
761 * @arg addr Multicast IP address to join
762 *
763 * @return 0 on success or a negative error code
764 */
rtnl_link_vxlan_set_group(struct rtnl_link * link,struct nl_addr * addr)765 int rtnl_link_vxlan_set_group(struct rtnl_link *link, struct nl_addr *addr)
766 {
767 struct vxlan_info *vxi = link->l_info;
768
769 IS_VXLAN_LINK_ASSERT(link);
770
771 if ((nl_addr_get_family(addr) == AF_INET) &&
772 (nl_addr_get_len(addr) == sizeof(vxi->vxi_group))) {
773 memcpy(&vxi->vxi_group, nl_addr_get_binary_addr(addr),
774 sizeof(vxi->vxi_group));
775 vxi->ce_mask |= VXLAN_ATTR_GROUP;
776 vxi->ce_mask &= ~VXLAN_ATTR_GROUP6;
777 } else if ((nl_addr_get_family(addr) == AF_INET6) &&
778 (nl_addr_get_len(addr) == sizeof(vxi->vxi_group6))) {
779 memcpy(&vxi->vxi_group6, nl_addr_get_binary_addr(addr),
780 sizeof(vxi->vxi_group6));
781 vxi->ce_mask |= VXLAN_ATTR_GROUP6;
782 vxi->ce_mask &= ~VXLAN_ATTR_GROUP;
783 } else
784 return -NLE_INVAL;
785
786 return 0;
787 }
788
789 /**
790 * Get VXLAN multicast IP address
791 * @arg link Link object
792 * @arg addr Pointer to store multicast IP address
793 *
794 * @return 0 on success or a negative error code
795 */
rtnl_link_vxlan_get_group(struct rtnl_link * link,struct nl_addr ** addr)796 int rtnl_link_vxlan_get_group(struct rtnl_link *link, struct nl_addr **addr)
797 {
798 struct vxlan_info *vxi = link->l_info;
799
800 IS_VXLAN_LINK_ASSERT(link);
801
802 if (!addr)
803 return -NLE_INVAL;
804
805 if (vxi->ce_mask & VXLAN_ATTR_GROUP)
806 *addr = nl_addr_build(AF_INET, &vxi->vxi_group, sizeof(vxi->vxi_group));
807 else if (vxi->ce_mask & VXLAN_ATTR_GROUP6)
808 *addr = nl_addr_build(AF_INET6, &vxi->vxi_group6, sizeof(vxi->vxi_group6));
809 else
810 return -NLE_AGAIN;
811
812 return 0;
813 }
814
815 /**
816 * Set physical device to use for VXLAN
817 * @arg link Link object
818 * @arg index Interface index
819 *
820 * @return 0 on success or a negative error code
821 */
rtnl_link_vxlan_set_link(struct rtnl_link * link,uint32_t index)822 int rtnl_link_vxlan_set_link(struct rtnl_link *link, uint32_t index)
823 {
824 struct vxlan_info *vxi = link->l_info;
825
826 IS_VXLAN_LINK_ASSERT(link);
827
828 vxi->vxi_link = index;
829 vxi->ce_mask |= VXLAN_ATTR_LINK;
830
831 return 0;
832 }
833
834 /**
835 * Get physical device to use for VXLAN
836 * @arg link Link object
837 * @arg index Pointer to store interface index
838 *
839 * @return 0 on success or a negative error code
840 */
rtnl_link_vxlan_get_link(struct rtnl_link * link,uint32_t * index)841 int rtnl_link_vxlan_get_link(struct rtnl_link *link, uint32_t *index)
842 {
843 struct vxlan_info *vxi = link->l_info;
844
845 IS_VXLAN_LINK_ASSERT(link);
846
847 if (!index)
848 return -NLE_INVAL;
849
850 if (!(vxi->ce_mask & VXLAN_ATTR_LINK))
851 return -NLE_AGAIN;
852
853 *index = vxi->vxi_link;
854
855 return 0;
856 }
857
858 /**
859 * Set source address to use for VXLAN
860 * @arg link Link object
861 * @arg addr Local address
862 *
863 * @return 0 on success or a negative error code
864 */
rtnl_link_vxlan_set_local(struct rtnl_link * link,struct nl_addr * addr)865 int rtnl_link_vxlan_set_local(struct rtnl_link *link, struct nl_addr *addr)
866 {
867 struct vxlan_info *vxi = link->l_info;
868
869 IS_VXLAN_LINK_ASSERT(link);
870
871 if ((nl_addr_get_family(addr) == AF_INET) &&
872 (nl_addr_get_len(addr) == sizeof(vxi->vxi_local))) {
873 memcpy(&vxi->vxi_local, nl_addr_get_binary_addr(addr),
874 sizeof(vxi->vxi_local));
875 vxi->ce_mask |= VXLAN_ATTR_LOCAL;
876 vxi->ce_mask &= ~VXLAN_ATTR_LOCAL6;
877 } else if ((nl_addr_get_family(addr) == AF_INET6) &&
878 (nl_addr_get_len(addr) == sizeof(vxi->vxi_local6))) {
879 memcpy(&vxi->vxi_local6, nl_addr_get_binary_addr(addr),
880 sizeof(vxi->vxi_local6));
881 vxi->ce_mask |= VXLAN_ATTR_LOCAL6;
882 vxi->ce_mask &= ~VXLAN_ATTR_LOCAL;
883 } else
884 return -NLE_INVAL;
885
886 return 0;
887 }
888
889 /**
890 * Get source address to use for VXLAN
891 * @arg link Link object
892 * @arg addr Pointer to store local address
893 *
894 * @return 0 on success or a negative error code
895 */
rtnl_link_vxlan_get_local(struct rtnl_link * link,struct nl_addr ** addr)896 int rtnl_link_vxlan_get_local(struct rtnl_link *link, struct nl_addr **addr)
897 {
898 struct vxlan_info *vxi = link->l_info;
899
900 IS_VXLAN_LINK_ASSERT(link);
901
902 if (!addr)
903 return -NLE_INVAL;
904
905 if (vxi->ce_mask & VXLAN_ATTR_LOCAL)
906 *addr = nl_addr_build(AF_INET, &vxi->vxi_local, sizeof(vxi->vxi_local));
907 else if (vxi->ce_mask & VXLAN_ATTR_LOCAL6)
908 *addr = nl_addr_build(AF_INET6, &vxi->vxi_local6, sizeof(vxi->vxi_local6));
909 else
910 return -NLE_AGAIN;
911
912 return 0;
913 }
914
915 /**
916 * Set IP TTL value to use for VXLAN
917 * @arg link Link object
918 * @arg ttl TTL value
919 *
920 * @return 0 on success or a negative error code
921 */
rtnl_link_vxlan_set_ttl(struct rtnl_link * link,uint8_t ttl)922 int rtnl_link_vxlan_set_ttl(struct rtnl_link *link, uint8_t ttl)
923 {
924 struct vxlan_info *vxi = link->l_info;
925
926 IS_VXLAN_LINK_ASSERT(link);
927
928 vxi->vxi_ttl = ttl;
929 vxi->ce_mask |= VXLAN_ATTR_TTL;
930
931 return 0;
932 }
933
934 /**
935 * Get IP TTL value to use for VXLAN
936 * @arg link Link object
937 *
938 * @return TTL value on success or a negative error code
939 */
rtnl_link_vxlan_get_ttl(struct rtnl_link * link)940 int rtnl_link_vxlan_get_ttl(struct rtnl_link *link)
941 {
942 struct vxlan_info *vxi = link->l_info;
943
944 IS_VXLAN_LINK_ASSERT(link);
945
946 if (!(vxi->ce_mask & VXLAN_ATTR_TTL))
947 return -NLE_AGAIN;
948
949 return vxi->vxi_ttl;
950 }
951
952 /**
953 * Set IP ToS value to use for VXLAN
954 * @arg link Link object
955 * @arg tos ToS value
956 *
957 * @return 0 on success or a negative error code
958 */
rtnl_link_vxlan_set_tos(struct rtnl_link * link,uint8_t tos)959 int rtnl_link_vxlan_set_tos(struct rtnl_link *link, uint8_t tos)
960 {
961 struct vxlan_info *vxi = link->l_info;
962
963 IS_VXLAN_LINK_ASSERT(link);
964
965 vxi->vxi_tos = tos;
966 vxi->ce_mask |= VXLAN_ATTR_TOS;
967
968 return 0;
969 }
970
971 /**
972 * Get IP ToS value to use for VXLAN
973 * @arg link Link object
974 *
975 * @return ToS value on success or a negative error code
976 */
rtnl_link_vxlan_get_tos(struct rtnl_link * link)977 int rtnl_link_vxlan_get_tos(struct rtnl_link *link)
978 {
979 struct vxlan_info *vxi = link->l_info;
980
981 IS_VXLAN_LINK_ASSERT(link);
982
983 if (!(vxi->ce_mask & VXLAN_ATTR_TOS))
984 return -NLE_AGAIN;
985
986 return vxi->vxi_tos;
987 }
988
989 /**
990 * Set VXLAN learning status
991 * @arg link Link object
992 * @arg learning Learning status value
993 *
994 * @return 0 on success or a negative error code
995 */
rtnl_link_vxlan_set_learning(struct rtnl_link * link,uint8_t learning)996 int rtnl_link_vxlan_set_learning(struct rtnl_link *link, uint8_t learning)
997 {
998 struct vxlan_info *vxi = link->l_info;
999
1000 IS_VXLAN_LINK_ASSERT(link);
1001
1002 vxi->vxi_learning = learning;
1003 vxi->ce_mask |= VXLAN_ATTR_LEARNING;
1004
1005 return 0;
1006 }
1007
1008 /**
1009 * Get VXLAN learning status
1010 * @arg link Link object
1011 *
1012 * @return Learning status value on success or a negative error code
1013 */
rtnl_link_vxlan_get_learning(struct rtnl_link * link)1014 int rtnl_link_vxlan_get_learning(struct rtnl_link *link)
1015 {
1016 struct vxlan_info *vxi = link->l_info;
1017
1018 IS_VXLAN_LINK_ASSERT(link);
1019
1020 if (!(vxi->ce_mask & VXLAN_ATTR_LEARNING))
1021 return -NLE_AGAIN;
1022
1023 return vxi->vxi_learning;
1024 }
1025
1026 /**
1027 * Enable VXLAN address learning
1028 * @arg link Link object
1029 *
1030 * @return 0 on success or a negative error code
1031 */
rtnl_link_vxlan_enable_learning(struct rtnl_link * link)1032 int rtnl_link_vxlan_enable_learning(struct rtnl_link *link)
1033 {
1034 return rtnl_link_vxlan_set_learning(link, 1);
1035 }
1036
1037 /**
1038 * Disable VXLAN address learning
1039 * @arg link Link object
1040 *
1041 * @return 0 on success or a negative error code
1042 */
rtnl_link_vxlan_disable_learning(struct rtnl_link * link)1043 int rtnl_link_vxlan_disable_learning(struct rtnl_link *link)
1044 {
1045 return rtnl_link_vxlan_set_learning(link, 0);
1046 }
1047
1048 /**
1049 * Set expiration timer value to use for VXLAN
1050 * @arg link Link object
1051 * @arg expiry Expiration timer value
1052 *
1053 * @return 0 on success or a negative error code
1054 */
rtnl_link_vxlan_set_ageing(struct rtnl_link * link,uint32_t expiry)1055 int rtnl_link_vxlan_set_ageing(struct rtnl_link *link, uint32_t expiry)
1056 {
1057 struct vxlan_info *vxi = link->l_info;
1058
1059 IS_VXLAN_LINK_ASSERT(link);
1060
1061 vxi->vxi_ageing = expiry;
1062 vxi->ce_mask |= VXLAN_ATTR_AGEING;
1063
1064 return 0;
1065 }
1066
1067 /**
1068 * Get expiration timer value to use for VXLAN
1069 * @arg link Link object
1070 * @arg expiry Pointer to store expiration timer value
1071 *
1072 * @return 0 on success or a negative error code
1073 */
rtnl_link_vxlan_get_ageing(struct rtnl_link * link,uint32_t * expiry)1074 int rtnl_link_vxlan_get_ageing(struct rtnl_link *link, uint32_t *expiry)
1075 {
1076 struct vxlan_info *vxi = link->l_info;
1077
1078 IS_VXLAN_LINK_ASSERT(link);
1079
1080 if (!expiry)
1081 return -NLE_INVAL;
1082
1083 if (vxi->ce_mask & VXLAN_ATTR_AGEING)
1084 *expiry = vxi->vxi_ageing;
1085 else
1086 return -NLE_AGAIN;
1087
1088 return 0;
1089 }
1090
1091 /**
1092 * Set maximum number of forwarding database entries to use for VXLAN
1093 * @arg link Link object
1094 * @arg limit Maximum number
1095 *
1096 * @return 0 on success or a negative error code
1097 */
rtnl_link_vxlan_set_limit(struct rtnl_link * link,uint32_t limit)1098 int rtnl_link_vxlan_set_limit(struct rtnl_link *link, uint32_t limit)
1099 {
1100 struct vxlan_info *vxi = link->l_info;
1101
1102 IS_VXLAN_LINK_ASSERT(link);
1103
1104 vxi->vxi_limit = limit;
1105 vxi->ce_mask |= VXLAN_ATTR_LIMIT;
1106
1107 return 0;
1108 }
1109
1110 /**
1111 * Get maximum number of forwarding database entries to use for VXLAN
1112 * @arg link Link object
1113 * @arg limit Pointer to store maximum number
1114 *
1115 * @return 0 on success or a negative error code
1116 */
rtnl_link_vxlan_get_limit(struct rtnl_link * link,uint32_t * limit)1117 int rtnl_link_vxlan_get_limit(struct rtnl_link *link, uint32_t *limit)
1118 {
1119 struct vxlan_info *vxi = link->l_info;
1120
1121 IS_VXLAN_LINK_ASSERT(link);
1122
1123 if (!limit)
1124 return -NLE_INVAL;
1125
1126 if (vxi->ce_mask & VXLAN_ATTR_LIMIT)
1127 *limit = vxi->vxi_limit;
1128 else
1129 return -NLE_AGAIN;
1130
1131 return 0;
1132 }
1133
1134 /**
1135 * Set range of UDP port numbers to use for VXLAN
1136 * @arg link Link object
1137 * @arg range Port number range
1138 *
1139 * @return 0 on success or a negative error code
1140 */
rtnl_link_vxlan_set_port_range(struct rtnl_link * link,struct ifla_vxlan_port_range * range)1141 int rtnl_link_vxlan_set_port_range(struct rtnl_link *link,
1142 struct ifla_vxlan_port_range *range)
1143 {
1144 struct vxlan_info *vxi = link->l_info;
1145
1146 IS_VXLAN_LINK_ASSERT(link);
1147
1148 if (!range)
1149 return -NLE_INVAL;
1150
1151 memcpy(&vxi->vxi_port_range, range, sizeof(vxi->vxi_port_range));
1152 vxi->ce_mask |= VXLAN_ATTR_PORT_RANGE;
1153
1154 return 0;
1155 }
1156
1157 /**
1158 * Get range of UDP port numbers to use for VXLAN
1159 * @arg link Link object
1160 * @arg range Pointer to store port range
1161 *
1162 * @return 0 on success or a negative error code
1163 */
rtnl_link_vxlan_get_port_range(struct rtnl_link * link,struct ifla_vxlan_port_range * range)1164 int rtnl_link_vxlan_get_port_range(struct rtnl_link *link,
1165 struct ifla_vxlan_port_range *range)
1166 {
1167 struct vxlan_info *vxi = link->l_info;
1168
1169 IS_VXLAN_LINK_ASSERT(link);
1170
1171 if (!range)
1172 return -NLE_INVAL;
1173
1174 if (vxi->ce_mask & VXLAN_ATTR_PORT_RANGE)
1175 memcpy(range, &vxi->vxi_port_range, sizeof(*range));
1176 else
1177 return -NLE_AGAIN;
1178
1179 return 0;
1180 }
1181
1182 /**
1183 * Set ARP proxy status to use for VXLAN
1184 * @arg link Link object
1185 * @arg proxy Status value
1186 *
1187 * @return 0 on success or a negative error code
1188 */
rtnl_link_vxlan_set_proxy(struct rtnl_link * link,uint8_t proxy)1189 int rtnl_link_vxlan_set_proxy(struct rtnl_link *link, uint8_t proxy)
1190 {
1191 struct vxlan_info *vxi = link->l_info;
1192
1193 IS_VXLAN_LINK_ASSERT(link);
1194
1195 vxi->vxi_proxy = proxy;
1196 vxi->ce_mask |= VXLAN_ATTR_PROXY;
1197
1198 return 0;
1199 }
1200
1201 /**
1202 * Get ARP proxy status to use for VXLAN
1203 * @arg link Link object
1204 *
1205 * @return Status value on success or a negative error code
1206 */
rtnl_link_vxlan_get_proxy(struct rtnl_link * link)1207 int rtnl_link_vxlan_get_proxy(struct rtnl_link *link)
1208 {
1209 struct vxlan_info *vxi = link->l_info;
1210
1211 IS_VXLAN_LINK_ASSERT(link);
1212
1213 if (!(vxi->ce_mask & VXLAN_ATTR_PROXY))
1214 return -NLE_AGAIN;
1215
1216 return vxi->vxi_proxy;
1217 }
1218
1219 /**
1220 * Enable ARP proxy
1221 * @arg link Link object
1222 *
1223 * @return 0 on success or a negative error code
1224 */
rtnl_link_vxlan_enable_proxy(struct rtnl_link * link)1225 int rtnl_link_vxlan_enable_proxy(struct rtnl_link *link)
1226 {
1227 return rtnl_link_vxlan_set_proxy(link, 1);
1228 }
1229
1230 /**
1231 * Disable ARP proxy
1232 * @arg link Link object
1233 *
1234 * @return 0 on success or a negative error code
1235 */
rtnl_link_vxlan_disable_proxy(struct rtnl_link * link)1236 int rtnl_link_vxlan_disable_proxy(struct rtnl_link *link)
1237 {
1238 return rtnl_link_vxlan_set_proxy(link, 0);
1239 }
1240
1241 /**
1242 * Set Route Short Circuit status to use for VXLAN
1243 * @arg link Link object
1244 * @arg rsc Status value
1245 *
1246 * @return 0 on success or a negative error code
1247 */
rtnl_link_vxlan_set_rsc(struct rtnl_link * link,uint8_t rsc)1248 int rtnl_link_vxlan_set_rsc(struct rtnl_link *link, uint8_t rsc)
1249 {
1250 struct vxlan_info *vxi = link->l_info;
1251
1252 IS_VXLAN_LINK_ASSERT(link);
1253
1254 vxi->vxi_rsc = rsc;
1255 vxi->ce_mask |= VXLAN_ATTR_RSC;
1256
1257 return 0;
1258 }
1259
1260 /**
1261 * Get Route Short Circuit status to use for VXLAN
1262 * @arg link Link object
1263 *
1264 * @return Status value on success or a negative error code
1265 */
rtnl_link_vxlan_get_rsc(struct rtnl_link * link)1266 int rtnl_link_vxlan_get_rsc(struct rtnl_link *link)
1267 {
1268 struct vxlan_info *vxi = link->l_info;
1269
1270 IS_VXLAN_LINK_ASSERT(link);
1271
1272 if (!(vxi->ce_mask & VXLAN_ATTR_RSC))
1273 return -NLE_AGAIN;
1274
1275 return vxi->vxi_rsc;
1276 }
1277
1278 /**
1279 * Enable Route Short Circuit
1280 * @arg link Link object
1281 *
1282 * @return 0 on success or a negative error code
1283 */
rtnl_link_vxlan_enable_rsc(struct rtnl_link * link)1284 int rtnl_link_vxlan_enable_rsc(struct rtnl_link *link)
1285 {
1286 return rtnl_link_vxlan_set_rsc(link, 1);
1287 }
1288
1289 /**
1290 * Disable Route Short Circuit
1291 * @arg link Link object
1292 *
1293 * @return 0 on success or a negative error code
1294 */
rtnl_link_vxlan_disable_rsc(struct rtnl_link * link)1295 int rtnl_link_vxlan_disable_rsc(struct rtnl_link *link)
1296 {
1297 return rtnl_link_vxlan_set_rsc(link, 0);
1298 }
1299
1300 /**
1301 * Set netlink LLADDR miss notification status to use for VXLAN
1302 * @arg link Link object
1303 * @arg miss Status value
1304 *
1305 * @return 0 on success or a negative error code
1306 */
rtnl_link_vxlan_set_l2miss(struct rtnl_link * link,uint8_t miss)1307 int rtnl_link_vxlan_set_l2miss(struct rtnl_link *link, uint8_t miss)
1308 {
1309 struct vxlan_info *vxi = link->l_info;
1310
1311 IS_VXLAN_LINK_ASSERT(link);
1312
1313 vxi->vxi_l2miss = miss;
1314 vxi->ce_mask |= VXLAN_ATTR_L2MISS;
1315
1316 return 0;
1317 }
1318
1319 /**
1320 * Get netlink LLADDR miss notification status to use for VXLAN
1321 * @arg link Link object
1322 *
1323 * @return Status value on success or a negative error code
1324 */
rtnl_link_vxlan_get_l2miss(struct rtnl_link * link)1325 int rtnl_link_vxlan_get_l2miss(struct rtnl_link *link)
1326 {
1327 struct vxlan_info *vxi = link->l_info;
1328
1329 IS_VXLAN_LINK_ASSERT(link);
1330
1331 if (!(vxi->ce_mask & VXLAN_ATTR_L2MISS))
1332 return -NLE_AGAIN;
1333
1334 return vxi->vxi_l2miss;
1335 }
1336
1337 /**
1338 * Enable netlink LLADDR miss notifications
1339 * @arg link Link object
1340 *
1341 * @return 0 on success or a negative error code
1342 */
rtnl_link_vxlan_enable_l2miss(struct rtnl_link * link)1343 int rtnl_link_vxlan_enable_l2miss(struct rtnl_link *link)
1344 {
1345 return rtnl_link_vxlan_set_l2miss(link, 1);
1346 }
1347
1348 /**
1349 * Disable netlink LLADDR miss notifications
1350 * @arg link Link object
1351 *
1352 * @return 0 on success or a negative error code
1353 */
rtnl_link_vxlan_disable_l2miss(struct rtnl_link * link)1354 int rtnl_link_vxlan_disable_l2miss(struct rtnl_link *link)
1355 {
1356 return rtnl_link_vxlan_set_l2miss(link, 0);
1357 }
1358
1359 /**
1360 * Set netlink IP ADDR miss notification status to use for VXLAN
1361 * @arg link Link object
1362 * @arg miss Status value
1363 *
1364 * @return 0 on success or a negative error code
1365 */
rtnl_link_vxlan_set_l3miss(struct rtnl_link * link,uint8_t miss)1366 int rtnl_link_vxlan_set_l3miss(struct rtnl_link *link, uint8_t miss)
1367 {
1368 struct vxlan_info *vxi = link->l_info;
1369
1370 IS_VXLAN_LINK_ASSERT(link);
1371
1372 vxi->vxi_l3miss = miss;
1373 vxi->ce_mask |= VXLAN_ATTR_L3MISS;
1374
1375 return 0;
1376 }
1377
1378 /**
1379 * Get netlink IP ADDR miss notification status to use for VXLAN
1380 * @arg link Link object
1381 *
1382 * @return Status value on success or a negative error code
1383 */
rtnl_link_vxlan_get_l3miss(struct rtnl_link * link)1384 int rtnl_link_vxlan_get_l3miss(struct rtnl_link *link)
1385 {
1386 struct vxlan_info *vxi = link->l_info;
1387
1388 IS_VXLAN_LINK_ASSERT(link);
1389
1390 if (!(vxi->ce_mask & VXLAN_ATTR_L3MISS))
1391 return -NLE_AGAIN;
1392
1393 return vxi->vxi_l3miss;
1394 }
1395
1396 /**
1397 * Enable netlink IP ADDR miss notifications
1398 * @arg link Link object
1399 *
1400 * @return 0 on success or a negative error code
1401 */
rtnl_link_vxlan_enable_l3miss(struct rtnl_link * link)1402 int rtnl_link_vxlan_enable_l3miss(struct rtnl_link *link)
1403 {
1404 return rtnl_link_vxlan_set_l3miss(link, 1);
1405 }
1406
1407 /**
1408 * Disable netlink IP ADDR miss notifications
1409 * @arg link Link object
1410 *
1411 * @return 0 on success or a negative error code
1412 */
rtnl_link_vxlan_disable_l3miss(struct rtnl_link * link)1413 int rtnl_link_vxlan_disable_l3miss(struct rtnl_link *link)
1414 {
1415 return rtnl_link_vxlan_set_l3miss(link, 0);
1416 }
1417
1418 /**
1419 * Set UDP destination port to use for VXLAN
1420 * @arg link Link object
1421 * @arg port Destination port
1422 *
1423 * @return 0 on success or a negative error code
1424 */
rtnl_link_vxlan_set_port(struct rtnl_link * link,uint32_t port)1425 int rtnl_link_vxlan_set_port(struct rtnl_link *link, uint32_t port)
1426 {
1427 struct vxlan_info *vxi = link->l_info;
1428
1429 IS_VXLAN_LINK_ASSERT(link);
1430
1431 vxi->vxi_port = htons(port);
1432 vxi->ce_mask |= VXLAN_ATTR_PORT;
1433
1434 return 0;
1435 }
1436
1437 /**
1438 * Get UDP destination port to use for VXLAN
1439 * @arg link Link object
1440 * @arg port Pointer to store destination port
1441 *
1442 * @return 0 on success or a negative error code
1443 */
rtnl_link_vxlan_get_port(struct rtnl_link * link,uint32_t * port)1444 int rtnl_link_vxlan_get_port(struct rtnl_link *link, uint32_t *port)
1445 {
1446 struct vxlan_info *vxi = link->l_info;
1447
1448 IS_VXLAN_LINK_ASSERT(link);
1449
1450 if (!port)
1451 return -NLE_INVAL;
1452
1453 if (!(vxi->ce_mask & VXLAN_ATTR_PORT))
1454 return -NLE_NOATTR;
1455
1456 *port = ntohs(vxi->vxi_port);
1457
1458 return 0;
1459 }
1460
1461 /**
1462 * Set UDP checksum status to use for VXLAN
1463 * @arg link Link object
1464 * @arg csum Status value
1465 *
1466 * @return 0 on success or a negative error code
1467 */
rtnl_link_vxlan_set_udp_csum(struct rtnl_link * link,uint8_t csum)1468 int rtnl_link_vxlan_set_udp_csum(struct rtnl_link *link, uint8_t csum)
1469 {
1470 struct vxlan_info *vxi = link->l_info;
1471
1472 IS_VXLAN_LINK_ASSERT(link);
1473
1474 vxi->vxi_udp_csum = csum;
1475 vxi->ce_mask |= VXLAN_ATTR_UDP_CSUM;
1476
1477 return 0;
1478 }
1479
1480 /**
1481 * Get UDP checksum status to use for VXLAN
1482 * @arg link Link object
1483 *
1484 * @return Status value on success or a negative error code
1485 */
rtnl_link_vxlan_get_udp_csum(struct rtnl_link * link)1486 int rtnl_link_vxlan_get_udp_csum(struct rtnl_link *link)
1487 {
1488 struct vxlan_info *vxi = link->l_info;
1489
1490 IS_VXLAN_LINK_ASSERT(link);
1491
1492 if (!(vxi->ce_mask & VXLAN_ATTR_UDP_CSUM))
1493 return -NLE_NOATTR;
1494
1495 return vxi->vxi_udp_csum;
1496 }
1497
1498 /**
1499 * Set skip UDP checksum transmitted over IPv6 status to use for VXLAN
1500 * @arg link Link object
1501 * @arg csum Status value
1502 *
1503 * @return 0 on success or a negative error code
1504 */
rtnl_link_vxlan_set_udp_zero_csum6_tx(struct rtnl_link * link,uint8_t csum)1505 int rtnl_link_vxlan_set_udp_zero_csum6_tx(struct rtnl_link *link, uint8_t csum)
1506 {
1507 struct vxlan_info *vxi = link->l_info;
1508
1509 IS_VXLAN_LINK_ASSERT(link);
1510
1511 vxi->vxi_udp_zero_csum6_tx = csum;
1512 vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_TX;
1513
1514 return 0;
1515 }
1516
1517 /**
1518 * Get skip UDP checksum transmitted over IPv6 status to use for VXLAN
1519 * @arg link Link object
1520 *
1521 * @return Status value on success or a negative error code
1522 */
rtnl_link_vxlan_get_udp_zero_csum6_tx(struct rtnl_link * link)1523 int rtnl_link_vxlan_get_udp_zero_csum6_tx(struct rtnl_link *link)
1524 {
1525 struct vxlan_info *vxi = link->l_info;
1526
1527 IS_VXLAN_LINK_ASSERT(link);
1528
1529 if (!(vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_TX))
1530 return -NLE_NOATTR;
1531
1532 return vxi->vxi_udp_zero_csum6_tx;
1533 }
1534
1535 /**
1536 * Set skip UDP checksum received over IPv6 status to use for VXLAN
1537 * @arg link Link object
1538 * @arg csum Status value
1539 *
1540 * @return 0 on success or a negative error code
1541 */
rtnl_link_vxlan_set_udp_zero_csum6_rx(struct rtnl_link * link,uint8_t csum)1542 int rtnl_link_vxlan_set_udp_zero_csum6_rx(struct rtnl_link *link, uint8_t csum)
1543 {
1544 struct vxlan_info *vxi = link->l_info;
1545
1546 IS_VXLAN_LINK_ASSERT(link);
1547
1548 vxi->vxi_udp_zero_csum6_rx = csum;
1549 vxi->ce_mask |= VXLAN_ATTR_UDP_ZERO_CSUM6_RX;
1550
1551 return 0;
1552 }
1553
1554 /**
1555 * Get skip UDP checksum received over IPv6 status to use for VXLAN
1556 * @arg link Link object
1557 *
1558 * @return Status value on success or a negative error code
1559 */
rtnl_link_vxlan_get_udp_zero_csum6_rx(struct rtnl_link * link)1560 int rtnl_link_vxlan_get_udp_zero_csum6_rx(struct rtnl_link *link)
1561 {
1562 struct vxlan_info *vxi = link->l_info;
1563
1564 IS_VXLAN_LINK_ASSERT(link);
1565
1566 if (!(vxi->ce_mask & VXLAN_ATTR_UDP_ZERO_CSUM6_RX))
1567 return -NLE_NOATTR;
1568
1569 return vxi->vxi_udp_zero_csum6_rx;
1570 }
1571
1572 /**
1573 * Set remote offload transmit checksum status to use for VXLAN
1574 * @arg link Link object
1575 * @arg csum Status value
1576 *
1577 * @return 0 on success or a negative error code
1578 */
rtnl_link_vxlan_set_remcsum_tx(struct rtnl_link * link,uint8_t csum)1579 int rtnl_link_vxlan_set_remcsum_tx(struct rtnl_link *link, uint8_t csum)
1580 {
1581 struct vxlan_info *vxi = link->l_info;
1582
1583 IS_VXLAN_LINK_ASSERT(link);
1584
1585 vxi->vxi_remcsum_tx = csum;
1586 vxi->ce_mask |= VXLAN_ATTR_REMCSUM_TX;
1587
1588 return 0;
1589 }
1590
1591 /**
1592 * Get remote offload transmit checksum status to use for VXLAN
1593 * @arg link Link object
1594 *
1595 * @return Status value on success or a negative error code
1596 */
rtnl_link_vxlan_get_remcsum_tx(struct rtnl_link * link)1597 int rtnl_link_vxlan_get_remcsum_tx(struct rtnl_link *link)
1598 {
1599 struct vxlan_info *vxi = link->l_info;
1600
1601 IS_VXLAN_LINK_ASSERT(link);
1602
1603 if (!(vxi->ce_mask & VXLAN_ATTR_REMCSUM_TX))
1604 return -NLE_NOATTR;
1605
1606 return vxi->vxi_remcsum_tx;
1607 }
1608
1609 /**
1610 * Set remote offload receive checksum status to use for VXLAN
1611 * @arg link Link object
1612 * @arg csum Status value
1613 *
1614 * @return 0 on success or a negative error code
1615 */
rtnl_link_vxlan_set_remcsum_rx(struct rtnl_link * link,uint8_t csum)1616 int rtnl_link_vxlan_set_remcsum_rx(struct rtnl_link *link, uint8_t csum)
1617 {
1618 struct vxlan_info *vxi = link->l_info;
1619
1620 IS_VXLAN_LINK_ASSERT(link);
1621
1622 vxi->vxi_remcsum_rx = csum;
1623 vxi->ce_mask |= VXLAN_ATTR_REMCSUM_RX;
1624
1625 return 0;
1626 }
1627
1628 /**
1629 * Get remote offload receive checksum status to use for VXLAN
1630 * @arg link Link object
1631 *
1632 * @return Status value on success or a negative error code
1633 */
rtnl_link_vxlan_get_remcsum_rx(struct rtnl_link * link)1634 int rtnl_link_vxlan_get_remcsum_rx(struct rtnl_link *link)
1635 {
1636 struct vxlan_info *vxi = link->l_info;
1637
1638 IS_VXLAN_LINK_ASSERT(link);
1639
1640 if (!(vxi->ce_mask & VXLAN_ATTR_REMCSUM_RX))
1641 return -NLE_NOATTR;
1642
1643 return vxi->vxi_remcsum_rx;
1644 }
1645
1646 /**
1647 * Set collect metadata status to use for VXLAN
1648 * @arg link Link object
1649 * @arg collect Status value
1650 *
1651 * @return 0 on success or a negative error code
1652 */
rtnl_link_vxlan_set_collect_metadata(struct rtnl_link * link,uint8_t collect)1653 int rtnl_link_vxlan_set_collect_metadata(struct rtnl_link *link, uint8_t collect)
1654 {
1655 struct vxlan_info *vxi = link->l_info;
1656
1657 IS_VXLAN_LINK_ASSERT(link);
1658
1659 vxi->vxi_collect_metadata = collect;
1660 vxi->ce_mask |= VXLAN_ATTR_COLLECT_METADATA;
1661
1662 return 0;
1663 }
1664
1665 /**
1666 * Get collect metadata status to use for VXLAN
1667 * @arg link Link object
1668 *
1669 * @return Status value on success or a negative error code
1670 */
rtnl_link_vxlan_get_collect_metadata(struct rtnl_link * link)1671 int rtnl_link_vxlan_get_collect_metadata(struct rtnl_link *link)
1672 {
1673 struct vxlan_info *vxi = link->l_info;
1674
1675 IS_VXLAN_LINK_ASSERT(link);
1676
1677 if (!(vxi->ce_mask & VXLAN_ATTR_COLLECT_METADATA))
1678 return -NLE_NOATTR;
1679
1680 return vxi->vxi_collect_metadata;
1681 }
1682
1683 /**
1684 * Set flow label to use for VXLAN
1685 * @arg link Link object
1686 * @arg label Destination label
1687 *
1688 * @return 0 on success or a negative error code
1689 */
rtnl_link_vxlan_set_label(struct rtnl_link * link,uint32_t label)1690 int rtnl_link_vxlan_set_label(struct rtnl_link *link, uint32_t label)
1691 {
1692 struct vxlan_info *vxi = link->l_info;
1693
1694 IS_VXLAN_LINK_ASSERT(link);
1695
1696 vxi->vxi_label = htonl(label);
1697 vxi->ce_mask |= VXLAN_ATTR_LABEL;
1698
1699 return 0;
1700 }
1701
1702 /**
1703 * Get flow label to use for VXLAN
1704 * @arg link Link object
1705 * @arg label Pointer to store destination label
1706 *
1707 * @return 0 on success or a negative error code
1708 */
rtnl_link_vxlan_get_label(struct rtnl_link * link,uint32_t * label)1709 int rtnl_link_vxlan_get_label(struct rtnl_link *link, uint32_t *label)
1710 {
1711 struct vxlan_info *vxi = link->l_info;
1712
1713 IS_VXLAN_LINK_ASSERT(link);
1714
1715 if (!label)
1716 return -NLE_INVAL;
1717
1718 if (!(vxi->ce_mask & VXLAN_ATTR_LABEL))
1719 return -NLE_NOATTR;
1720
1721 *label = ntohl(vxi->vxi_label);
1722
1723 return 0;
1724 }
1725
1726 /**
1727 * Set VXLAN flags RTNL_LINK_VXLAN_F_*
1728 * @arg link Link object
1729 * @flags Which flags to set
1730 * @arg enable Boolean enabling or disabling flag
1731 *
1732 * @return 0 on success or a negative error code
1733 */
rtnl_link_vxlan_set_flags(struct rtnl_link * link,uint32_t flags,int enable)1734 int rtnl_link_vxlan_set_flags(struct rtnl_link *link, uint32_t flags, int enable)
1735 {
1736 struct vxlan_info *vxi = link->l_info;
1737
1738 IS_VXLAN_LINK_ASSERT(link);
1739
1740 if (flags & ~(RTNL_LINK_VXLAN_F_GBP | RTNL_LINK_VXLAN_F_GPE | RTNL_LINK_VXLAN_F_REMCSUM_NOPARTIAL))
1741 return -NLE_INVAL;
1742
1743 if (enable)
1744 vxi->vxi_flags |= flags;
1745 else
1746 vxi->vxi_flags &= ~flags;
1747
1748 return 0;
1749 }
1750
1751 /**
1752 * Get VXLAN flags RTNL_LINK_VXLAN_F_*
1753 * @arg link Link object
1754 * @arg out_flags Output value for flags. Must be present.
1755 *
1756 * @return Zero on success or a negative error code
1757 */
rtnl_link_vxlan_get_flags(struct rtnl_link * link,uint32_t * out_flags)1758 int rtnl_link_vxlan_get_flags(struct rtnl_link *link, uint32_t *out_flags)
1759 {
1760 struct vxlan_info *vxi = link->l_info;
1761
1762 IS_VXLAN_LINK_ASSERT(link);
1763
1764 *out_flags = vxi->vxi_flags;
1765 return 0;
1766 }
1767
1768 /** @} */
1769
vxlan_init(void)1770 static void __init vxlan_init(void)
1771 {
1772 rtnl_link_register_info(&vxlan_info_ops);
1773 }
1774
vxlan_exit(void)1775 static void __exit vxlan_exit(void)
1776 {
1777 rtnl_link_unregister_info(&vxlan_info_ops);
1778 }
1779
1780 /** @} */
1781