1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2018 Wang Jian <[email protected]>
4 */
5
6 /**
7 * @ingroup link
8 * @defgroup geneve Geneve
9 * Generic Network Virtualization Encapsulation
10 *
11 * @details
12 * \b Link Type Name: "geneve"
13 *
14 * @route_doc{link_geneve, Geneve Documentation}
15 *
16 * @{
17 */
18 #include "nl-default.h"
19
20 #include <netlink/netlink.h>
21 #include <netlink/utils.h>
22 #include <netlink/object.h>
23 #include <netlink/route/rtnl.h>
24 #include <netlink/route/link/geneve.h>
25
26 #include "nl-route.h"
27 #include "link-api.h"
28
29 /** @cond SKIP */
30 #define GENEVE_ATTR_ID (1<<0)
31 #define GENEVE_ATTR_REMOTE (1<<1)
32 #define GENEVE_ATTR_REMOTE6 (1<<2)
33 #define GENEVE_ATTR_TTL (1<<3)
34 #define GENEVE_ATTR_TOS (1<<4)
35 #define GENEVE_ATTR_LABEL (1<<5)
36 #define GENEVE_ATTR_PORT (1<<6)
37 #define GENEVE_ATTR_FLAGS (1<<7)
38 #define GENEVE_ATTR_UDP_CSUM (1<<8)
39 #define GENEVE_ATTR_UDP_ZERO_CSUM6_TX (1<<9)
40 #define GENEVE_ATTR_UDP_ZERO_CSUM6_RX (1<<10)
41
42 struct geneve_info
43 {
44 uint32_t id;
45 uint32_t remote;
46 struct in6_addr remote6;
47 uint8_t ttl;
48 uint8_t tos;
49 uint32_t label;
50 uint16_t port;
51 uint8_t flags;
52 uint8_t udp_csum;
53 uint8_t udp_zero_csum6_tx;
54 uint8_t udp_zero_csum6_rx;
55 uint32_t mask;
56 };
57
58 /** @endcond */
59
60 static struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
61 [IFLA_GENEVE_ID] = { .type = NLA_U32 },
62 [IFLA_GENEVE_REMOTE] = { .minlen = sizeof(uint32_t) },
63 [IFLA_GENEVE_REMOTE6] = { .minlen = sizeof(struct in6_addr) },
64 [IFLA_GENEVE_TTL] = { .type = NLA_U8 },
65 [IFLA_GENEVE_TOS] = { .type = NLA_U8 },
66 [IFLA_GENEVE_LABEL] = { .type = NLA_U32 },
67 [IFLA_GENEVE_PORT] = { .type = NLA_U16 },
68 [IFLA_GENEVE_COLLECT_METADATA] = { .type = NLA_FLAG },
69 [IFLA_GENEVE_UDP_CSUM] = { .type = NLA_U8 },
70 [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
71 [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
72 };
73
geneve_alloc(struct rtnl_link * link)74 static int geneve_alloc(struct rtnl_link *link)
75 {
76 struct geneve_info *geneve;
77
78 if (link->l_info)
79 memset(link->l_info, 0, sizeof(*geneve));
80 else {
81 if ((geneve = calloc(1, sizeof(*geneve))) == NULL)
82 return -NLE_NOMEM;
83 link->l_info = geneve;
84 }
85
86 return 0;
87 }
88
geneve_parse(struct rtnl_link * link,struct nlattr * data,struct nlattr * xstats)89 static int geneve_parse(struct rtnl_link *link, struct nlattr *data,
90 struct nlattr *xstats)
91 {
92 struct nlattr *tb[IFLA_GENEVE_MAX + 1];
93 struct geneve_info *geneve;
94 int err = 0;
95
96 NL_DBG(3, "Parsing Geneve link info\n");
97
98 err = nla_parse_nested(tb, IFLA_GENEVE_MAX, data, geneve_policy);
99 if (err < 0)
100 return err;
101
102 err = geneve_alloc(link);
103 if (err < 0)
104 return err;
105
106 geneve = link->l_info;
107
108 if (tb[IFLA_GENEVE_ID]) {
109 geneve->id = nla_get_u32(tb[IFLA_GENEVE_ID]);
110 geneve->mask |= GENEVE_ATTR_ID;
111 }
112
113 if (tb[IFLA_GENEVE_REMOTE]) {
114 nla_memcpy(&geneve->remote, tb[IFLA_GENEVE_REMOTE],
115 sizeof(geneve->remote));
116 geneve->mask |= GENEVE_ATTR_REMOTE;
117 geneve->mask &= ~GENEVE_ATTR_REMOTE6;
118 }
119 if (tb[IFLA_GENEVE_REMOTE6]) {
120 nla_memcpy(&geneve->remote6, tb[IFLA_GENEVE_REMOTE6],
121 sizeof(geneve->remote6));
122 geneve->mask |= GENEVE_ATTR_REMOTE6;
123 geneve->mask &= ~GENEVE_ATTR_REMOTE;
124 }
125
126 if (tb[IFLA_GENEVE_TTL]) {
127 geneve->ttl = nla_get_u8(tb[IFLA_GENEVE_TTL]);
128 geneve->mask |= GENEVE_ATTR_TTL;
129 }
130
131 if (tb[IFLA_GENEVE_TOS]) {
132 geneve->tos = nla_get_u8(tb[IFLA_GENEVE_TOS]);
133 geneve->mask |= GENEVE_ATTR_TOS;
134 }
135
136 if (tb[IFLA_GENEVE_LABEL]) {
137 geneve->label = nla_get_u32(tb[IFLA_GENEVE_LABEL]);
138 geneve->mask |= GENEVE_ATTR_LABEL;
139 }
140
141 if (tb[IFLA_GENEVE_PORT]) {
142 geneve->port = nla_get_u16(tb[IFLA_GENEVE_PORT]);
143 geneve->mask |= GENEVE_ATTR_PORT;
144 }
145
146 if (tb[IFLA_GENEVE_COLLECT_METADATA])
147 geneve->flags |= RTNL_LINK_GENEVE_F_COLLECT_METADATA;
148
149 if (tb[IFLA_GENEVE_UDP_CSUM]) {
150 geneve->udp_csum = nla_get_u8(tb[IFLA_GENEVE_UDP_CSUM]);
151 geneve->mask |= GENEVE_ATTR_UDP_CSUM;
152 }
153
154 if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]) {
155 geneve->udp_zero_csum6_tx = nla_get_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]);
156 geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_TX;
157 }
158
159 if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]) {
160 geneve->udp_zero_csum6_rx = nla_get_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]);
161 geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_RX;
162 }
163
164 return err;
165 }
166
geneve_free(struct rtnl_link * link)167 static void geneve_free(struct rtnl_link *link)
168 {
169 struct geneve_info *geneve = link->l_info;
170
171 free(geneve);
172 link->l_info = NULL;
173 }
174
geneve_dump_line(struct rtnl_link * link,struct nl_dump_params * p)175 static void geneve_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
176 {
177 struct geneve_info *geneve = link->l_info;
178
179 nl_dump(p, "geneve-id %u", geneve->id);
180 }
181
geneve_dump_details(struct rtnl_link * link,struct nl_dump_params * p)182 static void geneve_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
183 {
184 struct geneve_info *geneve = link->l_info;
185 char addr[INET6_ADDRSTRLEN];
186
187 nl_dump_line(p, " geneve-id %u\n", geneve->id);
188
189 if (geneve->mask & GENEVE_ATTR_REMOTE) {
190 nl_dump(p, " remote ");
191 nl_dump_line(p, "%s\n",
192 _nl_inet_ntop(AF_INET, &geneve->remote, addr));
193 } else if (geneve->mask & GENEVE_ATTR_REMOTE6) {
194 nl_dump(p, " remote ");
195 nl_dump_line(p, "%s\n",
196 _nl_inet_ntop(AF_INET6, &geneve->remote6, addr));
197 }
198
199 if (geneve->mask & GENEVE_ATTR_TTL) {
200 nl_dump(p, " ttl ");
201 nl_dump_line(p, "%u\n", geneve->ttl);
202 }
203
204 if (geneve->mask & GENEVE_ATTR_TOS) {
205 nl_dump(p, " tos ");
206 nl_dump_line(p, "%u\n", geneve->tos);
207 }
208
209 if (geneve->mask & GENEVE_ATTR_PORT) {
210 nl_dump(p, " port ");
211 nl_dump_line(p, "%u\n", ntohs(geneve->port));
212 }
213
214 if (geneve->mask & GENEVE_ATTR_LABEL) {
215 nl_dump(p, " label ");
216 nl_dump_line(p, "%u\n", ntohl(geneve->label));
217 }
218
219 if (geneve->mask & GENEVE_ATTR_UDP_CSUM) {
220 nl_dump(p, " UDP checksum ");
221 if (geneve->udp_csum)
222 nl_dump_line(p, "enabled (%#x)\n", geneve->udp_csum);
223 else
224 nl_dump_line(p, "disabled\n");
225 }
226
227 if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX) {
228 nl_dump(p, " udp-zero-csum6-tx ");
229 if (geneve->udp_zero_csum6_tx)
230 nl_dump_line(p, "enabled (%#x)\n", geneve->udp_zero_csum6_tx);
231 else
232 nl_dump_line(p, "disabled\n");
233 }
234
235 if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX) {
236 nl_dump(p, " udp-zero-csum6-rx ");
237 if (geneve->udp_zero_csum6_rx)
238 nl_dump_line(p, "enabled (%#x)\n", geneve->udp_zero_csum6_rx);
239 else
240 nl_dump_line(p, "disabled\n");
241 }
242
243 if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA)
244 nl_dump(p, " collect-metadata\n");
245 }
246
geneve_clone(struct rtnl_link * dst,struct rtnl_link * src)247 static int geneve_clone(struct rtnl_link *dst, struct rtnl_link *src)
248 {
249 struct geneve_info *gdst, *gsrc;
250 int err;
251
252 gsrc = src->l_info;
253 dst->l_info = NULL;
254 err = rtnl_link_set_type(dst, "geneve");
255 if (err < 0)
256 return err;
257
258 gdst = dst->l_info;
259
260 if (!gsrc || !gdst)
261 return -NLE_NOMEM;
262
263 memcpy(gdst, gsrc, sizeof(struct geneve_info));
264
265 return 0;
266 }
267
geneve_put_attrs(struct nl_msg * msg,struct rtnl_link * link)268 static int geneve_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
269 {
270 struct geneve_info *geneve = link->l_info;
271 struct nlattr *data;
272
273 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
274 return -NLE_MSGSIZE;
275
276 if (geneve->mask & GENEVE_ATTR_ID)
277 NLA_PUT_U32(msg, IFLA_GENEVE_ID, geneve->id);
278
279 if (geneve->mask & GENEVE_ATTR_REMOTE)
280 NLA_PUT(msg, IFLA_GENEVE_REMOTE,
281 sizeof(geneve->remote), &geneve->remote);
282
283 if (geneve->mask & GENEVE_ATTR_REMOTE6)
284 NLA_PUT(msg, IFLA_GENEVE_REMOTE6,
285 sizeof(geneve->remote6), &geneve->remote6);
286
287 if (geneve->mask & GENEVE_ATTR_TTL)
288 NLA_PUT_U8(msg, IFLA_GENEVE_TTL, geneve->ttl);
289
290 if (geneve->mask & GENEVE_ATTR_TOS)
291 NLA_PUT_U8(msg, IFLA_GENEVE_TOS, geneve->tos);
292
293 if (geneve->mask & GENEVE_ATTR_LABEL)
294 NLA_PUT_U32(msg, IFLA_GENEVE_LABEL, geneve->label);
295
296 if (geneve->mask & GENEVE_ATTR_PORT)
297 NLA_PUT_U32(msg, IFLA_GENEVE_PORT, geneve->port);
298
299 if (geneve->mask & GENEVE_ATTR_UDP_CSUM)
300 NLA_PUT_U8(msg, IFLA_GENEVE_UDP_CSUM, geneve->udp_csum);
301
302 if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX)
303 NLA_PUT_U8(msg, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, geneve->udp_zero_csum6_tx);
304
305 if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX)
306 NLA_PUT_U8(msg, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, geneve->udp_zero_csum6_rx);
307
308 if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA)
309 NLA_PUT_FLAG(msg, IFLA_GENEVE_COLLECT_METADATA);
310
311 nla_nest_end(msg, data);
312
313 nla_put_failure:
314
315 return 0;
316 }
317
318 static struct rtnl_link_info_ops geneve_info_ops = {
319 .io_name = "geneve",
320 .io_alloc = geneve_alloc,
321 .io_parse = geneve_parse,
322 .io_dump = {
323 [NL_DUMP_LINE] = geneve_dump_line,
324 [NL_DUMP_DETAILS] = geneve_dump_details,
325 },
326 .io_clone = geneve_clone,
327 .io_put_attrs = geneve_put_attrs,
328 .io_free = geneve_free,
329 };
330
331
332 /** @cond SKIP */
333 #define IS_GENEVE_LINK_ASSERT(link) \
334 if ((link)->l_info_ops != &geneve_info_ops) { \
335 APPBUG("Link is not a geneve link. set type \"geneve\" first."); \
336 return -NLE_OPNOTSUPP; \
337 }
338 /** @endcond */
339
340 /**
341 * @name Geneve Object
342 * @{
343 */
344
345 /**
346 * Allocate link object of type Geneve
347 *
348 * @return Allocated link object or NULL.
349 */
rtnl_link_geneve_alloc(void)350 struct rtnl_link *rtnl_link_geneve_alloc(void)
351 {
352 struct rtnl_link *link;
353
354 if (!(link = rtnl_link_alloc()))
355 return NULL;
356
357 if (rtnl_link_set_type(link, "geneve") < 0) {
358 rtnl_link_put(link);
359 return NULL;
360 }
361
362 return link;
363 }
364
365 /**
366 * Check if link is a Geneve link
367 * @arg link Link object
368 *
369 * @return True if link is a Geneve link, otherwisee false is returned.
370 */
rtnl_link_is_geneve(struct rtnl_link * link)371 int rtnl_link_is_geneve(struct rtnl_link *link)
372 {
373 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "geneve");
374 }
375
376 /**
377 * Set Geneve Network Indentifier
378 * @arg link Link object
379 * @arg id Geneve network identifier
380 *
381 * @return 0 on success or a negative error code
382 */
rtnl_link_geneve_set_id(struct rtnl_link * link,uint32_t id)383 int rtnl_link_geneve_set_id(struct rtnl_link *link, uint32_t id)
384 {
385 struct geneve_info *geneve = link->l_info;
386
387 IS_GENEVE_LINK_ASSERT(link);
388
389 if (id > RTNL_GENEVE_ID_MAX)
390 return -NLE_INVAL;
391
392 geneve->id = id;
393 geneve->mask |= GENEVE_ATTR_ID;
394
395 return 0;
396 }
397
398 /**
399 * Get Geneve Network Identifier
400 * @arg link Link object
401 * @arg id Pointer to store network identifier
402 *
403 * @return 0 on success or a negative error code
404 */
rtnl_link_geneve_get_id(struct rtnl_link * link,uint32_t * id)405 int rtnl_link_geneve_get_id(struct rtnl_link *link, uint32_t *id)
406 {
407 struct geneve_info *geneve = link->l_info;
408
409 IS_GENEVE_LINK_ASSERT(link);
410
411 if (!id)
412 return -NLE_INVAL;
413
414 if (geneve->mask & GENEVE_ATTR_ID)
415 *id = geneve->id;
416 else
417 return -NLE_AGAIN;
418
419 return 0;
420 }
421
422 /**
423 * Set Geneve unicast destination IP address
424 * @arg link Link object
425 * @arg addr The unicast destination IP address
426 *
427 * @return 0 on success or a negative error code
428 */
rtnl_link_geneve_set_remote(struct rtnl_link * link,struct nl_addr * addr)429 int rtnl_link_geneve_set_remote(struct rtnl_link *link, struct nl_addr *addr)
430 {
431 struct geneve_info *geneve = link->l_info;
432
433 IS_GENEVE_LINK_ASSERT(link);
434
435 if ((nl_addr_get_family(addr) == AF_INET) &&
436 (nl_addr_get_len(addr) == sizeof(geneve->remote))) {
437 memcpy(&geneve->remote, nl_addr_get_binary_addr(addr),
438 sizeof(geneve->remote));
439 geneve->mask |= GENEVE_ATTR_REMOTE;
440 geneve->mask &= ~GENEVE_ATTR_REMOTE6;
441 } else if ((nl_addr_get_family(addr) == AF_INET6) &&
442 (nl_addr_get_len(addr) == sizeof(geneve->remote6))) {
443 memcpy(&geneve->remote6, nl_addr_get_binary_addr(addr),
444 sizeof(geneve->remote6));
445 geneve->mask |= GENEVE_ATTR_REMOTE6;
446 geneve->mask &= ~GENEVE_ATTR_REMOTE;
447 } else
448 return -NLE_INVAL;
449
450 return 0;
451 }
452
453 /**
454 * Get Geneve unicast destination IP address
455 * @arg link Link object
456 * @arg addr Pointer to store unicast destination IP addree
457 *
458 * @return 0 on success or a a negative error code
459 */
rtnl_link_geneve_get_remote(struct rtnl_link * link,struct nl_addr ** addr)460 int rtnl_link_geneve_get_remote(struct rtnl_link *link, struct nl_addr **addr)
461 {
462 struct geneve_info *geneve = link->l_info;
463
464 IS_GENEVE_LINK_ASSERT(link);
465
466 if (!addr)
467 return -NLE_INVAL;
468
469 if (geneve->mask & GENEVE_ATTR_REMOTE)
470 *addr = nl_addr_build(AF_INET, &geneve->remote, sizeof(geneve->remote));
471 else if (geneve->mask & GENEVE_ATTR_REMOTE6)
472 *addr = nl_addr_build(AF_INET6, &geneve->remote6, sizeof(geneve->remote6));
473 else
474 return -NLE_AGAIN;
475
476 return 0;
477 }
478
479 /**
480 * Set IP TTL value to use for Geneve
481 * @arg link Link object
482 * @arg ttl TTL value
483 *
484 * @return 0 on success or a negative error code
485 */
rtnl_link_geneve_set_ttl(struct rtnl_link * link,uint8_t ttl)486 int rtnl_link_geneve_set_ttl(struct rtnl_link *link, uint8_t ttl)
487 {
488 struct geneve_info *geneve = link->l_info;
489
490 IS_GENEVE_LINK_ASSERT(link);
491
492 geneve->ttl = ttl;
493 geneve->mask |= GENEVE_ATTR_TTL;
494
495 return 0;
496 }
497
498 /**
499 * Get IP TTL value to use for Geneve
500 * @arg link Link object
501 *
502 * @return TTL value on success or a negative error code
503 */
rtnl_link_geneve_get_ttl(struct rtnl_link * link)504 int rtnl_link_geneve_get_ttl(struct rtnl_link *link)
505 {
506 struct geneve_info *geneve = link->l_info;
507
508 IS_GENEVE_LINK_ASSERT(link);
509
510 if (!(geneve->mask & GENEVE_ATTR_TTL))
511 return -NLE_AGAIN;
512
513 return geneve->ttl;
514 }
515
516 /**
517 * Set IP ToS value to use for Geneve
518 * @arg link Link object
519 * @arg tos ToS value
520 *
521 * @return 0 on success or a negative error code
522 */
rtnl_link_geneve_set_tos(struct rtnl_link * link,uint8_t tos)523 int rtnl_link_geneve_set_tos(struct rtnl_link *link, uint8_t tos)
524 {
525 struct geneve_info *geneve = link->l_info;
526
527 IS_GENEVE_LINK_ASSERT(link);
528
529 geneve->tos = tos;
530 geneve->mask |= GENEVE_ATTR_TOS;
531
532 return 0;
533 }
534
535 /**
536 * Get IP ToS value to use for Geneve
537 * @arg link Link object
538 *
539 * @return ToS value on success or a negative error code
540 */
rtnl_link_geneve_get_tos(struct rtnl_link * link)541 int rtnl_link_geneve_get_tos(struct rtnl_link *link)
542 {
543 struct geneve_info *geneve = link->l_info;
544
545 IS_GENEVE_LINK_ASSERT(link);
546
547 if (!(geneve->mask & GENEVE_ATTR_TOS))
548 return -NLE_AGAIN;
549
550 return geneve->tos;
551 }
552
553 /**
554 * Set UDP destination port to use for Geneve
555 * @arg link Link object
556 * @arg port Destination port
557 *
558 * @return 0 on success or a negative error code
559 */
560
rtnl_link_geneve_set_port(struct rtnl_link * link,uint32_t port)561 int rtnl_link_geneve_set_port(struct rtnl_link *link, uint32_t port)
562 {
563 struct geneve_info *geneve = link->l_info;
564
565 IS_GENEVE_LINK_ASSERT(link);
566
567 geneve->port = htons(port);
568 geneve->mask |= GENEVE_ATTR_PORT;
569
570 return 0;
571 }
572
573 /**
574 * Get UDP destination port to use for Geneve
575 * @arg link Link object
576 * @arg port Pointer to store destination port
577 *
578 * @return 0 on success or a negative error code
579 */
rtnl_link_geneve_get_port(struct rtnl_link * link,uint32_t * port)580 int rtnl_link_geneve_get_port(struct rtnl_link *link, uint32_t *port)
581 {
582 struct geneve_info *geneve = link->l_info;
583
584 IS_GENEVE_LINK_ASSERT(link);
585
586 if (!port)
587 return -NLE_INVAL;
588
589 if (!(geneve->mask & GENEVE_ATTR_PORT))
590 return -NLE_NOATTR;
591
592 *port = ntohs(geneve->port);
593
594 return 0;
595 }
596
597 /**
598 * Set flow label to use for Geneve
599 * @arg link Link object
600 * @arg label Destination label
601 *
602 * @return 0 on success or a negative error code
603 */
rtnl_link_geneve_set_label(struct rtnl_link * link,uint32_t label)604 int rtnl_link_geneve_set_label(struct rtnl_link *link, uint32_t label)
605 {
606 struct geneve_info *geneve = link->l_info;
607
608 IS_GENEVE_LINK_ASSERT(link);
609
610 geneve->label = htonl(label);
611 geneve->mask |= GENEVE_ATTR_LABEL;
612
613 return 0;
614 }
615
616 /**
617 * Get flow label to use for Geneve
618 * @arg link Link object
619 * @arg label Pointer to store destination label
620 *
621 * @return 0 on success or a negative error code
622 */
rtnl_link_geneve_get_label(struct rtnl_link * link,uint32_t * label)623 int rtnl_link_geneve_get_label(struct rtnl_link *link, uint32_t *label)
624 {
625 struct geneve_info *geneve = link->l_info;
626
627 IS_GENEVE_LINK_ASSERT(link);
628
629 if (!label)
630 return -NLE_INVAL;
631 if (!(geneve->mask & GENEVE_ATTR_LABEL))
632 return -NLE_NOATTR;
633
634 *label = ntohl(geneve->label);
635
636 return 0;
637 }
638
639 /**
640 * Set UDP checksum status to use for Geneve
641 * @arg link Link object
642 * @arg csum Status value
643 *
644 * @return 0 on success or a negative error code
645 */
rtnl_link_geneve_set_udp_csum(struct rtnl_link * link,uint8_t csum)646 int rtnl_link_geneve_set_udp_csum(struct rtnl_link *link, uint8_t csum)
647 {
648 struct geneve_info *geneve = link->l_info;
649
650 IS_GENEVE_LINK_ASSERT(link);
651
652 geneve->udp_csum = csum;
653 geneve->mask |= GENEVE_ATTR_UDP_CSUM;
654
655 return 0;
656 }
657
658 /**
659 * Get UDP checksum status to use for Geneve
660 * @arg link Link object
661 *
662 * @return status value on success or a negative error code
663 */
rtnl_link_geneve_get_udp_csum(struct rtnl_link * link)664 int rtnl_link_geneve_get_udp_csum(struct rtnl_link *link)
665 {
666 struct geneve_info *geneve = link->l_info;
667
668 IS_GENEVE_LINK_ASSERT(link);
669
670 if (!(geneve->mask & GENEVE_ATTR_UDP_CSUM))
671 return -NLE_NOATTR;
672
673 return geneve->udp_csum;
674 }
675
676 /**
677 * Set skip UDP checksum transmitted over IPv6 status to use for Geneve
678 * @arg link Link object
679 * @arg csum Status value
680 *
681 * @return 0 on success or a negative error code
682 */
rtnl_link_geneve_set_udp_zero_csum6_tx(struct rtnl_link * link,uint8_t csum)683 int rtnl_link_geneve_set_udp_zero_csum6_tx(struct rtnl_link *link, uint8_t csum)
684 {
685 struct geneve_info *geneve = link->l_info;
686
687 IS_GENEVE_LINK_ASSERT(link);
688
689 geneve->udp_zero_csum6_tx = csum;
690 geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_TX;
691
692 return 0;
693 }
694
695 /**
696 * Get skip UDP checksum transmitted over IPv6 status to use for Geneve
697 * @arg link Link object
698 *
699 * @return Status value on success or a negative error code
700 */
rtnl_link_geneve_get_udp_zero_csum6_tx(struct rtnl_link * link)701 int rtnl_link_geneve_get_udp_zero_csum6_tx(struct rtnl_link *link)
702 {
703 struct geneve_info *geneve = link->l_info;
704
705 IS_GENEVE_LINK_ASSERT(link);
706
707 if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX))
708 return -NLE_NOATTR;
709
710 return geneve->udp_zero_csum6_tx;
711 }
712
713 /**
714 * Set skip UDP checksum received over IPv6 status to use for Geneve
715 * @arg link Link object
716 * @arg csum Status value
717 *
718 * @return 0 on success or a negative error code
719 */
rtnl_link_geneve_set_udp_zero_csum6_rx(struct rtnl_link * link,uint8_t csum)720 int rtnl_link_geneve_set_udp_zero_csum6_rx(struct rtnl_link *link, uint8_t csum)
721 {
722 struct geneve_info *geneve = link->l_info;
723
724 IS_GENEVE_LINK_ASSERT(link);
725
726 geneve->udp_zero_csum6_rx = csum;
727 geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_RX;
728
729 return 0;
730 }
731
732 /**
733 * Get skip UDP checksum received over IPv6 status to use for Geneve
734 * @arg link Link object
735 *
736 * @return Status value on success or a negative error code
737 */
rtnl_link_geneve_get_udp_zero_csum6_rx(struct rtnl_link * link)738 int rtnl_link_geneve_get_udp_zero_csum6_rx(struct rtnl_link *link)
739 {
740 struct geneve_info *geneve = link->l_info;
741
742 IS_GENEVE_LINK_ASSERT(link);
743
744 if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX))
745 return -NLE_NOATTR;
746
747 return geneve->udp_zero_csum6_rx;
748 }
749
750 /**
751 * Set Geneve flags
752 * @arg link Link object
753 * @arg flags Which flags to set
754 * @arg enable Boolean enabling or disabling flag
755 *
756 * @return 0 on success or a negative error code
757 */
rtnl_link_geneve_set_flags(struct rtnl_link * link,uint8_t flags,int enable)758 int rtnl_link_geneve_set_flags(struct rtnl_link *link, uint8_t flags, int enable)
759 {
760 struct geneve_info *geneve = link->l_info;
761
762 IS_GENEVE_LINK_ASSERT(link);
763
764 if (flags & ~RTNL_LINK_GENEVE_F_COLLECT_METADATA)
765 return -NLE_INVAL;
766
767 if (enable)
768 geneve->flags = flags;
769 else
770 geneve->flags &= ~flags;
771
772 return 0;
773 }
774
775 /**
776 * Get Geneve flags
777 * @arg link Link object
778 * @arg flags Pointer to store flags
779 *
780 * @return 0 on success or a negative error code
781 */
rtnl_link_geneve_get_flags(struct rtnl_link * link,uint8_t * flags)782 int rtnl_link_geneve_get_flags(struct rtnl_link *link, uint8_t *flags)
783 {
784 struct geneve_info *geneve = link->l_info;
785
786 IS_GENEVE_LINK_ASSERT(link);
787
788 *flags = geneve->flags;
789 return 0;
790 }
791
792 /** @} */
geneve_init(void)793 static void _nl_init geneve_init(void)
794 {
795 rtnl_link_register_info(&geneve_info_ops);
796 }
797
geneve_exit(void)798 static void _nl_exit geneve_exit(void)
799 {
800 rtnl_link_unregister_info(&geneve_info_ops);
801 }
802
803 /** @} */
804