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