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>
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)
44 struct in6_addr remote6;
51 uint8_t udp_zero_csum6_tx;
52 uint8_t udp_zero_csum6_rx;
58 static struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
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 },
72 static int geneve_alloc(
struct rtnl_link *link)
74 struct geneve_info *geneve;
77 memset(link->l_info, 0,
sizeof(*geneve));
79 if ((geneve = calloc(1,
sizeof(*geneve))) == NULL)
81 link->l_info = geneve;
87 static int geneve_parse(
struct rtnl_link *link,
struct nlattr *data,
88 struct nlattr *xstats)
90 struct nlattr *tb[IFLA_GENEVE_MAX + 1];
91 struct geneve_info *geneve;
94 NL_DBG(3,
"Parsing Geneve link info\n");
100 err = geneve_alloc(link);
104 geneve = link->l_info;
106 if (tb[IFLA_GENEVE_ID]) {
108 geneve->mask |= GENEVE_ATTR_ID;
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;
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;
124 if (tb[IFLA_GENEVE_TTL]) {
125 geneve->ttl =
nla_get_u8(tb[IFLA_GENEVE_TTL]);
126 geneve->mask |= GENEVE_ATTR_TTL;
129 if (tb[IFLA_GENEVE_TOS]) {
130 geneve->tos =
nla_get_u8(tb[IFLA_GENEVE_TOS]);
131 geneve->mask |= GENEVE_ATTR_TOS;
134 if (tb[IFLA_GENEVE_LABEL]) {
135 geneve->label =
nla_get_u32(tb[IFLA_GENEVE_LABEL]);
136 geneve->mask |= GENEVE_ATTR_LABEL;
139 if (tb[IFLA_GENEVE_PORT]) {
141 geneve->mask |= GENEVE_ATTR_PORT;
144 if (tb[IFLA_GENEVE_COLLECT_METADATA])
145 geneve->flags |= RTNL_LINK_GENEVE_F_COLLECT_METADATA;
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;
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;
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;
165 static void geneve_free(
struct rtnl_link *link)
167 struct geneve_info *geneve = link->l_info;
175 struct geneve_info *geneve = link->l_info;
177 nl_dump(p,
"geneve-id %u", geneve->id);
182 struct geneve_info *geneve = link->l_info;
183 char addr[INET6_ADDRSTRLEN];
185 nl_dump_line(p,
" geneve-id %u\n", geneve->id);
187 if (geneve->mask & GENEVE_ATTR_REMOTE) {
189 if (inet_ntop(AF_INET, &geneve->remote, addr,
sizeof(addr)))
190 nl_dump_line(p,
"%s\n", addr);
192 nl_dump_line(p,
"%#x\n", ntohs(geneve->remote));
193 }
else if (geneve->mask & GENEVE_ATTR_REMOTE6) {
195 if (inet_ntop(AF_INET6, &geneve->remote6, addr,
sizeof(addr)))
196 nl_dump_line(p,
"%s\n", addr);
198 nl_dump_line(p,
"%#x\n", geneve->remote6);
201 if (geneve->mask & GENEVE_ATTR_TTL) {
203 nl_dump_line(p,
"%u\n", geneve->ttl);
206 if (geneve->mask & GENEVE_ATTR_TOS) {
208 nl_dump_line(p,
"%u\n", geneve->tos);
211 if (geneve->mask & GENEVE_ATTR_PORT) {
213 nl_dump_line(p,
"%u\n", ntohs(geneve->port));
216 if (geneve->mask & GENEVE_ATTR_LABEL) {
218 nl_dump_line(p,
"%u\n", ntohl(geneve->label));
221 if (geneve->mask & GENEVE_ATTR_UDP_CSUM) {
223 if (geneve->udp_csum)
224 nl_dump_line(p,
"enabled (%#x)\n", geneve->udp_csum);
226 nl_dump_line(p,
"disabled\n");
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);
234 nl_dump_line(p,
"disabled\n");
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);
242 nl_dump_line(p,
"disabled\n");
245 if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA)
246 nl_dump(p,
" collect-metadata\n");
251 struct geneve_info *gdst, *gsrc;
265 memcpy(gdst, gsrc,
sizeof(
struct geneve_info));
270 static int geneve_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
272 struct geneve_info *geneve = link->l_info;
278 if (geneve->mask & GENEVE_ATTR_ID)
281 if (geneve->mask & GENEVE_ATTR_REMOTE)
282 NLA_PUT(msg, IFLA_GENEVE_REMOTE,
283 sizeof(geneve->remote), &geneve->remote);
285 if (geneve->mask & GENEVE_ATTR_REMOTE6)
286 NLA_PUT(msg, IFLA_GENEVE_REMOTE6,
287 sizeof(geneve->remote6), &geneve->remote6);
289 if (geneve->mask & GENEVE_ATTR_TTL)
290 NLA_PUT_U8(msg, IFLA_GENEVE_TTL, geneve->ttl);
292 if (geneve->mask & GENEVE_ATTR_TOS)
293 NLA_PUT_U8(msg, IFLA_GENEVE_TOS, geneve->tos);
295 if (geneve->mask & GENEVE_ATTR_LABEL)
296 NLA_PUT_U32(msg, IFLA_GENEVE_LABEL, geneve->label);
298 if (geneve->mask & GENEVE_ATTR_PORT)
301 if (geneve->mask & GENEVE_ATTR_UDP_CSUM)
302 NLA_PUT_U8(msg, IFLA_GENEVE_UDP_CSUM, geneve->udp_csum);
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);
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);
310 if (geneve->flags & RTNL_LINK_GENEVE_F_COLLECT_METADATA)
320 static struct rtnl_link_info_ops geneve_info_ops = {
322 .io_alloc = geneve_alloc,
323 .io_parse = geneve_parse,
328 .io_clone = geneve_clone,
329 .io_put_attrs = geneve_put_attrs,
330 .io_free = geneve_free,
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; \
376 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
"geneve");
388 struct geneve_info *geneve = link->l_info;
390 IS_GENEVE_LINK_ASSERT(link);
392 if (
id > RTNL_GENEVE_ID_MAX)
396 geneve->mask |= GENEVE_ATTR_ID;
410 struct geneve_info *geneve = link->l_info;
412 IS_GENEVE_LINK_ASSERT(link);
417 if (geneve->mask & GENEVE_ATTR_ID)
434 struct geneve_info *geneve = link->l_info;
436 IS_GENEVE_LINK_ASSERT(link);
441 sizeof(geneve->remote));
442 geneve->mask |= GENEVE_ATTR_REMOTE;
443 geneve->mask &= ~GENEVE_ATTR_REMOTE6;
447 sizeof(geneve->remote6));
448 geneve->mask |= GENEVE_ATTR_REMOTE6;
449 geneve->mask &= ~GENEVE_ATTR_REMOTE;
465 struct geneve_info *geneve = link->l_info;
467 IS_GENEVE_LINK_ASSERT(link);
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));
491 struct geneve_info *geneve = link->l_info;
493 IS_GENEVE_LINK_ASSERT(link);
496 geneve->mask |= GENEVE_ATTR_TTL;
509 struct geneve_info *geneve = link->l_info;
511 IS_GENEVE_LINK_ASSERT(link);
513 if (!(geneve->mask & GENEVE_ATTR_TTL))
528 struct geneve_info *geneve = link->l_info;
530 IS_GENEVE_LINK_ASSERT(link);
533 geneve->mask |= GENEVE_ATTR_TOS;
546 struct geneve_info *geneve = link->l_info;
548 IS_GENEVE_LINK_ASSERT(link);
550 if (!(geneve->mask & GENEVE_ATTR_TOS))
566 struct geneve_info *geneve = link->l_info;
568 IS_GENEVE_LINK_ASSERT(link);
570 geneve->port = htons(port);
571 geneve->mask |= GENEVE_ATTR_PORT;
585 struct geneve_info *geneve = link->l_info;
587 IS_GENEVE_LINK_ASSERT(link);
592 if (!(geneve->mask & GENEVE_ATTR_PORT))
595 *port = ntohs(geneve->port);
609 struct geneve_info *geneve = link->l_info;
611 IS_GENEVE_LINK_ASSERT(link);
613 geneve->label = htonl(label);
614 geneve->mask |= GENEVE_ATTR_LABEL;
628 struct geneve_info *geneve = link->l_info;
630 IS_GENEVE_LINK_ASSERT(link);
634 if (!(geneve->mask & GENEVE_ATTR_LABEL))
637 *label = ntohl(geneve->label);
651 struct geneve_info *geneve = link->l_info;
653 IS_GENEVE_LINK_ASSERT(link);
655 geneve->udp_csum = csum;
656 geneve->mask |= GENEVE_ATTR_UDP_CSUM;
669 struct geneve_info *geneve = link->l_info;
671 IS_GENEVE_LINK_ASSERT(link);
673 if (!(geneve->mask & GENEVE_ATTR_UDP_CSUM))
676 return geneve->udp_csum;
688 struct geneve_info *geneve = link->l_info;
690 IS_GENEVE_LINK_ASSERT(link);
692 geneve->udp_zero_csum6_tx = csum;
693 geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_TX;
706 struct geneve_info *geneve = link->l_info;
708 IS_GENEVE_LINK_ASSERT(link);
710 if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_TX))
713 return geneve->udp_zero_csum6_tx;
725 struct geneve_info *geneve = link->l_info;
727 IS_GENEVE_LINK_ASSERT(link);
729 geneve->udp_zero_csum6_rx = csum;
730 geneve->mask |= GENEVE_ATTR_UDP_ZERO_CSUM6_RX;
743 struct geneve_info *geneve = link->l_info;
745 IS_GENEVE_LINK_ASSERT(link);
747 if (!(geneve->mask & GENEVE_ATTR_UDP_ZERO_CSUM6_RX))
750 return geneve->udp_zero_csum6_rx;
763 struct geneve_info *geneve = link->l_info;
765 IS_GENEVE_LINK_ASSERT(link);
767 if (flags & ~RTNL_LINK_GENEVE_F_COLLECT_METADATA)
771 geneve->flags = flags;
773 geneve->flags &= ~flags;
787 struct geneve_info *geneve = link->l_info;
789 IS_GENEVE_LINK_ASSERT(link);
791 *flags = geneve->flags;
796 static void __init geneve_init(
void)
801 static void __exit geneve_exit(
void)
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
#define NLA_PUT_FLAG(msg, attrtype)
Add flag attribute to netlink message.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int rtnl_link_geneve_get_remote(struct rtnl_link *link, struct nl_addr **addr)
Get Geneve unicast destination IP address.
int rtnl_link_geneve_get_port(struct rtnl_link *link, uint32_t *port)
Get UDP destination port to use for Geneve.
int rtnl_link_geneve_set_flags(struct rtnl_link *link, uint8_t flags, int enable)
Set Geneve flags.
struct rtnl_link * rtnl_link_geneve_alloc(void)
Allocate link object of type Geneve.
int rtnl_link_geneve_set_tos(struct rtnl_link *link, uint8_t tos)
Set IP ToS value to use for Geneve.
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.
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.
int rtnl_link_geneve_set_remote(struct rtnl_link *link, struct nl_addr *addr)
Set Geneve unicast destination IP address.
int rtnl_link_geneve_get_tos(struct rtnl_link *link)
Get IP ToS value to use for Geneve.
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.
int rtnl_link_geneve_get_flags(struct rtnl_link *link, uint8_t *flags)
Get Geneve flags.
int rtnl_link_geneve_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP TTL value to use for Geneve.
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.
int rtnl_link_geneve_set_label(struct rtnl_link *link, uint32_t label)
Set flow label to use for Geneve.
int rtnl_link_geneve_get_label(struct rtnl_link *link, uint32_t *label)
Get flow label to use for Geneve.
int rtnl_link_geneve_set_udp_csum(struct rtnl_link *link, uint8_t csum)
Set UDP checksum status to use for Geneve.
int rtnl_link_geneve_get_udp_csum(struct rtnl_link *link)
Get UDP checksum status to use for Geneve.
int rtnl_link_geneve_set_port(struct rtnl_link *link, uint32_t port)
Set UDP destination port to use for Geneve.
int rtnl_link_geneve_set_id(struct rtnl_link *link, uint32_t id)
Set Geneve Network Indentifier.
int rtnl_link_geneve_get_ttl(struct rtnl_link *link)
Get IP TTL value to use for Geneve.
int rtnl_link_geneve_get_id(struct rtnl_link *link, uint32_t *id)
Get Geneve Network Identifier.
int rtnl_link_is_geneve(struct rtnl_link *link)
Check if link is a Geneve link.
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t type
Type of attribute or NLA_UNSPEC.