xref: /aosp_15_r20/external/libnl/lib/route/link/geneve.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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