libnl  3.6.0
geneve.c
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 
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 
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 
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 
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 
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  if (inet_ntop(AF_INET, &geneve->remote, addr, sizeof(addr)))
190  nl_dump_line(p, "%s\n", addr);
191  else
192  nl_dump_line(p, "%#x\n", ntohs(geneve->remote));
193  } else if (geneve->mask & GENEVE_ATTR_REMOTE6) {
194  nl_dump(p, " remote ");
195  if (inet_ntop(AF_INET6, &geneve->remote6, addr, sizeof(addr)))
196  nl_dump_line(p, "%s\n", addr);
197  else
198  nl_dump_line(p, "%#x\n", geneve->remote6);
199  }
200 
201  if (geneve->mask & GENEVE_ATTR_TTL) {
202  nl_dump(p, " ttl ");
203  nl_dump_line(p, "%u\n", geneve->ttl);
204  }
205 
206  if (geneve->mask & GENEVE_ATTR_TOS) {
207  nl_dump(p, " tos ");
208  nl_dump_line(p, "%u\n", geneve->tos);
209  }
210 
211  if (geneve->mask & GENEVE_ATTR_PORT) {
212  nl_dump(p, " port ");
213  nl_dump_line(p, "%u\n", ntohs(geneve->port));
214  }
215 
216  if (geneve->mask & GENEVE_ATTR_LABEL) {
217  nl_dump(p, " label ");
218  nl_dump_line(p, "%u\n", ntohl(geneve->label));
219  }
220 
221  if (geneve->mask & GENEVE_ATTR_UDP_CSUM) {
222  nl_dump(p, " UDP checksum ");
223  if (geneve->udp_csum)
224  nl_dump_line(p, "enabled (%#x)\n", geneve->udp_csum);
225  else
226  nl_dump_line(p, "disabled\n");
227  }
228 
229  if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX) {
230  nl_dump(p, " udp-zero-csum6-tx ");
231  if (geneve->udp_zero_csum6_tx)
232  nl_dump_line(p, "enabled (%#x)\n", geneve->udp_zero_csum6_tx);
233  else
234  nl_dump_line(p, "disabled\n");
235  }
236 
237  if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX) {
238  nl_dump(p, " udp-zero-csum6-rx ");
239  if (geneve->udp_zero_csum6_rx)
240  nl_dump_line(p, "enabled (%#x)\n", geneve->udp_zero_csum6_rx);
241  else
242  nl_dump_line(p, "disabled\n");
243  }
244 
245  if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA)
246  nl_dump(p, " collect-metadata\n");
247 }
248 
249 static int geneve_clone(struct rtnl_link *dst, struct rtnl_link *src)
250 {
251  struct geneve_info *gdst, *gsrc;
252  int err;
253 
254  gsrc = src->l_info;
255  dst->l_info = NULL;
256  err = rtnl_link_set_type(dst, "geneve");
257  if (err < 0)
258  return err;
259 
260  gdst = dst->l_info;
261 
262  if (!gsrc || !gdst)
263  return -NLE_NOMEM;
264 
265  memcpy(gdst, gsrc, sizeof(struct geneve_info));
266 
267  return 0;
268 }
269 
270 static int geneve_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
271 {
272  struct geneve_info *geneve = link->l_info;
273  struct nlattr *data;
274 
275  if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
276  return -NLE_MSGSIZE;
277 
278  if (geneve->mask & GENEVE_ATTR_ID)
279  NLA_PUT_U32(msg, IFLA_GENEVE_ID, geneve->id);
280 
281  if (geneve->mask & GENEVE_ATTR_REMOTE)
282  NLA_PUT(msg, IFLA_GENEVE_REMOTE,
283  sizeof(geneve->remote), &geneve->remote);
284 
285  if (geneve->mask & GENEVE_ATTR_REMOTE6)
286  NLA_PUT(msg, IFLA_GENEVE_REMOTE6,
287  sizeof(geneve->remote6), &geneve->remote6);
288 
289  if (geneve->mask & GENEVE_ATTR_TTL)
290  NLA_PUT_U8(msg, IFLA_GENEVE_TTL, geneve->ttl);
291 
292  if (geneve->mask & GENEVE_ATTR_TOS)
293  NLA_PUT_U8(msg, IFLA_GENEVE_TOS, geneve->tos);
294 
295  if (geneve->mask & GENEVE_ATTR_LABEL)
296  NLA_PUT_U32(msg, IFLA_GENEVE_LABEL, geneve->label);
297 
298  if (geneve->mask & GENEVE_ATTR_PORT)
299  NLA_PUT_U32(msg, IFLA_GENEVE_PORT, geneve->port);
300 
301  if (geneve->mask & GENEVE_ATTR_UDP_CSUM)
302  NLA_PUT_U8(msg, IFLA_GENEVE_UDP_CSUM, geneve->udp_csum);
303 
304  if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX)
305  NLA_PUT_U8(msg, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, geneve->udp_zero_csum6_tx);
306 
307  if (geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX)
308  NLA_PUT_U8(msg, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, geneve->udp_zero_csum6_rx);
309 
310  if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA)
311  NLA_PUT_FLAG(msg, IFLA_GENEVE_COLLECT_METADATA);
312 
313  nla_nest_end(msg, data);
314 
315 nla_put_failure:
316 
317  return 0;
318 }
319 
320 static struct rtnl_link_info_ops geneve_info_ops = {
321  .io_name = "geneve",
322  .io_alloc = geneve_alloc,
323  .io_parse = geneve_parse,
324  .io_dump = {
325  [NL_DUMP_LINE] = geneve_dump_line,
326  [NL_DUMP_DETAILS] = geneve_dump_details,
327  },
328  .io_clone = geneve_clone,
329  .io_put_attrs = geneve_put_attrs,
330  .io_free = geneve_free,
331 };
332 
333 
334 /** @cond SKIP */
335 #define IS_GENEVE_LINK_ASSERT(link) \
336  if ((link)->l_info_ops != &geneve_info_ops) { \
337  APPBUG("Link is not a geneve link. set type \"geneve\" first."); \
338  return -NLE_OPNOTSUPP; \
339  }
340 /** @endcond */
341 
342 /**
343  * @name Geneve Object
344  * @{
345  */
346 
347 /**
348  * Allocate link object of type Geneve
349  *
350  * @return Allocated link object or NULL.
351  */
353 {
354  struct rtnl_link *link;
355  int err;
356 
357  if (!(link = rtnl_link_alloc()))
358  return NULL;
359 
360  if ((err = rtnl_link_set_type(link, "geneve")) < 0) {
361  rtnl_link_put(link);
362  return NULL;
363  }
364 
365  return link;
366 }
367 
368 /**
369  * Check if link is a Geneve link
370  * @arg link Link object
371  *
372  * @return True if link is a Geneve link, otherwisee false is returned.
373  */
375 {
376  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "geneve");
377 }
378 
379 /**
380  * Set Geneve Network Indentifier
381  * @arg link Link object
382  * @arg id Geneve network identifier
383  *
384  * @return 0 on success or a negative error code
385  */
386 int rtnl_link_geneve_set_id(struct rtnl_link *link, uint32_t id)
387 {
388  struct geneve_info *geneve = link->l_info;
389 
390  IS_GENEVE_LINK_ASSERT(link);
391 
392  if (id > RTNL_GENEVE_ID_MAX)
393  return -NLE_INVAL;
394 
395  geneve->id = id;
396  geneve->mask |= GENEVE_ATTR_ID;
397 
398  return 0;
399 }
400 
401 /**
402  * Get Geneve Network Identifier
403  * @arg link Link object
404  * @arg id Pointer to store network identifier
405  *
406  * @return 0 on success or a negative error code
407  */
408 int rtnl_link_geneve_get_id(struct rtnl_link *link, uint32_t *id)
409 {
410  struct geneve_info *geneve = link->l_info;
411 
412  IS_GENEVE_LINK_ASSERT(link);
413 
414  if (!id)
415  return -NLE_INVAL;
416 
417  if (geneve->mask & GENEVE_ATTR_ID)
418  *id = geneve->id;
419  else
420  return -NLE_AGAIN;
421 
422  return 0;
423 }
424 
425 /**
426  * Set Geneve unicast destination IP address
427  * @arg link Link object
428  * @arg addr The unicast destination IP address
429  *
430  * @return 0 on success or a negative error code
431  */
432 int rtnl_link_geneve_set_remote(struct rtnl_link *link, struct nl_addr *addr)
433 {
434  struct geneve_info *geneve = link->l_info;
435 
436  IS_GENEVE_LINK_ASSERT(link);
437 
438  if ((nl_addr_get_family(addr) == AF_INET) &&
439  (nl_addr_get_len(addr) == sizeof(geneve->remote))) {
440  memcpy(&geneve->remote, nl_addr_get_binary_addr(addr),
441  sizeof(geneve->remote));
442  geneve->mask |= GENEVE_ATTR_REMOTE;
443  geneve->mask &= ~GENEVE_ATTR_REMOTE6;
444  } else if ((nl_addr_get_family(addr) == AF_INET6) &&
445  (nl_addr_get_len(addr) == sizeof(geneve->remote6))) {
446  memcpy(&geneve->remote6, nl_addr_get_binary_addr(addr),
447  sizeof(geneve->remote6));
448  geneve->mask |= GENEVE_ATTR_REMOTE6;
449  geneve->mask &= ~GENEVE_ATTR_REMOTE;
450  } else
451  return -NLE_INVAL;
452 
453  return 0;
454 }
455 
456 /**
457  * Get Geneve unicast destination IP address
458  * @arg link Link object
459  * @arg addr Pointer to store unicast destination IP addree
460  *
461  * @return 0 on success or a a negative error code
462  */
463 int rtnl_link_geneve_get_remote(struct rtnl_link *link, struct nl_addr **addr)
464 {
465  struct geneve_info *geneve = link->l_info;
466 
467  IS_GENEVE_LINK_ASSERT(link);
468 
469  if (!addr)
470  return -NLE_INVAL;
471 
472  if (geneve->mask & GENEVE_ATTR_REMOTE)
473  *addr = nl_addr_build(AF_INET, &geneve->remote, sizeof(geneve->remote));
474  else if (geneve->mask & GENEVE_ATTR_REMOTE6)
475  *addr = nl_addr_build(AF_INET6, &geneve->remote6, sizeof(geneve->remote6));
476  else
477  return -NLE_AGAIN;
478 
479  return 0;
480 }
481 
482 /**
483  * Set IP TTL value to use for Geneve
484  * @arg link Link object
485  * @arg ttl TTL value
486  *
487  * @return 0 on success or a negative error code
488  */
489 int rtnl_link_geneve_set_ttl(struct rtnl_link *link, uint8_t ttl)
490 {
491  struct geneve_info *geneve = link->l_info;
492 
493  IS_GENEVE_LINK_ASSERT(link);
494 
495  geneve->ttl = ttl;
496  geneve->mask |= GENEVE_ATTR_TTL;
497 
498  return 0;
499 }
500 
501 /**
502  * Get IP TTL value to use for Geneve
503  * @arg link Link object
504  *
505  * @return TTL value on success or a negative error code
506  */
508 {
509  struct geneve_info *geneve = link->l_info;
510 
511  IS_GENEVE_LINK_ASSERT(link);
512 
513  if (!(geneve->mask & GENEVE_ATTR_TTL))
514  return -NLE_AGAIN;
515 
516  return geneve->ttl;
517 }
518 
519 /**
520  * Set IP ToS value to use for Geneve
521  * @arg link Link object
522  * @arg tos ToS value
523  *
524  * @return 0 on success or a negative error code
525  */
526 int rtnl_link_geneve_set_tos(struct rtnl_link *link, uint8_t tos)
527 {
528  struct geneve_info *geneve = link->l_info;
529 
530  IS_GENEVE_LINK_ASSERT(link);
531 
532  geneve->tos = tos;
533  geneve->mask |= GENEVE_ATTR_TOS;
534 
535  return 0;
536 }
537 
538 /**
539  * Get IP ToS value to use for Geneve
540  * @arg link Link object
541  *
542  * @return ToS value on success or a negative error code
543  */
545 {
546  struct geneve_info *geneve = link->l_info;
547 
548  IS_GENEVE_LINK_ASSERT(link);
549 
550  if (!(geneve->mask & GENEVE_ATTR_TOS))
551  return -NLE_AGAIN;
552 
553  return geneve->tos;
554 }
555 
556 /**
557  * Set UDP destination port to use for Geneve
558  * @arg link Link object
559  * @arg port Destination port
560  *
561  * @return 0 on success or a negative error code
562  */
563 
564 int rtnl_link_geneve_set_port(struct rtnl_link *link, uint32_t port)
565 {
566  struct geneve_info *geneve = link->l_info;
567 
568  IS_GENEVE_LINK_ASSERT(link);
569 
570  geneve->port = htons(port);
571  geneve->mask |= GENEVE_ATTR_PORT;
572 
573  return 0;
574 }
575 
576 /**
577  * Get UDP destination port to use for Geneve
578  * @arg link Link object
579  * @arg port Pointer to store destination port
580  *
581  * @return 0 on success or a negative error code
582  */
583 int rtnl_link_geneve_get_port(struct rtnl_link *link, uint32_t *port)
584 {
585  struct geneve_info *geneve = link->l_info;
586 
587  IS_GENEVE_LINK_ASSERT(link);
588 
589  if (!port)
590  return -NLE_INVAL;
591 
592  if (!(geneve->mask & GENEVE_ATTR_PORT))
593  return -NLE_NOATTR;
594 
595  *port = ntohs(geneve->port);
596 
597  return 0;
598 }
599 
600 /**
601  * Set flow label to use for Geneve
602  * @arg link Link object
603  * @arg label Destination label
604  *
605  * @return 0 on success or a negative error code
606  */
607 int rtnl_link_geneve_set_label(struct rtnl_link *link, uint32_t label)
608 {
609  struct geneve_info *geneve = link->l_info;
610 
611  IS_GENEVE_LINK_ASSERT(link);
612 
613  geneve->label = htonl(label);
614  geneve->mask |= GENEVE_ATTR_LABEL;
615 
616  return 0;
617 }
618 
619 /**
620  * Get flow label to use for Geneve
621  * @arg link Link object
622  * @arg label Pointer to store destination label
623  *
624  * @return 0 on success or a negative error code
625  */
626 int rtnl_link_geneve_get_label(struct rtnl_link *link, uint32_t *label)
627 {
628  struct geneve_info *geneve = link->l_info;
629 
630  IS_GENEVE_LINK_ASSERT(link);
631 
632  if (!label)
633  return -NLE_INVAL;
634  if (!(geneve->mask & GENEVE_ATTR_LABEL))
635  return -NLE_NOATTR;
636 
637  *label = ntohl(geneve->label);
638 
639  return 0;
640 }
641 
642 /**
643  * Set UDP checksum status to use for Geneve
644  * @arg link Link object
645  * @arg csum Status value
646  *
647  * @return 0 on success or a negative error code
648  */
649 int rtnl_link_geneve_set_udp_csum(struct rtnl_link *link, uint8_t csum)
650 {
651  struct geneve_info *geneve = link->l_info;
652 
653  IS_GENEVE_LINK_ASSERT(link);
654 
655  geneve->udp_csum = csum;
656  geneve->mask |= GENEVE_ATTR_UDP_CSUM;
657 
658  return 0;
659 }
660 
661 /**
662  * Get UDP checksum status to use for Geneve
663  * @arg link Link object
664  *
665  * @return status value on success or a negative error code
666  */
668 {
669  struct geneve_info *geneve = link->l_info;
670 
671  IS_GENEVE_LINK_ASSERT(link);
672 
673  if (!(geneve->mask & GENEVE_ATTR_UDP_CSUM))
674  return -NLE_NOATTR;
675 
676  return geneve->udp_csum;
677 }
678 
679 /**
680  * Set skip UDP checksum transmitted over IPv6 status to use for Geneve
681  * @arg link Link object
682  * @arg csum Status value
683  *
684  * @return 0 on success or a negative error code
685  */
686 int rtnl_link_geneve_set_udp_zero_csum6_tx(struct rtnl_link *link, uint8_t csum)
687 {
688  struct geneve_info *geneve = link->l_info;
689 
690  IS_GENEVE_LINK_ASSERT(link);
691 
692  geneve->udp_zero_csum6_tx = csum;
693  geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_TX;
694 
695  return 0;
696 }
697 
698 /**
699  * Get skip UDP checksum transmitted over IPv6 status to use for Geneve
700  * @arg link Link object
701  *
702  * @return Status value on success or a negative error code
703  */
705 {
706  struct geneve_info *geneve = link->l_info;
707 
708  IS_GENEVE_LINK_ASSERT(link);
709 
710  if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX))
711  return -NLE_NOATTR;
712 
713  return geneve->udp_zero_csum6_tx;
714 }
715 
716 /**
717  * Set skip UDP checksum received over IPv6 status to use for Geneve
718  * @arg link Link object
719  * @arg csum Status value
720  *
721  * @return 0 on success or a negative error code
722  */
723 int rtnl_link_geneve_set_udp_zero_csum6_rx(struct rtnl_link *link, uint8_t csum)
724 {
725  struct geneve_info *geneve = link->l_info;
726 
727  IS_GENEVE_LINK_ASSERT(link);
728 
729  geneve->udp_zero_csum6_rx = csum;
730  geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_RX;
731 
732  return 0;
733 }
734 
735 /**
736  * Get skip UDP checksum received over IPv6 status to use for Geneve
737  * @arg link Link object
738  *
739  * @return Status value on success or a negative error code
740  */
742 {
743  struct geneve_info *geneve = link->l_info;
744 
745  IS_GENEVE_LINK_ASSERT(link);
746 
747  if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX))
748  return -NLE_NOATTR;
749 
750  return geneve->udp_zero_csum6_rx;
751 }
752 
753 /**
754  * Set Geneve flags
755  * @arg link Link object
756  * @arg flags Which flags to set
757  * @arg enable Boolean enabling or disabling flag
758  *
759  * @return 0 on success or a negative error code
760  */
761 int rtnl_link_geneve_set_flags(struct rtnl_link *link, uint8_t flags, int enable)
762 {
763  struct geneve_info *geneve = link->l_info;
764 
765  IS_GENEVE_LINK_ASSERT(link);
766 
767  if (flags & ~RTNL_LINK_GENEVE_F_COLLECT_METADATA)
768  return -NLE_INVAL;
769 
770  if (enable)
771  geneve->flags = flags;
772  else
773  geneve->flags &= ~flags;
774 
775  return 0;
776 }
777 
778 /**
779  * Get Geneve flags
780  * @arg link Link object
781  * @arg flags Pointer to store flags
782  *
783  * @return 0 on success or a negative error code
784  */
785 int rtnl_link_geneve_get_flags(struct rtnl_link *link, uint8_t *flags)
786 {
787  struct geneve_info *geneve = link->l_info;
788 
789  IS_GENEVE_LINK_ASSERT(link);
790 
791  *flags = geneve->flags;
792  return 0;
793 }
794 
795 /** @} */
796 static void __init geneve_init(void)
797 {
798  rtnl_link_register_info(&geneve_info_ops);
799 }
800 
801 static void __exit geneve_exit(void)
802 {
803  rtnl_link_unregister_info(&geneve_info_ops);
804 }
805 
806 /** @} */
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition: addr.c:935
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
Definition: addr.c:211
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition: addr.c:887
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition: addr.c:947
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:649
#define NLA_PUT_FLAG(msg, attrtype)
Add flag attribute to netlink message.
Definition: attr.h:265
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:194
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:159
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:230
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:599
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition: attr.c:346
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1013
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:958
@ NLA_U8
8 bit integer
Definition: attr.h:35
@ NLA_FLAG
Flag.
Definition: attr.h:40
@ NLA_U16
16 bit integer
Definition: attr.h:36
@ NLA_U32
32 bit integer
Definition: attr.h:37
int rtnl_link_geneve_get_remote(struct rtnl_link *link, struct nl_addr **addr)
Get Geneve unicast destination IP address.
Definition: geneve.c:463
int rtnl_link_geneve_get_port(struct rtnl_link *link, uint32_t *port)
Get UDP destination port to use for Geneve.
Definition: geneve.c:583
int rtnl_link_geneve_set_flags(struct rtnl_link *link, uint8_t flags, int enable)
Set Geneve flags.
Definition: geneve.c:761
struct rtnl_link * rtnl_link_geneve_alloc(void)
Allocate link object of type Geneve.
Definition: geneve.c:352
int rtnl_link_geneve_set_tos(struct rtnl_link *link, uint8_t tos)
Set IP ToS value to use for Geneve.
Definition: geneve.c:526
int rtnl_link_geneve_get_udp_zero_csum6_tx(struct rtnl_link *link)
Get skip UDP checksum transmitted over IPv6 status to use for Geneve.
Definition: geneve.c:704
int rtnl_link_geneve_get_udp_zero_csum6_rx(struct rtnl_link *link)
Get skip UDP checksum received over IPv6 status to use for Geneve.
Definition: geneve.c:741
int rtnl_link_geneve_set_remote(struct rtnl_link *link, struct nl_addr *addr)
Set Geneve unicast destination IP address.
Definition: geneve.c:432
int rtnl_link_geneve_get_tos(struct rtnl_link *link)
Get IP ToS value to use for Geneve.
Definition: geneve.c:544
int rtnl_link_geneve_set_udp_zero_csum6_tx(struct rtnl_link *link, uint8_t csum)
Set skip UDP checksum transmitted over IPv6 status to use for Geneve.
Definition: geneve.c:686
int rtnl_link_geneve_get_flags(struct rtnl_link *link, uint8_t *flags)
Get Geneve flags.
Definition: geneve.c:785
int rtnl_link_geneve_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP TTL value to use for Geneve.
Definition: geneve.c:489
int rtnl_link_geneve_set_udp_zero_csum6_rx(struct rtnl_link *link, uint8_t csum)
Set skip UDP checksum received over IPv6 status to use for Geneve.
Definition: geneve.c:723
int rtnl_link_geneve_set_label(struct rtnl_link *link, uint32_t label)
Set flow label to use for Geneve.
Definition: geneve.c:607
int rtnl_link_geneve_get_label(struct rtnl_link *link, uint32_t *label)
Get flow label to use for Geneve.
Definition: geneve.c:626
int rtnl_link_geneve_set_udp_csum(struct rtnl_link *link, uint8_t csum)
Set UDP checksum status to use for Geneve.
Definition: geneve.c:649
int rtnl_link_geneve_get_udp_csum(struct rtnl_link *link)
Get UDP checksum status to use for Geneve.
Definition: geneve.c:667
int rtnl_link_geneve_set_port(struct rtnl_link *link, uint32_t port)
Set UDP destination port to use for Geneve.
Definition: geneve.c:564
int rtnl_link_geneve_set_id(struct rtnl_link *link, uint32_t id)
Set Geneve Network Indentifier.
Definition: geneve.c:386
int rtnl_link_geneve_get_ttl(struct rtnl_link *link)
Get IP TTL value to use for Geneve.
Definition: geneve.c:507
int rtnl_link_geneve_get_id(struct rtnl_link *link, uint32_t *id)
Get Geneve Network Identifier.
Definition: geneve.c:408
int rtnl_link_is_geneve(struct rtnl_link *link)
Check if link is a Geneve link.
Definition: geneve.c:374
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65