diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libnftnl.map | 16 | ||||
-rw-r--r-- | src/obj/tunnel.c | 473 | ||||
-rw-r--r-- | src/object.c | 4 |
3 files changed, 412 insertions, 81 deletions
diff --git a/src/libnftnl.map b/src/libnftnl.map index 8fffff1..10c0e7f 100644 --- a/src/libnftnl.map +++ b/src/libnftnl.map @@ -383,3 +383,19 @@ LIBNFTNL_16 { LIBNFTNL_17 { nftnl_set_elem_nlmsg_build; } LIBNFTNL_16; + +LIBNFTNL_18 { +nftnl_tunnel_opt_get; +nftnl_tunnel_opt_get_data; +nftnl_tunnel_opt_get_u8; +nftnl_tunnel_opt_get_u16; +nftnl_tunnel_opt_get_u32; +nftnl_tunnel_opt_set; +nftnl_tunnel_opt_alloc; +nftnl_tunnel_opt_get_type; +nftnl_tunnel_opt_get_flags; +nftnl_tunnel_opts_alloc; +nftnl_obj_tunnel_opts_foreach; +nftnl_tunnel_opts_add; +nftnl_tunnel_opts_free; +} LIBNFTNL_17; diff --git a/src/obj/tunnel.c b/src/obj/tunnel.c index 8941e39..bed0342 100644 --- a/src/obj/tunnel.c +++ b/src/obj/tunnel.c @@ -57,20 +57,8 @@ nftnl_obj_tunnel_set(struct nftnl_obj *e, uint16_t type, case NFTNL_OBJ_TUNNEL_TTL: memcpy(&tun->tun_ttl, data, data_len); break; - case NFTNL_OBJ_TUNNEL_VXLAN_GBP: - memcpy(&tun->u.tun_vxlan.gbp, data, data_len); - break; - case NFTNL_OBJ_TUNNEL_ERSPAN_VERSION: - memcpy(&tun->u.tun_erspan.version, data, data_len); - break; - case NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX: - memcpy(&tun->u.tun_erspan.u.v1_index, data, data_len); - break; - case NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID: - memcpy(&tun->u.tun_erspan.u.v2.hwid, data, data_len); - break; - case NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR: - memcpy(&tun->u.tun_erspan.u.v2.dir, data, data_len); + case NFTNL_OBJ_TUNNEL_OPTS: + memcpy(&tun->tun_opts, data, data_len); break; } return 0; @@ -116,21 +104,9 @@ nftnl_obj_tunnel_get(const struct nftnl_obj *e, uint16_t type, case NFTNL_OBJ_TUNNEL_TTL: *data_len = sizeof(tun->tun_ttl); return &tun->tun_ttl; - case NFTNL_OBJ_TUNNEL_VXLAN_GBP: - *data_len = sizeof(tun->u.tun_vxlan.gbp); - return &tun->u.tun_vxlan.gbp; - case NFTNL_OBJ_TUNNEL_ERSPAN_VERSION: - *data_len = sizeof(tun->u.tun_erspan.version); - return &tun->u.tun_erspan.version; - case NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX: - *data_len = sizeof(tun->u.tun_erspan.u.v1_index); - return &tun->u.tun_erspan.u.v1_index; - case NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID: - *data_len = sizeof(tun->u.tun_erspan.u.v2.hwid); - return &tun->u.tun_erspan.u.v2.hwid; - case NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR: - *data_len = sizeof(tun->u.tun_erspan.u.v2.dir); - return &tun->u.tun_erspan.u.v2.dir; + case NFTNL_OBJ_TUNNEL_OPTS: + *data_len = sizeof(tun->tun_opts); + return &tun->tun_opts; } return NULL; } @@ -171,11 +147,14 @@ static int nftnl_obj_tunnel_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; } +static void nftnl_tunnel_opts_build(struct nlmsghdr *nlh, + struct nftnl_tunnel_opts *opts); + static void nftnl_obj_tunnel_build(struct nlmsghdr *nlh, const struct nftnl_obj *e) { struct nftnl_obj_tunnel *tun = nftnl_obj_data(e); - struct nlattr *nest, *nest_inner; + struct nlattr *nest; if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ID)) mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ID, htonl(tun->id)); @@ -212,34 +191,8 @@ nftnl_obj_tunnel_build(struct nlmsghdr *nlh, const struct nftnl_obj *e) mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_TTL, tun->tun_ttl); if (e->flags & (1 << NFTNL_OBJ_TUNNEL_FLAGS)) mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_FLAGS, htonl(tun->tun_flags)); - if (e->flags & (1 << NFTNL_OBJ_TUNNEL_VXLAN_GBP)) { - nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS); - nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_VXLAN); - mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_VXLAN_GBP, - htonl(tun->u.tun_vxlan.gbp)); - mnl_attr_nest_end(nlh, nest_inner); - mnl_attr_nest_end(nlh, nest); - } - if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_VERSION) && - (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX) || - (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID) && - e->flags & (1u << NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR)))) { - nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS); - nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_ERSPAN); - mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_VERSION, - htonl(tun->u.tun_erspan.version)); - if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX)) - mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX, - htonl(tun->u.tun_erspan.u.v1_index)); - if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID)) - mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID, - tun->u.tun_erspan.u.v2.hwid); - if (e->flags & (1u << NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR)) - mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR, - tun->u.tun_erspan.u.v2.dir); - mnl_attr_nest_end(nlh, nest_inner); - mnl_attr_nest_end(nlh, nest); - } + if (e->flags & (1 << NFTNL_OBJ_TUNNEL_OPTS)) + nftnl_tunnel_opts_build(nlh, tun->tun_opts); } static int nftnl_obj_tunnel_ip_cb(const struct nlattr *attr, void *data) @@ -335,6 +288,131 @@ static int nftnl_obj_tunnel_parse_ip6(struct nftnl_obj *e, struct nlattr *attr, return 0; } +struct nftnl_tunnel_opt { + struct list_head list; + + enum nftnl_tunnel_type type; + uint32_t flags; + + union { + struct { + uint32_t gbp; + } vxlan; + struct { + uint32_t version; + struct { + uint32_t index; + } v1; + struct { + uint8_t hwid; + uint8_t dir; + } v2; + } erspan; + }; +}; + +struct nftnl_tunnel_opts { + enum nftnl_tunnel_type type; + uint32_t num; + struct list_head opts_list; +}; + +EXPORT_SYMBOL(nftnl_tunnel_opt_get_data); +const void *nftnl_tunnel_opt_get_data(const struct nftnl_tunnel_opt *ne, + uint16_t attr, uint32_t *data_len) +{ + if (!(ne->flags & (1 << attr))) + return NULL; + + switch (ne->type) { + case NFTNL_TUNNEL_TYPE_ERSPAN: + switch (attr) { + case NFTNL_TUNNEL_ERSPAN_VERSION: + *data_len = sizeof(uint32_t); + return &ne->erspan.version; + case NFTNL_TUNNEL_ERSPAN_V1_INDEX: + *data_len = sizeof(uint32_t); + return &ne->erspan.v1.index; + case NFTNL_TUNNEL_ERSPAN_V2_HWID: + *data_len = sizeof(uint8_t); + return &ne->erspan.v2.hwid; + case NFTNL_TUNNEL_ERSPAN_V2_DIR: + *data_len = sizeof(uint8_t); + return &ne->erspan.v2.dir; + } + break; + case NFTNL_TUNNEL_TYPE_VXLAN: + switch (attr) { + case NFTNL_TUNNEL_VXLAN_GBP: + *data_len = sizeof(uint32_t); + return &ne->vxlan.gbp; + } + break; + } + + errno = EOPNOTSUPP; + return NULL; +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_get); +const void * +nftnl_tunnel_opt_get(const struct nftnl_tunnel_opt *ne, uint16_t attr) +{ + uint32_t data_len; + return nftnl_tunnel_opt_get_data(ne, attr, &data_len); +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_get_u8); +uint8_t nftnl_tunnel_opt_get_u8(const struct nftnl_tunnel_opt *ne, uint16_t attr) +{ + const void *ret = nftnl_tunnel_opt_get(ne, attr); + return ret == NULL ? 0 : *((uint8_t *)ret); +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_get_u16); +uint16_t nftnl_tunnel_opt_get_u16(const struct nftnl_tunnel_opt *ne, uint16_t attr) +{ + const void *ret = nftnl_tunnel_opt_get(ne, attr); + return ret == NULL ? 0 : *((uint16_t *)ret); +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_get_u32); +uint32_t nftnl_tunnel_opt_get_u32(const struct nftnl_tunnel_opt *ne, uint16_t attr) +{ + const void *ret = nftnl_tunnel_opt_get(ne, attr); + return ret == NULL ? 0 : *((uint32_t *)ret); +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_get_type); +enum nftnl_tunnel_type nftnl_tunnel_opt_get_type(const struct nftnl_tunnel_opt *ne) +{ + return ne->type; +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_get_flags); +uint32_t nftnl_tunnel_opt_get_flags(const struct nftnl_tunnel_opt *ne) +{ + return ne->flags; +} + +EXPORT_SYMBOL(nftnl_obj_tunnel_opts_foreach); +int nftnl_obj_tunnel_opts_foreach(const struct nftnl_obj *ne, + int (*cb)(struct nftnl_tunnel_opt *opt, void *data), + void *data) +{ + struct nftnl_obj_tunnel *tun = nftnl_obj_data(ne); + struct nftnl_tunnel_opt *cur, *tmp; + int ret; + + list_for_each_entry_safe(cur, tmp, &tun->tun_opts->opts_list, list) { + ret = cb(cur, data); + if (ret < 0) + return ret; + } + + return 0; +} + static int nftnl_obj_tunnel_vxlan_cb(const struct nlattr *attr, void *data) { const struct nlattr **tb = data; @@ -354,21 +432,29 @@ static int nftnl_obj_tunnel_vxlan_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; } +struct nftnl_tunnel_opt *nftnl_tunnel_opt_alloc(enum nftnl_tunnel_type type); + static int -nftnl_obj_tunnel_parse_vxlan(struct nftnl_obj *e, struct nlattr *attr, - struct nftnl_obj_tunnel *tun) +nftnl_obj_tunnel_parse_vxlan(struct nftnl_tunnel_opts *opts, struct nlattr *attr) { struct nlattr *tb[NFTA_TUNNEL_KEY_VXLAN_MAX + 1] = {}; + struct nftnl_tunnel_opt *opt; if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_vxlan_cb, tb) < 0) return -1; + opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_VXLAN); + if (!opt) + return -1; + if (tb[NFTA_TUNNEL_KEY_VXLAN_GBP]) { - tun->u.tun_vxlan.gbp = + opt->vxlan.gbp = ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_VXLAN_GBP])); - e->flags |= (1 << NFTNL_OBJ_TUNNEL_VXLAN_GBP); + opt->flags |= (1 << NFTNL_TUNNEL_VXLAN_GBP); } + list_add_tail(&opt->list, &opts->opts_list); + return 0; } @@ -398,35 +484,41 @@ static int nftnl_obj_tunnel_erspan_cb(const struct nlattr *attr, void *data) } static int -nftnl_obj_tunnel_parse_erspan(struct nftnl_obj *e, struct nlattr *attr, - struct nftnl_obj_tunnel *tun) +nftnl_obj_tunnel_parse_erspan(struct nftnl_tunnel_opts *opts, struct nlattr *attr) { struct nlattr *tb[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = {}; + struct nftnl_tunnel_opt *opt; if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_erspan_cb, tb) < 0) return -1; + opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_ERSPAN); + if (!opt) + return -1; + if (tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]) { - tun->u.tun_erspan.version = + opt->erspan.version = ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION])); - e->flags |= (1 << NFTNL_OBJ_TUNNEL_ERSPAN_VERSION); + opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_VERSION); } if (tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]) { - tun->u.tun_erspan.u.v1_index = + opt->erspan.v1.index = ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX])); - e->flags |= (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX); + opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX); } if (tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]) { - tun->u.tun_erspan.u.v2.hwid = + opt->erspan.v2.hwid = mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]); - e->flags |= (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID); + opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID); } if (tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]) { - tun->u.tun_erspan.u.v2.dir = + opt->erspan.v2.dir = mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]); - e->flags |= (1u << NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR); + opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR); } + list_add_tail(&opt->list, &opts->opts_list); + return 0; } @@ -450,22 +542,36 @@ static int nftnl_obj_tunnel_opts_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; } +struct nftnl_tunnel_opts *nftnl_tunnel_opts_alloc(enum nftnl_tunnel_type type); + static int nftnl_obj_tunnel_parse_opts(struct nftnl_obj *e, struct nlattr *attr, struct nftnl_obj_tunnel *tun) { struct nlattr *tb[NFTA_TUNNEL_KEY_OPTS_MAX + 1] = {}; + struct nftnl_tunnel_opts *opts = NULL; int err = 0; if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_opts_cb, tb) < 0) return -1; if (tb[NFTA_TUNNEL_KEY_OPTS_VXLAN]) { - err = nftnl_obj_tunnel_parse_vxlan(e, tb[NFTA_TUNNEL_KEY_OPTS_VXLAN], - tun); + opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_VXLAN); + if (!opts) + return -1; + + err = nftnl_obj_tunnel_parse_vxlan(opts, tb[NFTA_TUNNEL_KEY_OPTS_VXLAN]); } else if (tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN]) { - err = nftnl_obj_tunnel_parse_erspan(e, tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN], - tun); + opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_ERSPAN); + if (!opts) + return -1; + + err = nftnl_obj_tunnel_parse_erspan(opts, tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN]); + } + + if (opts) { + tun->tun_opts = opts; + e->flags |= (1 << NFTNL_OBJ_TUNNEL_OPTS); } return err; @@ -532,6 +638,215 @@ static int nftnl_obj_tunnel_snprintf(char *buf, size_t len, return snprintf(buf, len, "id %u ", tun->id); } +EXPORT_SYMBOL(nftnl_tunnel_opts_alloc); +struct nftnl_tunnel_opts *nftnl_tunnel_opts_alloc(enum nftnl_tunnel_type type) +{ + struct nftnl_tunnel_opts *opts; + + switch (type) { + case NFTNL_TUNNEL_TYPE_VXLAN: + case NFTNL_TUNNEL_TYPE_ERSPAN: + break; + default: + errno = EOPNOTSUPP; + return NULL; + } + + opts = calloc(1, sizeof(struct nftnl_tunnel_opts)); + if (!opts) + return NULL; + + opts->type = type; + INIT_LIST_HEAD(&opts->opts_list); + + return opts; +} + +EXPORT_SYMBOL(nftnl_tunnel_opts_add); +int nftnl_tunnel_opts_add(struct nftnl_tunnel_opts *opts, + struct nftnl_tunnel_opt *opt) +{ + if (opt->type != opts->type) { + errno = EOPNOTSUPP; + return -1; + } + + switch (opts->type) { + case NFTNL_TUNNEL_TYPE_VXLAN: + case NFTNL_TUNNEL_TYPE_ERSPAN: + if (opts->num > 0) { + errno = EEXIST; + return -1; + } + break; + default: + errno = EOPNOTSUPP; + return -1; + } + + list_add_tail(&opt->list, &opts->opts_list); + + return 0; +} + +EXPORT_SYMBOL(nftnl_tunnel_opts_free); +void nftnl_tunnel_opts_free(struct nftnl_tunnel_opts *opts) +{ + struct nftnl_tunnel_opt *opt, *next; + + list_for_each_entry_safe(opt, next, &opts->opts_list, list) { + switch(opts->type) { + case NFTNL_TUNNEL_TYPE_VXLAN: + case NFTNL_TUNNEL_TYPE_ERSPAN: + list_del(&opt->list); + xfree(opt); + break; + } + } +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_alloc); +struct nftnl_tunnel_opt *nftnl_tunnel_opt_alloc(enum nftnl_tunnel_type type) +{ + struct nftnl_tunnel_opt *opt; + + switch (type) { + case NFTNL_TUNNEL_TYPE_VXLAN: + case NFTNL_TUNNEL_TYPE_ERSPAN: + break; + default: + errno = EOPNOTSUPP; + return NULL; + } + + opt = calloc(1, sizeof(struct nftnl_tunnel_opt)); + if (!opt) + return NULL; + + opt->type = type; + + return opt; +} + +static int nftnl_tunnel_opt_vxlan_set(struct nftnl_tunnel_opt *opt, uint16_t type, + const void *data, uint32_t data_len) +{ + switch (type) { + case NFTNL_TUNNEL_VXLAN_GBP: + memcpy(&opt->vxlan.gbp, data, data_len); + break; + default: + errno = EOPNOTSUPP; + return -1; + } + + opt->flags |= (1 << type); + + return 0; +} + +static int nftnl_tunnel_opt_erspan_set(struct nftnl_tunnel_opt *opt, uint16_t type, + const void *data, uint32_t data_len) +{ + switch (type) { + case NFTNL_TUNNEL_ERSPAN_VERSION: + memcpy(&opt->erspan.version, data, data_len); + break; + case NFTNL_TUNNEL_ERSPAN_V1_INDEX: + memcpy(&opt->erspan.v1.index, data, data_len); + break; + case NFTNL_TUNNEL_ERSPAN_V2_HWID: + memcpy(&opt->erspan.v2.hwid, data, data_len); + break; + case NFTNL_TUNNEL_ERSPAN_V2_DIR: + memcpy(&opt->erspan.v2.dir, data, data_len); + break; + default: + errno = EOPNOTSUPP; + return -1; + } + + opt->flags |= (1 << type); + + return 0; +} + +EXPORT_SYMBOL(nftnl_tunnel_opt_set); +int nftnl_tunnel_opt_set(struct nftnl_tunnel_opt *opt, uint16_t type, + const void *data, uint32_t data_len) +{ + switch (opt->type) { + case NFTNL_TUNNEL_TYPE_VXLAN: + return nftnl_tunnel_opt_vxlan_set(opt, type, data, data_len); + case NFTNL_TUNNEL_TYPE_ERSPAN: + return nftnl_tunnel_opt_erspan_set(opt, type, data, data_len); + default: + errno = EOPNOTSUPP; + return -1; + } + + return 0; +} + +static void nftnl_tunnel_opt_build_vxlan(struct nlmsghdr *nlh, + const struct nftnl_tunnel_opt *opt) +{ + struct nlattr *nest_inner; + + if (opt->flags & (1 << NFTNL_TUNNEL_VXLAN_GBP)) { + nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_VXLAN); + mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_VXLAN_GBP, + htonl(opt->vxlan.gbp)); + mnl_attr_nest_end(nlh, nest_inner); + } +} + +static void nftnl_tunnel_opt_build_erspan(struct nlmsghdr *nlh, + const struct nftnl_tunnel_opt *opt) +{ + struct nlattr *nest_inner; + + if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_VERSION) && + (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX) || + (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID) && + opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR)))) { + nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_ERSPAN); + mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_VERSION, + htonl(opt->erspan.version)); + if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX)) + mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX, + htonl(opt->erspan.v1.index)); + if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID)) + mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID, + opt->erspan.v2.hwid); + if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR)) + mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR, + opt->erspan.v2.dir); + mnl_attr_nest_end(nlh, nest_inner); + } +} + +void nftnl_tunnel_opts_build(struct nlmsghdr *nlh, + struct nftnl_tunnel_opts *opts) +{ + const struct nftnl_tunnel_opt *opt; + struct nlattr *nest; + + nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS); + + list_for_each_entry(opt, &opts->opts_list, list) { + switch (opts->type) { + case NFTNL_TUNNEL_TYPE_VXLAN: + nftnl_tunnel_opt_build_vxlan(nlh, opt); + break; + case NFTNL_TUNNEL_TYPE_ERSPAN: + nftnl_tunnel_opt_build_erspan(nlh, opt); + break; + } + } + mnl_attr_nest_end(nlh, nest); +} + static struct attr_policy obj_tunnel_attr_policy[__NFTNL_OBJ_TUNNEL_MAX] = { [NFTNL_OBJ_TUNNEL_ID] = { .maxlen = sizeof(uint32_t) }, [NFTNL_OBJ_TUNNEL_IPV4_SRC] = { .maxlen = sizeof(uint32_t) }, @@ -544,11 +859,7 @@ static struct attr_policy obj_tunnel_attr_policy[__NFTNL_OBJ_TUNNEL_MAX] = { [NFTNL_OBJ_TUNNEL_FLAGS] = { .maxlen = sizeof(uint32_t) }, [NFTNL_OBJ_TUNNEL_TOS] = { .maxlen = sizeof(uint8_t) }, [NFTNL_OBJ_TUNNEL_TTL] = { .maxlen = sizeof(uint8_t) }, - [NFTNL_OBJ_TUNNEL_VXLAN_GBP] = { .maxlen = sizeof(uint32_t) }, - [NFTNL_OBJ_TUNNEL_ERSPAN_VERSION] = { .maxlen = sizeof(uint32_t) }, - [NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX] = { .maxlen = sizeof(uint32_t) }, - [NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID] = { .maxlen = sizeof(uint8_t) }, - [NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR] = { .maxlen = sizeof(uint8_t) }, + [NFTNL_OBJ_TUNNEL_OPTS] = { .maxlen = sizeof(struct nftnl_tunnel_opts *) }, }; struct obj_ops obj_ops_tunnel = { diff --git a/src/object.c b/src/object.c index bfcceb9..275a202 100644 --- a/src/object.c +++ b/src/object.c @@ -55,6 +55,10 @@ void nftnl_obj_free(const struct nftnl_obj *obj) xfree(obj->name); if (obj->flags & (1 << NFTNL_OBJ_USERDATA)) xfree(obj->user.data); + if (obj->flags & (1 << NFTNL_OBJ_TUNNEL_OPTS)) { + nftnl_tunnel_opts_free(obj->data.tunnel.tun_opts); + xfree(obj->data.tunnel.tun_opts); + } xfree(obj); } |