diff options
-rw-r--r-- | include/cache.h | 1 | ||||
-rw-r--r-- | include/mnl.h | 3 | ||||
-rw-r--r-- | src/cache.c | 55 | ||||
-rw-r--r-- | src/mnl.c | 14 | ||||
-rw-r--r-- | src/netlink.c | 3 | ||||
-rwxr-xr-x | tests/shell/testcases/listing/0020flowtable_0 | 51 |
6 files changed, 103 insertions, 24 deletions
diff --git a/include/cache.h b/include/cache.h index 3a9a5e81..d185f3cf 100644 --- a/include/cache.h +++ b/include/cache.h @@ -54,6 +54,7 @@ struct nft_cache_filter { const char *table; const char *chain; const char *set; + const char *ft; } list; struct { diff --git a/include/mnl.h b/include/mnl.h index 8659879c..b006192c 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -77,7 +77,8 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd, int mnl_nft_obj_del(struct netlink_ctx *ctx, struct cmd *cmd, int type); struct nftnl_flowtable_list * -mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table); +mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, + const char *table, const char *ft); int mnl_nft_flowtable_add(struct netlink_ctx *ctx, struct cmd *cmd, unsigned int flags); diff --git a/src/cache.c b/src/cache.c index 38a34ee3..6494e474 100644 --- a/src/cache.c +++ b/src/cache.c @@ -229,6 +229,15 @@ static unsigned int evaluate_cache_list(struct nft_ctx *nft, struct cmd *cmd, case CMD_OBJ_MAPS: flags |= NFT_CACHE_TABLE | NFT_CACHE_SET; break; + case CMD_OBJ_FLOWTABLE: + if (filter && + cmd->handle.table.name && + cmd->handle.flowtable.name) { + filter->list.family = cmd->handle.family; + filter->list.table = cmd->handle.table.name; + filter->list.ft = cmd->handle.flowtable.name; + } + /* fall through */ case CMD_OBJ_FLOWTABLES: flags |= NFT_CACHE_TABLE | NFT_CACHE_FLOWTABLE; break; @@ -681,10 +690,19 @@ struct ft_cache_dump_ctx { static int ft_cache_cb(struct nftnl_flowtable *nlf, void *arg) { struct ft_cache_dump_ctx *ctx = arg; - const char *ft_name; struct flowtable *ft; + const char *ft_table; + const char *ft_name; + uint32_t ft_family; uint32_t hash; + ft_family = nftnl_flowtable_get_u32(nlf, NFTNL_FLOWTABLE_FAMILY); + ft_table = nftnl_flowtable_get_str(nlf, NFTNL_FLOWTABLE_TABLE); + + if (ft_family != ctx->table->handle.family || + strcmp(ft_table, ctx->table->handle.table.name)) + return 0; + ft = netlink_delinearize_flowtable(ctx->nlctx, nlf); if (!ft) return -1; @@ -693,6 +711,8 @@ static int ft_cache_cb(struct nftnl_flowtable *nlf, void *arg) hash = djb_hash(ft_name) % NFT_CACHE_HSIZE; cache_add(&ft->cache, &ctx->table->ft_cache, hash); + nftnl_flowtable_list_del(nlf); + nftnl_flowtable_free(nlf); return 0; } @@ -708,13 +728,21 @@ static int ft_cache_init(struct netlink_ctx *ctx, struct table *table, return 0; } -static struct nftnl_flowtable_list *ft_cache_dump(struct netlink_ctx *ctx, - const struct table *table) +static struct nftnl_flowtable_list * +ft_cache_dump(struct netlink_ctx *ctx, const struct nft_cache_filter *filter) { struct nftnl_flowtable_list *ft_list; + int family = NFPROTO_UNSPEC; + const char *table = NULL; + const char *ft = NULL; - ft_list = mnl_nft_flowtable_dump(ctx, table->handle.family, - table->handle.table.name); + if (filter) { + family = filter->list.family; + table = filter->list.table; + ft = filter->list.ft; + } + + ft_list = mnl_nft_flowtable_dump(ctx, family, table, ft); if (!ft_list) { if (errno == EINTR) return NULL; @@ -801,6 +829,13 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags, goto cache_fails; } } + if (flags & NFT_CACHE_FLOWTABLE_BIT) { + ft_list = ft_cache_dump(ctx, filter); + if (!ft_list) { + ret = -1; + goto cache_fails; + } + } list_for_each_entry(table, &ctx->nft->cache.table_cache.list, cache.list) { if (flags & NFT_CACHE_SET_BIT) { @@ -849,15 +884,7 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags, } } if (flags & NFT_CACHE_FLOWTABLE_BIT) { - ft_list = ft_cache_dump(ctx, table); - if (!ft_list) { - ret = -1; - goto cache_fails; - } ret = ft_cache_init(ctx, table, ft_list); - - nftnl_flowtable_list_free(ft_list); - if (ret < 0) { ret = -1; goto cache_fails; @@ -903,6 +930,8 @@ static int cache_init_objects(struct netlink_ctx *ctx, unsigned int flags, cache_fails: if (set_list) nftnl_set_list_free(set_list); + if (ft_list) + nftnl_flowtable_list_free(ft_list); if (flags & NFT_CACHE_CHAIN_BIT) nftnl_chain_list_free(chain_list); @@ -1826,11 +1826,13 @@ err_free: } struct nftnl_flowtable_list * -mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table) +mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, + const char *table, const char *ft) { struct nftnl_flowtable_list *nln_list; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nftnl_flowtable *n; + int flags = NLM_F_DUMP; struct nlmsghdr *nlh; int ret; @@ -1838,10 +1840,14 @@ mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table) if (n == NULL) memory_allocation_error(); - nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, - NLM_F_DUMP, ctx->seqnum); if (table != NULL) nftnl_flowtable_set_str(n, NFTNL_FLOWTABLE_TABLE, table); + if (ft) { + nftnl_flowtable_set_str(n, NFTNL_FLOWTABLE_NAME, ft); + flags = NLM_F_ACK; + } + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, + flags, ctx->seqnum); nftnl_flowtable_nlmsg_build_payload(nlh, n); nftnl_flowtable_free(n); @@ -1850,7 +1856,7 @@ mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table) memory_allocation_error(); ret = nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, flowtable_cb, nln_list); - if (ret < 0) + if (ret < 0 && errno != ENOENT) goto err; return nln_list; diff --git a/src/netlink.c b/src/netlink.c index f74c0383..359d801c 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1721,7 +1721,8 @@ int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h) struct nftnl_flowtable_list *flowtable_cache; int err; - flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family, h->table.name); + flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family, + h->table.name, NULL); if (flowtable_cache == NULL) { if (errno == EINTR) return -1; diff --git a/tests/shell/testcases/listing/0020flowtable_0 b/tests/shell/testcases/listing/0020flowtable_0 index 2f0a98d1..47488d8e 100755 --- a/tests/shell/testcases/listing/0020flowtable_0 +++ b/tests/shell/testcases/listing/0020flowtable_0 @@ -2,19 +2,60 @@ # list only the flowtable asked for with table +FLOWTABLES="flowtable f { + hook ingress priority filter + devices = { lo } +} +flowtable f2 { + hook ingress priority filter + devices = { d0 } +}" + +RULESET="table inet filter { + $FLOWTABLES +} +table ip filter { + $FLOWTABLES +}" + EXPECTED="table inet filter { flowtable f { hook ingress priority filter devices = { lo } } }" +EXPECTED2="table ip filter { + flowtable f2 { + hook ingress priority filter + devices = { d0 } + } +}" +EXPECTED3="table ip filter { + flowtable f { + hook ingress priority filter + devices = { lo } + } + flowtable f2 { + hook ingress priority filter + devices = { d0 } + } +}" + +ip link add d0 type dummy || { + echo "Skipping, no dummy interface available" + exit 0 +} +trap "ip link del d0" EXIT set -e -$NFT -f - <<< "$EXPECTED" +$NFT -f - <<< "$RULESET" GET="$($NFT list flowtable inet filter f)" -if [ "$EXPECTED" != "$GET" ] ; then - $DIFF -u <(echo "$EXPECTED") <(echo "$GET") - exit 1 -fi +$DIFF -u <(echo "$EXPECTED") <(echo "$GET") + +GET="$($NFT list flowtable ip filter f2)" +$DIFF -u <(echo "$EXPECTED2") <(echo "$GET") + +GET="$($NFT list flowtables ip)" +$DIFF -u <(echo "$EXPECTED3") <(echo "$GET") |