• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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