summaryrefslogtreecommitdiffstats
path: root/src/netlink.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-05-19 12:18:04 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2014-05-19 12:18:06 +0200
commit337636fc670eaed5c7146f99af8719018f63fe3b (patch)
tree7ddacf7ef5052951706748180432e6c0605319b7 /src/netlink.c
parentef184c4e844eac8c3eda0c8c6fc1370078a9d66a (diff)
src: add set netlink message to the batch
This patch moves the netlink set messages to the batch that contains the rules. This helps to speed up rule-set restoration time by changing the operational. To achieve this, an internal set ID which is unique to the batch is allocated as suggested by Patrick. To retain backward compatibility, nft initially guesses if the kernel supports set in batches. Otherwise, it falls back to the previous (slowier) operational. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink.c')
-rw-r--r--src/netlink.c170
1 files changed, 162 insertions, 8 deletions
diff --git a/src/netlink.c b/src/netlink.c
index 22150f20..f4c512cc 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -180,6 +180,8 @@ struct nft_set *alloc_nft_set(const struct handle *h)
nft_set_attr_set_str(nls, NFT_SET_ATTR_TABLE, h->table);
if (h->set != NULL)
nft_set_attr_set_str(nls, NFT_SET_ATTR_NAME, h->set);
+ if (h->set_id)
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_ID, h->set_id);
return nls;
}
@@ -842,8 +844,8 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
return set;
}
-int netlink_add_set(struct netlink_ctx *ctx, const struct handle *h,
- struct set *set)
+static int netlink_add_set_compat(struct netlink_ctx *ctx,
+ const struct handle *h, struct set *set)
{
struct nft_set *nls;
int err;
@@ -874,8 +876,57 @@ int netlink_add_set(struct netlink_ctx *ctx, const struct handle *h,
return err;
}
-int netlink_delete_set(struct netlink_ctx *ctx, const struct handle *h,
- const struct location *loc)
+/* internal ID to uniquely identify a set in the batch */
+static uint32_t set_id;
+
+static int netlink_add_set_batch(struct netlink_ctx *ctx,
+ const struct handle *h, struct set *set)
+{
+ struct nft_set *nls;
+ int err;
+
+ nls = alloc_nft_set(h);
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_FLAGS, set->flags);
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_KEY_TYPE,
+ dtype_map_to_kernel(set->keytype));
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_KEY_LEN,
+ set->keylen / BITS_PER_BYTE);
+ if (set->flags & NFT_SET_MAP) {
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_TYPE,
+ dtype_map_to_kernel(set->datatype));
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_LEN,
+ set->datalen / BITS_PER_BYTE);
+ }
+ set->handle.set_id = ++set_id;
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_ID, set->handle.set_id);
+ netlink_dump_set(nls);
+
+ err = mnl_nft_set_batch_add(nf_sock, nls, NLM_F_EXCL, ctx->seqnum);
+ if (err < 0) {
+ netlink_io_error(ctx, &set->location, "Could not add set: %s",
+ strerror(errno));
+ }
+ nft_set_free(nls);
+
+ return err;
+}
+
+int netlink_add_set(struct netlink_ctx *ctx, const struct handle *h,
+ struct set *set)
+{
+ int ret;
+
+ if (ctx->batch_supported)
+ ret = netlink_add_set_batch(ctx, h, set);
+ else
+ ret = netlink_add_set_compat(ctx, h, set);
+
+ return ret;
+}
+
+static int netlink_del_set_compat(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct location *loc)
{
struct nft_set *nls;
int err;
@@ -890,6 +941,36 @@ int netlink_delete_set(struct netlink_ctx *ctx, const struct handle *h,
return err;
}
+static int netlink_del_set_batch(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct location *loc)
+{
+ struct nft_set *nls;
+ int err;
+
+ nls = alloc_nft_set(h);
+ err = mnl_nft_set_batch_del(nf_sock, nls, 0, ctx->seqnum);
+ nft_set_free(nls);
+
+ if (err < 0)
+ netlink_io_error(ctx, loc, "Could not delete set: %s",
+ strerror(errno));
+ return err;
+}
+
+int netlink_delete_set(struct netlink_ctx *ctx, const struct handle *h,
+ const struct location *loc)
+{
+ int ret;
+
+ if (ctx->batch_supported)
+ ret = netlink_del_set_batch(ctx, h, loc);
+ else
+ ret = netlink_del_set_compat(ctx, h, loc);
+
+ return ret;
+}
+
static int list_set_cb(struct nft_set *nls, void *arg)
{
struct netlink_ctx *ctx = arg;
@@ -946,8 +1027,29 @@ static void alloc_setelem_cache(const struct expr *set, struct nft_set *nls)
}
}
-int netlink_add_setelems(struct netlink_ctx *ctx, const struct handle *h,
- const struct expr *expr)
+static int netlink_add_setelems_batch(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct expr *expr)
+{
+ struct nft_set *nls;
+ int err;
+
+ nls = alloc_nft_set(h);
+ alloc_setelem_cache(expr, nls);
+ netlink_dump_set(nls);
+
+ err = mnl_nft_setelem_batch_add(nf_sock, nls, 0, ctx->seqnum);
+ nft_set_free(nls);
+ if (err < 0)
+ netlink_io_error(ctx, &expr->location,
+ "Could not add set elements: %s",
+ strerror(errno));
+ return err;
+}
+
+static int netlink_add_setelems_compat(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct expr *expr)
{
struct nft_set *nls;
int err;
@@ -965,8 +1067,42 @@ int netlink_add_setelems(struct netlink_ctx *ctx, const struct handle *h,
return err;
}
-int netlink_delete_setelems(struct netlink_ctx *ctx, const struct handle *h,
- const struct expr *expr)
+int netlink_add_setelems(struct netlink_ctx *ctx, const struct handle *h,
+ const struct expr *expr)
+{
+ int ret;
+
+ if (ctx->batch_supported)
+ ret = netlink_add_setelems_batch(ctx, h, expr);
+ else
+ ret = netlink_add_setelems_compat(ctx, h, expr);
+
+ return ret;
+}
+
+static int netlink_del_setelems_batch(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct expr *expr)
+{
+ struct nft_set *nls;
+ int err;
+
+ nls = alloc_nft_set(h);
+ alloc_setelem_cache(expr, nls);
+ netlink_dump_set(nls);
+
+ err = mnl_nft_setelem_batch_del(nf_sock, nls, 0, ctx->seqnum);
+ nft_set_free(nls);
+ if (err < 0)
+ netlink_io_error(ctx, &expr->location,
+ "Could not delete set elements: %s",
+ strerror(errno));
+ return err;
+}
+
+static int netlink_del_setelems_compat(struct netlink_ctx *ctx,
+ const struct handle *h,
+ const struct expr *expr)
{
struct nft_set *nls;
int err;
@@ -1031,6 +1167,19 @@ out:
return 0;
}
+int netlink_delete_setelems(struct netlink_ctx *ctx, const struct handle *h,
+ const struct expr *expr)
+{
+ int ret;
+
+ if (ctx->batch_supported)
+ ret = netlink_del_setelems_batch(ctx, h, expr);
+ else
+ ret = netlink_del_setelems_compat(ctx, h, expr);
+
+ return ret;
+}
+
static int list_setelem_cb(struct nft_set_elem *nlse, void *arg)
{
struct netlink_ctx *ctx = arg;
@@ -1603,3 +1752,8 @@ int netlink_monitor(struct netlink_mon_handler *monhandler)
return mnl_nft_event_listener(nf_mon_sock, netlink_events_cb,
monhandler);
}
+
+bool netlink_batch_supported(void)
+{
+ return mnl_batch_supported(nf_sock);
+}