12#include <linux/netfilter/nf_tables.h>
14#include <libmnl/libmnl.h>
15#include <libnftnl/object.h>
21nftnl_obj_tunnel_set(
struct nftnl_obj *e, uint16_t type,
22 const void *data, uint32_t data_len)
24 struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
27 case NFTNL_OBJ_TUNNEL_ID:
28 memcpy(&tun->id, data, data_len);
30 case NFTNL_OBJ_TUNNEL_IPV4_SRC:
31 memcpy(&tun->src_v4, data, data_len);
33 case NFTNL_OBJ_TUNNEL_IPV4_DST:
34 memcpy(&tun->dst_v4, data, data_len);
36 case NFTNL_OBJ_TUNNEL_IPV6_SRC:
37 memcpy(&tun->src_v6, data, data_len);
39 case NFTNL_OBJ_TUNNEL_IPV6_DST:
40 memcpy(&tun->dst_v6, data, data_len);
42 case NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL:
43 memcpy(&tun->flowlabel, data, data_len);
45 case NFTNL_OBJ_TUNNEL_SPORT:
46 memcpy(&tun->sport, data, data_len);
48 case NFTNL_OBJ_TUNNEL_DPORT:
49 memcpy(&tun->dport, data, data_len);
51 case NFTNL_OBJ_TUNNEL_FLAGS:
52 memcpy(&tun->tun_flags, data, data_len);
54 case NFTNL_OBJ_TUNNEL_TOS:
55 memcpy(&tun->tun_tos, data, data_len);
57 case NFTNL_OBJ_TUNNEL_TTL:
58 memcpy(&tun->tun_ttl, data, data_len);
60 case NFTNL_OBJ_TUNNEL_OPTS:
61 memcpy(&tun->tun_opts, data, data_len);
68nftnl_obj_tunnel_get(
const struct nftnl_obj *e, uint16_t type,
71 struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
74 case NFTNL_OBJ_TUNNEL_ID:
75 *data_len =
sizeof(tun->id);
77 case NFTNL_OBJ_TUNNEL_IPV4_SRC:
78 *data_len =
sizeof(tun->src_v4);
80 case NFTNL_OBJ_TUNNEL_IPV4_DST:
81 *data_len =
sizeof(tun->dst_v4);
83 case NFTNL_OBJ_TUNNEL_IPV6_SRC:
84 *data_len =
sizeof(tun->src_v6);
86 case NFTNL_OBJ_TUNNEL_IPV6_DST:
87 *data_len =
sizeof(tun->dst_v6);
89 case NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL:
90 *data_len =
sizeof(tun->flowlabel);
91 return &tun->flowlabel;
92 case NFTNL_OBJ_TUNNEL_SPORT:
93 *data_len =
sizeof(tun->sport);
95 case NFTNL_OBJ_TUNNEL_DPORT:
96 *data_len =
sizeof(tun->dport);
98 case NFTNL_OBJ_TUNNEL_FLAGS:
99 *data_len =
sizeof(tun->tun_flags);
100 return &tun->tun_flags;
101 case NFTNL_OBJ_TUNNEL_TOS:
102 *data_len =
sizeof(tun->tun_tos);
103 return &tun->tun_tos;
104 case NFTNL_OBJ_TUNNEL_TTL:
105 *data_len =
sizeof(tun->tun_ttl);
106 return &tun->tun_ttl;
107 case NFTNL_OBJ_TUNNEL_OPTS:
108 *data_len =
sizeof(tun->tun_opts);
109 return &tun->tun_opts;
114static int nftnl_obj_tunnel_cb(
const struct nlattr *attr,
void *data)
116 const struct nlattr **tb = data;
117 int type = mnl_attr_get_type(attr);
119 if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_MAX) < 0)
123 case NFTA_TUNNEL_KEY_ID:
124 case NFTA_TUNNEL_KEY_FLAGS:
125 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
128 case NFTA_TUNNEL_KEY_IP:
129 case NFTA_TUNNEL_KEY_IP6:
130 case NFTA_TUNNEL_KEY_OPTS:
131 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
134 case NFTA_TUNNEL_KEY_SPORT:
135 case NFTA_TUNNEL_KEY_DPORT:
136 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
139 case NFTA_TUNNEL_KEY_TOS:
140 case NFTA_TUNNEL_KEY_TTL:
141 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
150static void nftnl_tunnel_opts_build(
struct nlmsghdr *nlh,
154nftnl_obj_tunnel_build(
struct nlmsghdr *nlh,
const struct nftnl_obj *e)
156 struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
159 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ID))
160 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ID, htonl(tun->id));
161 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV4_SRC) ||
162 e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV4_DST)) {
163 nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_IP);
164 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV4_SRC))
165 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_IP_SRC, tun->src_v4);
166 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV4_DST))
167 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_IP_DST, tun->dst_v4);
168 mnl_attr_nest_end(nlh, nest);
170 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV6_SRC) ||
171 e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV6_DST)) {
172 nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_IP6);
173 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV6_SRC))
174 mnl_attr_put(nlh, NFTA_TUNNEL_KEY_IP6_SRC,
175 sizeof(tun->src_v6), &tun->src_v6);
176 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV6_DST))
177 mnl_attr_put(nlh, NFTA_TUNNEL_KEY_IP6_DST,
178 sizeof(tun->dst_v6), &tun->dst_v6);
179 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL))
180 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_IP6_FLOWLABEL,
181 htonl(tun->flowlabel));
182 mnl_attr_nest_end(nlh, nest);
184 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_SPORT))
185 mnl_attr_put_u16(nlh, NFTA_TUNNEL_KEY_SPORT, htons(tun->sport));
186 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_DPORT))
187 mnl_attr_put_u16(nlh, NFTA_TUNNEL_KEY_DPORT, htons(tun->dport));
188 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_TOS))
189 mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_TOS, tun->tun_tos);
190 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_TTL))
191 mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_TTL, tun->tun_ttl);
192 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_FLAGS))
193 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_FLAGS, htonl(tun->tun_flags));
194 if (e->flags & (1 << NFTNL_OBJ_TUNNEL_OPTS))
195 nftnl_tunnel_opts_build(nlh, tun->tun_opts);
198static int nftnl_obj_tunnel_ip_cb(
const struct nlattr *attr,
void *data)
200 const struct nlattr **tb = data;
201 int type = mnl_attr_get_type(attr);
203 if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_MAX) < 0)
207 case NFTA_TUNNEL_KEY_IP_SRC:
208 case NFTA_TUNNEL_KEY_IP_DST:
209 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
218static int nftnl_obj_tunnel_parse_ip(
struct nftnl_obj *e,
struct nlattr *attr,
219 struct nftnl_obj_tunnel *tun)
221 struct nlattr *tb[NFTA_TUNNEL_KEY_IP_MAX + 1] = {};
223 if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_ip_cb, tb) < 0)
226 if (tb[NFTA_TUNNEL_KEY_IP_SRC]) {
227 tun->src_v4 = mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_IP_SRC]);
228 e->flags |= (1 << NFTNL_OBJ_TUNNEL_IPV4_SRC);
230 if (tb[NFTA_TUNNEL_KEY_IP_DST]) {
231 tun->dst_v4 = mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_IP_DST]);
232 e->flags |= (1 << NFTNL_OBJ_TUNNEL_IPV4_DST);
238static int nftnl_obj_tunnel_ip6_cb(
const struct nlattr *attr,
void *data)
240 const struct nlattr **tb = data;
241 int type = mnl_attr_get_type(attr);
243 if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_MAX) < 0)
247 case NFTA_TUNNEL_KEY_IP6_SRC:
248 case NFTA_TUNNEL_KEY_IP6_DST:
249 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
252 case NFTA_TUNNEL_KEY_IP6_FLOWLABEL:
253 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
262static int nftnl_obj_tunnel_parse_ip6(
struct nftnl_obj *e,
struct nlattr *attr,
263 struct nftnl_obj_tunnel *tun)
265 struct nlattr *tb[NFTA_TUNNEL_KEY_IP6_MAX + 1] = {};
267 if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_ip6_cb, tb) < 0)
270 if (tb[NFTA_TUNNEL_KEY_IP6_SRC]) {
272 mnl_attr_get_payload(tb[NFTA_TUNNEL_KEY_IP6_SRC]),
273 sizeof(
struct in6_addr));
274 e->flags |= (1 << NFTNL_OBJ_TUNNEL_IPV6_SRC);
276 if (tb[NFTA_TUNNEL_KEY_IP6_DST]) {
278 mnl_attr_get_payload(tb[NFTA_TUNNEL_KEY_IP6_DST]),
279 sizeof(
struct in6_addr));
280 e->flags |= (1 << NFTNL_OBJ_TUNNEL_IPV6_DST);
282 if (tb[NFTA_TUNNEL_KEY_IP6_FLOWLABEL]) {
284 ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_IP6_FLOWLABEL]));
285 e->flags |= (1 << NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL);
292 struct list_head list;
294 enum nftnl_tunnel_type type;
312 uint16_t geneve_class;
314 uint8_t data[NFTNL_TUNNEL_GENEVE_DATA_MAXLEN];
321 enum nftnl_tunnel_type type;
323 struct list_head opts_list;
326EXPORT_SYMBOL(nftnl_tunnel_opt_get_data);
328 uint16_t attr, uint32_t *data_len)
330 if (!(ne->flags & (1 << attr)))
334 case NFTNL_TUNNEL_TYPE_ERSPAN:
336 case NFTNL_TUNNEL_ERSPAN_VERSION:
337 *data_len =
sizeof(uint32_t);
338 return &ne->erspan.version;
339 case NFTNL_TUNNEL_ERSPAN_V1_INDEX:
340 *data_len =
sizeof(uint32_t);
341 return &ne->erspan.v1.index;
342 case NFTNL_TUNNEL_ERSPAN_V2_HWID:
343 *data_len =
sizeof(uint8_t);
344 return &ne->erspan.v2.hwid;
345 case NFTNL_TUNNEL_ERSPAN_V2_DIR:
346 *data_len =
sizeof(uint8_t);
347 return &ne->erspan.v2.dir;
350 case NFTNL_TUNNEL_TYPE_VXLAN:
352 case NFTNL_TUNNEL_VXLAN_GBP:
353 *data_len =
sizeof(uint32_t);
354 return &ne->vxlan.gbp;
357 case NFTNL_TUNNEL_TYPE_GENEVE:
359 case NFTNL_TUNNEL_GENEVE_CLASS:
360 *data_len =
sizeof(uint16_t);
361 return &ne->geneve.geneve_class;
362 case NFTNL_TUNNEL_GENEVE_TYPE:
363 *data_len =
sizeof(uint8_t);
364 return &ne->geneve.type;
365 case NFTNL_TUNNEL_GENEVE_DATA:
366 *data_len = ne->geneve.data_len;
367 return &ne->geneve.data;
376EXPORT_SYMBOL(nftnl_tunnel_opt_get);
381 return nftnl_tunnel_opt_get_data(ne, attr, &data_len);
384EXPORT_SYMBOL(nftnl_tunnel_opt_get_u8);
385uint8_t nftnl_tunnel_opt_get_u8(
const struct nftnl_tunnel_opt *ne, uint16_t attr)
387 const void *ret = nftnl_tunnel_opt_get(ne, attr);
388 return ret == NULL ? 0 : *((uint8_t *)ret);
391EXPORT_SYMBOL(nftnl_tunnel_opt_get_u16);
392uint16_t nftnl_tunnel_opt_get_u16(
const struct nftnl_tunnel_opt *ne, uint16_t attr)
394 const void *ret = nftnl_tunnel_opt_get(ne, attr);
395 return ret == NULL ? 0 : *((uint16_t *)ret);
398EXPORT_SYMBOL(nftnl_tunnel_opt_get_u32);
399uint32_t nftnl_tunnel_opt_get_u32(
const struct nftnl_tunnel_opt *ne, uint16_t attr)
401 const void *ret = nftnl_tunnel_opt_get(ne, attr);
402 return ret == NULL ? 0 : *((uint32_t *)ret);
405EXPORT_SYMBOL(nftnl_tunnel_opt_get_type);
406enum nftnl_tunnel_type nftnl_tunnel_opt_get_type(
const struct nftnl_tunnel_opt *ne)
411EXPORT_SYMBOL(nftnl_tunnel_opt_get_flags);
417EXPORT_SYMBOL(nftnl_obj_tunnel_opts_foreach);
418int nftnl_obj_tunnel_opts_foreach(
const struct nftnl_obj *ne,
422 struct nftnl_obj_tunnel *tun = nftnl_obj_data(ne);
426 list_for_each_entry_safe(cur, tmp, &tun->tun_opts->opts_list, list) {
435static int nftnl_obj_tunnel_vxlan_cb(
const struct nlattr *attr,
void *data)
437 const struct nlattr **tb = data;
438 int type = mnl_attr_get_type(attr);
440 if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_VXLAN_MAX) < 0)
444 case NFTA_TUNNEL_KEY_VXLAN_GBP:
445 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
454struct nftnl_tunnel_opt *nftnl_tunnel_opt_alloc(
enum nftnl_tunnel_type type);
459 struct nlattr *tb[NFTA_TUNNEL_KEY_VXLAN_MAX + 1] = {};
462 if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_vxlan_cb, tb) < 0)
465 opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_VXLAN);
469 if (tb[NFTA_TUNNEL_KEY_VXLAN_GBP]) {
471 ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_VXLAN_GBP]));
472 opt->flags |= (1 << NFTNL_TUNNEL_VXLAN_GBP);
475 list_add_tail(&opt->list, &opts->opts_list);
480static int nftnl_obj_tunnel_erspan_cb(
const struct nlattr *attr,
void *data)
482 const struct nlattr **tb = data;
483 int type = mnl_attr_get_type(attr);
485 if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_ERSPAN_MAX) < 0)
489 case NFTA_TUNNEL_KEY_ERSPAN_VERSION:
490 case NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX:
491 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
494 case NFTA_TUNNEL_KEY_ERSPAN_V2_HWID:
495 case NFTA_TUNNEL_KEY_ERSPAN_V2_DIR:
496 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
506nftnl_obj_tunnel_parse_erspan(
struct nftnl_tunnel_opts *opts,
struct nlattr *attr)
508 struct nlattr *tb[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = {};
511 if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_erspan_cb, tb) < 0)
514 opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_ERSPAN);
518 if (tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]) {
519 opt->erspan.version =
520 ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]));
521 opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_VERSION);
523 if (tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]) {
524 opt->erspan.v1.index =
525 ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]));
526 opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX);
528 if (tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]) {
529 opt->erspan.v2.hwid =
530 mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]);
531 opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID);
533 if (tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]) {
535 mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]);
536 opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR);
539 list_add_tail(&opt->list, &opts->opts_list);
544static int nftnl_obj_tunnel_geneve_cb(
const struct nlattr *attr,
void *data)
546 const struct nlattr **tb = data;
547 int type = mnl_attr_get_type(attr);
549 if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_GENEVE_MAX) < 0)
553 case NFTA_TUNNEL_KEY_GENEVE_CLASS:
554 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
557 case NFTA_TUNNEL_KEY_GENEVE_TYPE:
558 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
561 case NFTA_TUNNEL_KEY_GENEVE_DATA:
562 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
572nftnl_obj_tunnel_parse_geneve(
struct nftnl_tunnel_opts *opts,
struct nlattr *attr)
574 struct nlattr *tb[NFTA_TUNNEL_KEY_GENEVE_MAX + 1] = {};
577 if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_geneve_cb, tb) < 0)
580 opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_GENEVE);
584 if (tb[NFTA_TUNNEL_KEY_GENEVE_CLASS]) {
585 opt->geneve.geneve_class =
586 ntohs(mnl_attr_get_u16(tb[NFTA_TUNNEL_KEY_GENEVE_CLASS]));
587 opt->flags |= (1 << NFTNL_TUNNEL_GENEVE_CLASS);
590 if (tb[NFTA_TUNNEL_KEY_GENEVE_TYPE]) {
592 mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_GENEVE_TYPE]);
593 opt->flags |= (1 << NFTNL_TUNNEL_GENEVE_TYPE);
596 if (tb[NFTA_TUNNEL_KEY_GENEVE_DATA]) {
597 uint32_t len = mnl_attr_get_payload_len(tb[NFTA_TUNNEL_KEY_GENEVE_DATA]);
599 memcpy(opt->geneve.data,
600 mnl_attr_get_payload(tb[NFTA_TUNNEL_KEY_GENEVE_DATA]),
602 opt->geneve.data_len = len;
603 opt->flags |= (1 << NFTNL_TUNNEL_GENEVE_DATA);
606 list_add_tail(&opt->list, &opts->opts_list);
614nftnl_obj_tunnel_parse_opts(
struct nftnl_obj *e,
struct nlattr *nest,
615 struct nftnl_obj_tunnel *tun)
621 mnl_attr_for_each_nested(attr, nest) {
622 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
625 switch(mnl_attr_get_type(attr)) {
626 case NFTA_TUNNEL_KEY_OPTS_VXLAN:
627 opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_VXLAN);
631 err = nftnl_obj_tunnel_parse_vxlan(opts, attr);
633 case NFTA_TUNNEL_KEY_OPTS_ERSPAN:
634 opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_ERSPAN);
638 err = nftnl_obj_tunnel_parse_erspan(opts, attr);
640 case NFTA_TUNNEL_KEY_OPTS_GENEVE:
642 opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_GENEVE);
647 err = nftnl_obj_tunnel_parse_geneve(opts, attr);
653 tun->tun_opts = opts;
654 e->flags |= (1 << NFTNL_OBJ_TUNNEL_OPTS);
661nftnl_obj_tunnel_parse(
struct nftnl_obj *e,
struct nlattr *attr)
663 struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
664 struct nlattr *tb[NFTA_TUNNEL_KEY_MAX + 1] = {};
667 if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_cb, tb) < 0)
670 if (tb[NFTA_TUNNEL_KEY_ID]) {
671 tun->id = ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ID]));
672 e->flags |= (1 << NFTNL_OBJ_TUNNEL_ID);
674 if (tb[NFTA_TUNNEL_KEY_IP]) {
675 err = nftnl_obj_tunnel_parse_ip(e, tb[NFTA_TUNNEL_KEY_IP], tun);
678 }
else if (tb[NFTA_TUNNEL_KEY_IP6]) {
679 err = nftnl_obj_tunnel_parse_ip6(e, tb[NFTA_TUNNEL_KEY_IP6], tun);
684 if (tb[NFTA_TUNNEL_KEY_SPORT]) {
685 tun->sport = ntohs(mnl_attr_get_u16(tb[NFTA_TUNNEL_KEY_SPORT]));
686 e->flags |= (1 << NFTNL_OBJ_TUNNEL_SPORT);
688 if (tb[NFTA_TUNNEL_KEY_DPORT]) {
689 tun->dport = ntohs(mnl_attr_get_u16(tb[NFTA_TUNNEL_KEY_DPORT]));
690 e->flags |= (1 << NFTNL_OBJ_TUNNEL_DPORT);
692 if (tb[NFTA_TUNNEL_KEY_TOS]) {
693 tun->tun_tos = mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_TOS]);
694 e->flags |= (1 << NFTNL_OBJ_TUNNEL_TOS);
696 if (tb[NFTA_TUNNEL_KEY_TTL]) {
697 tun->tun_ttl = mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_TTL]);
698 e->flags |= (1 << NFTNL_OBJ_TUNNEL_TTL);
700 if (tb[NFTA_TUNNEL_KEY_FLAGS]) {
701 tun->tun_flags = mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_FLAGS]);
702 e->flags |= (1 << NFTNL_OBJ_TUNNEL_FLAGS);
704 if (tb[NFTA_TUNNEL_KEY_OPTS]) {
705 err = nftnl_obj_tunnel_parse_opts(e, tb[NFTA_TUNNEL_KEY_OPTS], tun);
713static int nftnl_obj_tunnel_snprintf(
char *buf,
size_t len,
714 uint32_t flags,
const struct nftnl_obj *e)
716 struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
718 return snprintf(buf, len,
"id %u ", tun->id);
721EXPORT_SYMBOL(nftnl_tunnel_opts_alloc);
727 case NFTNL_TUNNEL_TYPE_VXLAN:
728 case NFTNL_TUNNEL_TYPE_ERSPAN:
729 case NFTNL_TUNNEL_TYPE_GENEVE:
741 INIT_LIST_HEAD(&opts->opts_list);
746EXPORT_SYMBOL(nftnl_tunnel_opts_add);
750 if (opt->type != opts->type) {
755 switch (opts->type) {
756 case NFTNL_TUNNEL_TYPE_VXLAN:
757 case NFTNL_TUNNEL_TYPE_ERSPAN:
763 case NFTNL_TUNNEL_TYPE_GENEVE:
770 list_add_tail(&opt->list, &opts->opts_list);
775EXPORT_SYMBOL(nftnl_tunnel_opts_free);
780 list_for_each_entry_safe(opt, next, &opts->opts_list, list) {
782 case NFTNL_TUNNEL_TYPE_VXLAN:
783 case NFTNL_TUNNEL_TYPE_ERSPAN:
784 case NFTNL_TUNNEL_TYPE_GENEVE:
785 list_del(&opt->list);
792EXPORT_SYMBOL(nftnl_tunnel_opt_alloc);
798 case NFTNL_TUNNEL_TYPE_VXLAN:
799 case NFTNL_TUNNEL_TYPE_ERSPAN:
800 case NFTNL_TUNNEL_TYPE_GENEVE:
816static int nftnl_tunnel_opt_vxlan_set(
struct nftnl_tunnel_opt *opt, uint16_t type,
817 const void *data, uint32_t data_len)
820 case NFTNL_TUNNEL_VXLAN_GBP:
821 memcpy(&opt->vxlan.gbp, data, data_len);
828 opt->flags |= (1 << type);
833static int nftnl_tunnel_opt_erspan_set(
struct nftnl_tunnel_opt *opt, uint16_t type,
834 const void *data, uint32_t data_len)
837 case NFTNL_TUNNEL_ERSPAN_VERSION:
838 memcpy(&opt->erspan.version, data, data_len);
840 case NFTNL_TUNNEL_ERSPAN_V1_INDEX:
841 memcpy(&opt->erspan.v1.index, data, data_len);
843 case NFTNL_TUNNEL_ERSPAN_V2_HWID:
844 memcpy(&opt->erspan.v2.hwid, data, data_len);
846 case NFTNL_TUNNEL_ERSPAN_V2_DIR:
847 memcpy(&opt->erspan.v2.dir, data, data_len);
854 opt->flags |= (1 << type);
859static int nftnl_tunnel_opt_geneve_set(
struct nftnl_tunnel_opt *opt, uint16_t type,
860 const void *data, uint32_t data_len)
863 case NFTNL_TUNNEL_GENEVE_CLASS:
864 memcpy(&opt->geneve.geneve_class, data, data_len);
866 case NFTNL_TUNNEL_GENEVE_TYPE:
867 memcpy(&opt->geneve.type, data, data_len);
869 case NFTNL_TUNNEL_GENEVE_DATA:
870 if (data_len > NFTNL_TUNNEL_GENEVE_DATA_MAXLEN) {
874 memcpy(&opt->geneve.data, data, data_len);
875 opt->geneve.data_len = data_len;
882 opt->flags |= (1 << type);
887EXPORT_SYMBOL(nftnl_tunnel_opt_set);
889 const void *data, uint32_t data_len)
892 case NFTNL_TUNNEL_TYPE_VXLAN:
893 return nftnl_tunnel_opt_vxlan_set(opt, type, data, data_len);
894 case NFTNL_TUNNEL_TYPE_ERSPAN:
895 return nftnl_tunnel_opt_erspan_set(opt, type, data, data_len);
896 case NFTNL_TUNNEL_TYPE_GENEVE:
897 return nftnl_tunnel_opt_geneve_set(opt, type, data, data_len);
906static void nftnl_tunnel_opt_build_vxlan(
struct nlmsghdr *nlh,
909 struct nlattr *nest_inner;
911 if (opt->flags & (1 << NFTNL_TUNNEL_VXLAN_GBP)) {
912 nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_VXLAN);
913 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_VXLAN_GBP,
914 htonl(opt->vxlan.gbp));
915 mnl_attr_nest_end(nlh, nest_inner);
919static void nftnl_tunnel_opt_build_erspan(
struct nlmsghdr *nlh,
922 struct nlattr *nest_inner;
924 if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_VERSION) &&
925 (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX) ||
926 (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID) &&
927 opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR)))) {
928 nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_ERSPAN);
929 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_VERSION,
930 htonl(opt->erspan.version));
931 if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX))
932 mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
933 htonl(opt->erspan.v1.index));
934 if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID))
935 mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
936 opt->erspan.v2.hwid);
937 if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR))
938 mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
940 mnl_attr_nest_end(nlh, nest_inner);
944static void nftnl_tunnel_opt_build_geneve(
struct nlmsghdr *nlh,
947 struct nlattr *nest_inner;
949 if (opt->flags & (1 << NFTNL_TUNNEL_GENEVE_CLASS) &&
950 opt->flags & (1 << NFTNL_TUNNEL_GENEVE_TYPE) &&
951 opt->flags & (1 << NFTNL_TUNNEL_GENEVE_DATA)) {
952 nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_GENEVE);
953 mnl_attr_put_u16(nlh, NFTA_TUNNEL_KEY_GENEVE_CLASS,
954 htons(opt->geneve.geneve_class));
955 mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_GENEVE_TYPE,
957 mnl_attr_put(nlh, NFTA_TUNNEL_KEY_GENEVE_DATA,
958 opt->geneve.data_len,
960 mnl_attr_nest_end(nlh, nest_inner);
964void nftnl_tunnel_opts_build(
struct nlmsghdr *nlh,
970 nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS);
972 list_for_each_entry(opt, &opts->opts_list, list) {
973 switch (opts->type) {
974 case NFTNL_TUNNEL_TYPE_VXLAN:
975 nftnl_tunnel_opt_build_vxlan(nlh, opt);
977 case NFTNL_TUNNEL_TYPE_ERSPAN:
978 nftnl_tunnel_opt_build_erspan(nlh, opt);
980 case NFTNL_TUNNEL_TYPE_GENEVE:
981 nftnl_tunnel_opt_build_geneve(nlh, opt);
985 mnl_attr_nest_end(nlh, nest);
988static struct attr_policy obj_tunnel_attr_policy[__NFTNL_OBJ_TUNNEL_MAX] = {
989 [NFTNL_OBJ_TUNNEL_ID] = { .maxlen =
sizeof(uint32_t) },
990 [NFTNL_OBJ_TUNNEL_IPV4_SRC] = { .maxlen =
sizeof(uint32_t) },
991 [NFTNL_OBJ_TUNNEL_IPV4_DST] = { .maxlen =
sizeof(uint32_t) },
992 [NFTNL_OBJ_TUNNEL_IPV6_SRC] = { .maxlen =
sizeof(
struct in6_addr) },
993 [NFTNL_OBJ_TUNNEL_IPV6_DST] = { .maxlen =
sizeof(
struct in6_addr) },
994 [NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL] = { .maxlen =
sizeof(uint32_t) },
995 [NFTNL_OBJ_TUNNEL_SPORT] = { .maxlen =
sizeof(uint16_t) },
996 [NFTNL_OBJ_TUNNEL_DPORT] = { .maxlen =
sizeof(uint16_t) },
997 [NFTNL_OBJ_TUNNEL_FLAGS] = { .maxlen =
sizeof(uint32_t) },
998 [NFTNL_OBJ_TUNNEL_TOS] = { .maxlen =
sizeof(uint8_t) },
999 [NFTNL_OBJ_TUNNEL_TTL] = { .maxlen =
sizeof(uint8_t) },
1003struct obj_ops obj_ops_tunnel = {
1005 .type = NFT_OBJECT_TUNNEL,
1006 .alloc_len =
sizeof(
struct nftnl_obj_tunnel),
1007 .nftnl_max_attr = __NFTNL_OBJ_TUNNEL_MAX - 1,
1008 .attr_policy = obj_tunnel_attr_policy,
1009 .set = nftnl_obj_tunnel_set,
1010 .get = nftnl_obj_tunnel_get,
1011 .parse = nftnl_obj_tunnel_parse,
1012 .build = nftnl_obj_tunnel_build,
1013 .output = nftnl_obj_tunnel_snprintf,