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