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