summaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-09-22 20:41:03 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2013-09-23 20:28:22 +0200
commita72315d2bad47d99a18376290dd62336ca94ed95 (patch)
treef0c194f4ac38b1363b58fc33cd83c2b547b52bcb /src/main.c
parente391b72b611403d184bbb26e3d076d543c7ea7c6 (diff)
src: add rule batching support
This patch allows nft to put all rule update messages into one single batch that is sent to the kernel if `-f' option is used. In order to provide fine grain error reporting, I decided to to correlate the netlink message sequence number with the correspoding command sequence number, which is the same. Thus, nft can identify what rules trigger problems inside a batch and report them accordingly. Moreover, to avoid playing buffer size games at batch building stage, ie. guess what is the final size of the batch for this ruleset update will be, this patch collects batch pages that are converted to iovec to ensure linearization when the batch is sent to the kernel. This reduces the amount of unnecessary memory usage that is allocated for the batch. This patch uses the libmnl nlmsg batching infrastructure and it requires the kernel patch entitled (netfilter: nfnetlink: add batch support and use it from nf_tables). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c68
1 files changed, 50 insertions, 18 deletions
diff --git a/src/main.c b/src/main.c
index 1a40b9ee..3ddcb713 100644
--- a/src/main.c
+++ b/src/main.c
@@ -24,6 +24,7 @@
#include <rule.h>
#include <netlink.h>
#include <erec.h>
+#include <mnl.h>
unsigned int numeric_output;
unsigned int handle_output;
@@ -149,10 +150,57 @@ static const struct input_descriptor indesc_cmdline = {
.name = "<cmdline>",
};
+static int nft_netlink(struct parser_state *state, struct list_head *msgs)
+{
+ struct netlink_ctx ctx;
+ struct cmd *cmd, *next;
+ struct mnl_err *err, *tmp;
+ LIST_HEAD(err_list);
+ int ret = 0;
+
+ mnl_batch_begin();
+ list_for_each_entry(cmd, &state->cmds, list) {
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.msgs = msgs;
+ ctx.seqnum = cmd->seqnum = mnl_seqnum_alloc();
+ init_list_head(&ctx.list);
+ ret = do_command(&ctx, cmd);
+ if (ret < 0)
+ return ret;
+ }
+ mnl_batch_end();
+
+ if (mnl_batch_ready())
+ ret = netlink_batch_send(&err_list);
+ else {
+ mnl_batch_reset();
+ goto out;
+ }
+
+ list_for_each_entry_safe(err, tmp, &err_list, head) {
+ list_for_each_entry(cmd, &state->cmds, list) {
+ if (err->seqnum == cmd->seqnum) {
+ netlink_io_error(&ctx, &cmd->location,
+ "Could not process rule in batch: %s",
+ strerror(err->err));
+ mnl_err_list_free(err);
+ break;
+ }
+ }
+ }
+out:
+ list_for_each_entry_safe(cmd, next, &state->cmds, list) {
+ list_del(&cmd->list);
+ cmd_free(cmd);
+ }
+
+ return ret;
+}
+
int nft_run(void *scanner, struct parser_state *state, struct list_head *msgs)
{
struct eval_ctx ctx;
- int ret;
+ int ret = 0;
ret = nft_parse(scanner, state);
if (ret != 0)
@@ -163,23 +211,7 @@ int nft_run(void *scanner, struct parser_state *state, struct list_head *msgs)
if (evaluate(&ctx, &state->cmds) < 0)
return -1;
- {
- struct netlink_ctx ctx;
- struct cmd *cmd, *next;
-
- list_for_each_entry_safe(cmd, next, &state->cmds, list) {
- memset(&ctx, 0, sizeof(ctx));
- ctx.msgs = msgs;
- init_list_head(&ctx.list);
- ret = do_command(&ctx, cmd);
- list_del(&cmd->list);
- cmd_free(cmd);
- if (ret < 0)
- return ret;
- }
- }
-
- return 0;
+ return nft_netlink(state, msgs);
}
int main(int argc, char * const *argv)