From patchwork Tue Jan 23 12:16:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 864742 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zQnN411dqz9t3n for ; Tue, 23 Jan 2018 23:16:36 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751402AbeAWMQd (ORCPT ); Tue, 23 Jan 2018 07:16:33 -0500 Received: from mail.us.es ([193.147.175.20]:44754 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751323AbeAWMQa (ORCPT ); Tue, 23 Jan 2018 07:16:30 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id 57ADC2519A2 for ; Tue, 23 Jan 2018 13:16:28 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id 4103BDA39F for ; Tue, 23 Jan 2018 13:16:28 +0100 (CET) Received: by antivirus1-rhel7.int (Postfix, from userid 99) id 361C0DA863; Tue, 23 Jan 2018 13:16:28 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on antivirus1-rhel7.int X-Spam-Level: X-Spam-Status: No, score=-108.2 required=7.5 tests=ALL_TRUSTED,BAYES_50, SMTPAUTH_US2,USER_IN_WHITELIST autolearn=disabled version=3.4.1 Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id C8AA9DA7E0 for ; Tue, 23 Jan 2018 13:16:25 +0100 (CET) Received: from 192.168.1.97 (192.168.1.97) by antivirus1-rhel7.int (F-Secure/fsigk_smtp/550/antivirus1-rhel7.int); Tue, 23 Jan 2018 13:16:25 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/550/antivirus1-rhel7.int) Received: from salvia.here (129.166.216.87.static.jazztel.es [87.216.166.129]) (Authenticated sender: pneira@us.es) by entrada.int (Postfix) with ESMTPA id 6F15B41E4817 for ; Tue, 23 Jan 2018 13:16:25 +0100 (CET) X-SMTPAUTHUS: auth mail.us.es From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nft 1/6] src: support for flowtable listing Date: Tue, 23 Jan 2018 13:16:17 +0100 Message-Id: <20180123121622.16287-1-pablo@netfilter.org> X-Mailer: git-send-email 2.11.0 X-Virus-Scanned: ClamAV using ClamSMTP Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch allows you to dump existing flowtable. # nft list ruleset table ip x { flowtable x { hook ingress priority 10 devices = { eth0, tap0 } } } You can also list existing flowtables via: # nft list flowtables table ip x { flowtable x { hook ingress priority 10 devices = { eth0, tap0 } } } You need a Linux kernel >= 4.16-rc to test this new feature. Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_tables.h | 6 ++ include/mnl.h | 3 + include/netlink.h | 4 ++ include/rule.h | 24 +++++++ src/evaluate.c | 1 + src/mnl.c | 58 +++++++++++++++++ src/netlink.c | 65 +++++++++++++++++++ src/parser_bison.y | 6 ++ src/rule.c | 122 ++++++++++++++++++++++++++++++++++++ src/scanner.l | 2 + 10 files changed, 291 insertions(+) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 2efbf9744c2a..b2d36004b85d 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -92,6 +92,9 @@ enum nft_verdicts { * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes) * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes) * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum nft_obj_attributes) + * @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes) + * @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes) + * @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes) */ enum nf_tables_msg_types { NFT_MSG_NEWTABLE, @@ -116,6 +119,9 @@ enum nf_tables_msg_types { NFT_MSG_GETOBJ, NFT_MSG_DELOBJ, NFT_MSG_GETOBJ_RESET, + NFT_MSG_NEWFLOWTABLE, + NFT_MSG_GETFLOWTABLE, + NFT_MSG_DELFLOWTABLE, NFT_MSG_MAX, }; diff --git a/include/mnl.h b/include/mnl.h index 4662cd04df9b..4475e7f872d9 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -89,6 +89,9 @@ int mnl_nft_obj_batch_add(struct nftnl_obj *nln, struct nftnl_batch *batch, int mnl_nft_obj_batch_del(struct nftnl_obj *nln, struct nftnl_batch *batch, unsigned int flags, uint32_t seqnum); +struct nftnl_flowtable_list * +mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table); + struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx, uint32_t family); int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask, diff --git a/include/netlink.h b/include/netlink.h index 0d71a6b96d82..bca59bbd9ebe 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -181,6 +181,10 @@ extern int netlink_add_obj(struct netlink_ctx *ctx, const struct handle *h, extern int netlink_delete_obj(struct netlink_ctx *ctx, const struct handle *h, struct location *loc, uint32_t type); +extern int netlink_list_flowtables(struct netlink_ctx *ctx, + const struct handle *h, + const struct location *loc); + extern void netlink_dump_chain(const struct nftnl_chain *nlc, struct netlink_ctx *ctx); extern void netlink_dump_rule(const struct nftnl_rule *nlr, diff --git a/include/rule.h b/include/rule.h index 4e5a349a806a..5ee5389a6c36 100644 --- a/include/rule.h +++ b/include/rule.h @@ -35,6 +35,7 @@ struct position_spec { * @chain: chain name (chains and rules only) * @set: set name (sets only) * @obj: stateful object name (stateful object only) + * @flowtable: flow table name (flow table only) * @handle: rule handle (rules only) * @position: rule position (rules only) * @set_id: set ID (sets only) @@ -45,6 +46,7 @@ struct handle { const char *chain; const char *set; const char *obj; + const char *flowtable; struct handle_spec handle; struct position_spec position; uint32_t set_id; @@ -98,6 +100,7 @@ enum table_flags { * @chains: chains contained in the table * @sets: sets contained in the table * @objs: stateful objects contained in the table + * @flowtables: flow tables contained in the table * @flags: table flags * @refcnt: table reference counter */ @@ -109,6 +112,7 @@ struct table { struct list_head chains; struct list_head sets; struct list_head objs; + struct list_head flowtables; enum table_flags flags; unsigned int refcnt; }; @@ -313,6 +317,24 @@ void obj_print_plain(const struct obj *obj, struct output_ctx *octx); const char *obj_type_name(uint32_t type); uint32_t obj_type_to_cmd(uint32_t type); +struct flowtable { + struct list_head list; + struct handle handle; + struct location location; + unsigned int hooknum; + int priority; + const char **dev_array; + int dev_array_len; + unsigned int refcnt; +}; + +extern struct flowtable *flowtable_alloc(const struct location *loc); +extern struct flowtable *flowtable_get(struct flowtable *flowtable); +extern void flowtable_free(struct flowtable *flowtable); +extern void flowtable_add_hash(struct flowtable *flowtable, struct table *table); + +void flowtable_print(const struct flowtable *n, struct output_ctx *octx); + /** * enum cmd_ops - command operations * @@ -371,6 +393,7 @@ enum cmd_ops { * @CMD_OBJ_QUOTAS: multiple quotas * @CMD_OBJ_LIMIT: limit * @CMD_OBJ_LIMITS: multiple limits + * @CMD_OBJ_FLOWTABLES: flow tables */ enum cmd_obj { CMD_OBJ_INVALID, @@ -397,6 +420,7 @@ enum cmd_obj { CMD_OBJ_CT_HELPERS, CMD_OBJ_LIMIT, CMD_OBJ_LIMITS, + CMD_OBJ_FLOWTABLES, }; struct markup { diff --git a/src/evaluate.c b/src/evaluate.c index 2da589c01a62..a58fca9e6362 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -3193,6 +3193,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) case CMD_OBJ_CT_HELPERS: case CMD_OBJ_LIMITS: case CMD_OBJ_SETS: + case CMD_OBJ_FLOWTABLES: if (cmd->handle.table == NULL) return 0; if (table_lookup(&cmd->handle, ctx->cache) == NULL) diff --git a/src/mnl.c b/src/mnl.c index 5587e1589cda..e70b0cdeb723 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -953,6 +954,63 @@ int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls) return nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, set_elem_cb, nls); } +static int flowtable_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nftnl_flowtable_list *nln_list = data; + struct nftnl_flowtable *n; + + if (check_genid(nlh) < 0) + return MNL_CB_ERROR; + + n = nftnl_flowtable_alloc(); + if (n == NULL) + memory_allocation_error(); + + if (nftnl_flowtable_nlmsg_parse(nlh, n) < 0) + goto err_free; + + nftnl_flowtable_list_add_tail(n, nln_list); + return MNL_CB_OK; + +err_free: + nftnl_flowtable_free(n); + return MNL_CB_OK; +} + +struct nftnl_flowtable_list * +mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table) +{ + struct nftnl_flowtable_list *nln_list; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nftnl_flowtable *n; + struct nlmsghdr *nlh; + int ret; + + n = nftnl_flowtable_alloc(); + if (n == NULL) + memory_allocation_error(); + + nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETFLOWTABLE, family, + NLM_F_DUMP | NLM_F_ACK, ctx->seqnum); + if (table != NULL) + nftnl_flowtable_set_str(n, NFTNL_FLOWTABLE_TABLE, table); + nftnl_flowtable_nlmsg_build_payload(nlh, n); + nftnl_flowtable_free(n); + + nln_list = nftnl_flowtable_list_alloc(); + if (nln_list == NULL) + memory_allocation_error(); + + ret = nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, flowtable_cb, nln_list); + if (ret < 0) + goto err; + + return nln_list; +err: + nftnl_flowtable_list_free(nln_list); + return NULL; +} + /* * ruleset */ diff --git a/src/netlink.c b/src/netlink.c index 23f92443f8c4..7b8e48dc341d 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1815,6 +1816,70 @@ int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h, return err; } +static struct flowtable * +netlink_delinearize_flowtable(struct netlink_ctx *ctx, + struct nftnl_flowtable *nlo) +{ + struct flowtable *flowtable; + const char **dev_array; + int len = 0, i; + + flowtable = flowtable_alloc(&netlink_location); + flowtable->handle.family = + nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY); + flowtable->handle.table = + xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE)); + flowtable->handle.flowtable = + xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME)); + dev_array = nftnl_flowtable_get_array(nlo, NFTNL_FLOWTABLE_DEVICES); + while (dev_array[len] != '\0') + len++; + + flowtable->dev_array = calloc(1, len * sizeof(char *)); + for (i = 0; i < len; i++) + flowtable->dev_array[i] = xstrdup(dev_array[i]); + + flowtable->dev_array_len = len; + + flowtable->priority = + nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_PRIO); + flowtable->hooknum = + nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_HOOKNUM); + + return flowtable; +} + +static int list_flowtable_cb(struct nftnl_flowtable *nls, void *arg) +{ + struct netlink_ctx *ctx = arg; + struct flowtable *flowtable; + + flowtable = netlink_delinearize_flowtable(ctx, nls); + if (flowtable == NULL) + return -1; + list_add_tail(&flowtable->list, &ctx->list); + return 0; +} + +int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h, + const struct location *loc) +{ + struct nftnl_flowtable_list *flowtable_cache; + int err; + + flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family, h->table); + if (flowtable_cache == NULL) { + if (errno == EINTR) + return -1; + + return 0; + } + + err = nftnl_flowtable_list_foreach(flowtable_cache, list_flowtable_cb, ctx); + nftnl_flowtable_list_free(flowtable_cache); + return err; +} + int netlink_batch_send(struct netlink_ctx *ctx, struct list_head *err_list) { return mnl_batch_talk(ctx, err_list); diff --git a/src/parser_bison.y b/src/parser_bison.y index 009b801f9d6b..4cfa8076cfc4 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -247,6 +247,8 @@ int nft_lex(void *, void *, void *); %token METER "meter" %token METERS "meters" +%token FLOWTABLES "flowtables" + %token NUM "number" %token STRING "string" %token QUOTED_STRING "quoted string" @@ -1103,6 +1105,10 @@ list_cmd : TABLE table_spec { $$ = cmd_alloc(CMD_LIST, CMD_OBJ_METER, &$2, &@$, NULL); } + | FLOWTABLES ruleset_spec + { + $$ = cmd_alloc(CMD_LIST, CMD_OBJ_FLOWTABLES, &$2, &@$, NULL); + } | MAPS ruleset_spec { $$ = cmd_alloc(CMD_LIST, CMD_OBJ_MAPS, &$2, &@$, NULL); diff --git a/src/rule.c b/src/rule.c index f19197fe240d..08ea2c3c9fb5 100644 --- a/src/rule.c +++ b/src/rule.c @@ -95,6 +95,11 @@ static int cache_init_objects(struct netlink_ctx *ctx, enum cmd_ops cmd) return -1; list_splice_tail_init(&ctx->list, &table->chains); + ret = netlink_list_flowtables(ctx, &table->handle, &internal_location); + if (ret < 0) + return -1; + list_splice_tail_init(&ctx->list, &table->flowtables); + if (cmd != CMD_RESET) { ret = netlink_list_objs(ctx, &table->handle, &internal_location); if (ret < 0) @@ -719,6 +724,7 @@ struct table *table_alloc(void) init_list_head(&table->chains); init_list_head(&table->sets); init_list_head(&table->objs); + init_list_head(&table->flowtables); init_list_head(&table->scope.symbols); table->refcnt = 1; @@ -794,6 +800,7 @@ static void table_print_options(const struct table *table, const char **delim, static void table_print(const struct table *table, struct output_ctx *octx) { + struct flowtable *flowtable; struct chain *chain; struct obj *obj; struct set *set; @@ -815,6 +822,11 @@ static void table_print(const struct table *table, struct output_ctx *octx) set_print(set, octx); delim = "\n"; } + list_for_each_entry(flowtable, &table->flowtables, list) { + nft_print(octx, "%s", delim); + flowtable_print(flowtable, octx); + delim = "\n"; + } list_for_each_entry(chain, &table->chains, list) { nft_print(octx, "%s", delim); chain_print(chain, octx); @@ -1478,6 +1490,114 @@ static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type) return 0; } +struct flowtable *flowtable_alloc(const struct location *loc) +{ + struct flowtable *flowtable; + + flowtable = xzalloc(sizeof(*flowtable)); + if (loc != NULL) + flowtable->location = *loc; + + flowtable->refcnt = 1; + return flowtable; +} + +struct flowtable *flowtable_get(struct flowtable *flowtable) +{ + flowtable->refcnt++; + return flowtable; +} + +void flowtable_free(struct flowtable *flowtable) +{ + if (--flowtable->refcnt > 0) + return; + handle_free(&flowtable->handle); + xfree(flowtable); +} + +void flowtable_add_hash(struct flowtable *flowtable, struct table *table) +{ + list_add_tail(&flowtable->list, &table->flowtables); +} + +static void flowtable_print_declaration(const struct flowtable *flowtable, + struct print_fmt_options *opts, + struct output_ctx *octx) +{ + int i; + + nft_print(octx, "%sflowtable", opts->tab); + + if (opts->family != NULL) + nft_print(octx, " %s", opts->family); + + if (opts->table != NULL) + nft_print(octx, " %s", opts->table); + + nft_print(octx, " %s {%s", flowtable->handle.flowtable, opts->nl); + + nft_print(octx, "%s%shook %s priority %d%s", + opts->tab, opts->tab, "ingress", + flowtable->priority, opts->stmt_separator); + + nft_print(octx, "%s%sdevices = { ", opts->tab, opts->tab); + for (i = 0; i < flowtable->dev_array_len; i++) { + nft_print(octx, "%s", flowtable->dev_array[i]); + if (i + 1 != flowtable->dev_array_len) + nft_print(octx, ", "); + } + nft_print(octx, " }%s", opts->stmt_separator); +} + +static void do_flowtable_print(const struct flowtable *flowtable, + struct print_fmt_options *opts, + struct output_ctx *octx) +{ + flowtable_print_declaration(flowtable, opts, octx); + nft_print(octx, "%s}%s", opts->tab, opts->nl); +} + +void flowtable_print(const struct flowtable *s, struct output_ctx *octx) +{ + struct print_fmt_options opts = { + .tab = "\t", + .nl = "\n", + .stmt_separator = "\n", + }; + + do_flowtable_print(s, &opts, octx); +} + +static int do_list_flowtables(struct netlink_ctx *ctx, struct cmd *cmd) +{ + struct print_fmt_options opts = { + .tab = "\t", + .nl = "\n", + .stmt_separator = "\n", + }; + struct flowtable *flowtable; + struct table *table; + + list_for_each_entry(table, &ctx->cache->list, list) { + if (cmd->handle.family != NFPROTO_UNSPEC && + cmd->handle.family != table->handle.family) + continue; + + nft_print(ctx->octx, "table %s %s {\n", + family2str(table->handle.family), + table->handle.table); + + list_for_each_entry(flowtable, &table->flowtables, list) { + flowtable_print_declaration(flowtable, &opts, ctx->octx); + nft_print(ctx->octx, "%s}%s", opts.tab, opts.nl); + } + + nft_print(ctx->octx, "}\n"); + } + return 0; +} + static int do_list_ruleset(struct netlink_ctx *ctx, struct cmd *cmd) { unsigned int family = cmd->handle.family; @@ -1625,6 +1745,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) case CMD_OBJ_LIMIT: case CMD_OBJ_LIMITS: return do_list_obj(ctx, cmd, NFT_OBJECT_LIMIT); + case CMD_OBJ_FLOWTABLES: + return do_list_flowtables(ctx, cmd); default: BUG("invalid command object type %u\n", cmd->obj); } diff --git a/src/scanner.l b/src/scanner.l index 5402be1cc2b0..6a1f2f685615 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -296,6 +296,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "meter" { return METER; } "meters" { return METERS; } +"flowtables" { return FLOWTABLES; } + "counter" { return COUNTER; } "name" { return NAME; } "packets" { return PACKETS; } From patchwork Tue Jan 23 12:16:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 864745 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zQnNB1yyMz9t3n for ; Tue, 23 Jan 2018 23:16:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751429AbeAWMQk (ORCPT ); Tue, 23 Jan 2018 07:16:40 -0500 Received: from mail.us.es ([193.147.175.20]:44786 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751125AbeAWMQc (ORCPT ); Tue, 23 Jan 2018 07:16:32 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id DF2162519A5 for ; Tue, 23 Jan 2018 13:16:30 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id C413EDA861 for ; Tue, 23 Jan 2018 13:16:30 +0100 (CET) Received: by antivirus1-rhel7.int (Postfix, from userid 99) id B917ADA84A; Tue, 23 Jan 2018 13:16:30 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on antivirus1-rhel7.int X-Spam-Level: X-Spam-Status: No, score=-108.2 required=7.5 tests=ALL_TRUSTED,BAYES_50, SMTPAUTH_US2,USER_IN_WHITELIST autolearn=disabled version=3.4.1 Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id 3F22ADA387 for ; Tue, 23 Jan 2018 13:16:28 +0100 (CET) Received: from 192.168.1.97 (192.168.1.97) by antivirus1-rhel7.int (F-Secure/fsigk_smtp/550/antivirus1-rhel7.int); Tue, 23 Jan 2018 13:16:28 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/550/antivirus1-rhel7.int) Received: from salvia.here (129.166.216.87.static.jazztel.es [87.216.166.129]) (Authenticated sender: pneira@us.es) by entrada.int (Postfix) with ESMTPA id E5F8141E4817 for ; Tue, 23 Jan 2018 13:16:27 +0100 (CET) X-SMTPAUTHUS: auth mail.us.es From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nft 2/6] src: add support to add flowtables Date: Tue, 23 Jan 2018 13:16:18 +0100 Message-Id: <20180123121622.16287-2-pablo@netfilter.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180123121622.16287-1-pablo@netfilter.org> References: <20180123121622.16287-1-pablo@netfilter.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch allows you to create flowtable: # nft add table x # nft add flowtable x m { hook ingress priority 10\; devices = { eth0, wlan0 }\; } You have to specify hook and priority. So far, only the ingress hook is supported. The priority represents where this flowtable is placed in the ingress hook, which is registered to the devices that the user specifies. You can also use the 'create' command instead to bail out in case that there is an existing flowtable with this name. Signed-off-by: Pablo Neira Ayuso --- include/expression.h | 2 + include/mnl.h | 4 ++ include/netlink.h | 4 ++ include/rule.h | 7 ++++ src/evaluate.c | 26 ++++++++++++ src/expression.c | 4 +- src/mnl.c | 16 ++++++++ src/netlink.c | 58 ++++++++++++++++++++++++++ src/parser_bison.y | 112 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/rule.c | 17 ++++++++ src/scanner.l | 2 + 11 files changed, 245 insertions(+), 7 deletions(-) diff --git a/include/expression.h b/include/expression.h index 0a0e178fe468..8f9da1b1c7c9 100644 --- a/include/expression.h +++ b/include/expression.h @@ -407,6 +407,8 @@ extern struct expr *prefix_expr_alloc(const struct location *loc, extern struct expr *range_expr_alloc(const struct location *loc, struct expr *low, struct expr *high); +extern struct expr *compound_expr_alloc(const struct location *loc, + const struct expr_ops *ops); extern void compound_expr_add(struct expr *compound, struct expr *expr); extern void compound_expr_remove(struct expr *compound, struct expr *expr); extern void list_expr_sort(struct list_head *head); diff --git a/include/mnl.h b/include/mnl.h index 4475e7f872d9..470b29787fa6 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -92,6 +92,10 @@ int mnl_nft_obj_batch_del(struct nftnl_obj *nln, struct nftnl_batch *batch, struct nftnl_flowtable_list * mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table); +int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo, + struct nftnl_batch *batch, unsigned int flags, + uint32_t seqnum); + struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx, uint32_t family); int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask, diff --git a/include/netlink.h b/include/netlink.h index bca59bbd9ebe..b80acbabe80f 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -184,6 +185,9 @@ extern int netlink_delete_obj(struct netlink_ctx *ctx, const struct handle *h, extern int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h, const struct location *loc); +extern int netlink_add_flowtable(struct netlink_ctx *ctx, + const struct handle *h, struct flowtable *ft, + uint32_t flags); extern void netlink_dump_chain(const struct nftnl_chain *nlc, struct netlink_ctx *ctx); diff --git a/include/rule.h b/include/rule.h index 5ee5389a6c36..de84cfc0ae64 100644 --- a/include/rule.h +++ b/include/rule.h @@ -320,10 +320,13 @@ uint32_t obj_type_to_cmd(uint32_t type); struct flowtable { struct list_head list; struct handle handle; + struct scope scope; struct location location; + const char * hookstr; unsigned int hooknum; int priority; const char **dev_array; + struct expr *dev_expr; int dev_array_len; unsigned int refcnt; }; @@ -381,6 +384,8 @@ enum cmd_ops { * @CMD_OBJ_CHAIN: chain * @CMD_OBJ_CHAINS: multiple chains * @CMD_OBJ_TABLE: table + * @CMD_OBJ_FLOWTABLE: flowtable + * @CMD_OBJ_FLOWTABLES: flowtables * @CMD_OBJ_RULESET: ruleset * @CMD_OBJ_EXPR: expression * @CMD_OBJ_MONITOR: monitor @@ -420,6 +425,7 @@ enum cmd_obj { CMD_OBJ_CT_HELPERS, CMD_OBJ_LIMIT, CMD_OBJ_LIMITS, + CMD_OBJ_FLOWTABLE, CMD_OBJ_FLOWTABLES, }; @@ -479,6 +485,7 @@ struct cmd { struct rule *rule; struct chain *chain; struct table *table; + struct flowtable *flowtable; struct monitor *monitor; struct markup *markup; struct obj *object; diff --git a/src/evaluate.c b/src/evaluate.c index a58fca9e6362..70a61c72838a 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2894,6 +2894,24 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set) return 0; } +static uint32_t str2hooknum(uint32_t family, const char *hook); + +static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft) +{ + struct table *table; + + table = table_lookup_global(ctx); + if (table == NULL) + return cmd_error(ctx, "Could not process rule: Table '%s' does not exist", + ctx->cmd->handle.table); + + ft->hooknum = str2hooknum(NFPROTO_NETDEV, ft->hookstr); + if (ft->hooknum == NF_INET_NUMHOOKS) + return chain_error(ctx, ft, "invalid hook %s", ft->hookstr); + + return 0; +} + static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule) { struct stmt *stmt, *tstmt = NULL; @@ -3066,6 +3084,14 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) return chain_evaluate(ctx, cmd->chain); case CMD_OBJ_TABLE: return table_evaluate(ctx, cmd->table); + case CMD_OBJ_FLOWTABLE: + ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, + ctx->msgs, ctx->debug_mask & NFT_DEBUG_NETLINK, ctx->octx); + if (ret < 0) + return ret; + + handle_merge(&cmd->flowtable->handle, &cmd->handle); + return flowtable_evaluate(ctx, cmd->flowtable); case CMD_OBJ_COUNTER: case CMD_OBJ_QUOTA: case CMD_OBJ_CT_HELPER: diff --git a/src/expression.c b/src/expression.c index 393c1b2b2cfe..7da69442bf03 100644 --- a/src/expression.c +++ b/src/expression.c @@ -663,8 +663,8 @@ struct expr *range_expr_alloc(const struct location *loc, return expr; } -static struct expr *compound_expr_alloc(const struct location *loc, - const struct expr_ops *ops) +struct expr *compound_expr_alloc(const struct location *loc, + const struct expr_ops *ops) { struct expr *expr; diff --git a/src/mnl.c b/src/mnl.c index e70b0cdeb723..be6e05da5936 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -1011,6 +1011,22 @@ err: return NULL; } +int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo, + struct nftnl_batch *batch, unsigned int flags, + uint32_t seqnum) +{ + struct nlmsghdr *nlh; + + nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), + NFT_MSG_NEWFLOWTABLE, + nftnl_flowtable_get_u32(flo, NFTNL_FLOWTABLE_FAMILY), + NLM_F_CREATE | flags, seqnum); + nftnl_flowtable_nlmsg_build_payload(nlh, flo); + mnl_nft_batch_continue(batch); + + return 0; +} + /* * ruleset */ diff --git a/src/netlink.c b/src/netlink.c index 7b8e48dc341d..89513584a50f 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1762,6 +1762,64 @@ static struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx, return obj; } +static struct nftnl_flowtable *alloc_nftnl_flowtable(const struct handle *h, + const struct flowtable *ft) +{ + struct nftnl_flowtable *flo; + + flo = nftnl_flowtable_alloc(); + if (flo == NULL) + memory_allocation_error(); + + nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_FAMILY, h->family); + nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE, h->table); + if (h->flowtable != NULL) + nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME, h->flowtable); + + return flo; +} + +static void netlink_dump_flowtable(struct nftnl_flowtable *flo, + struct netlink_ctx *ctx) +{ + FILE *fp = ctx->octx->output_fp; + + if (!(ctx->debug_mask & NFT_DEBUG_NETLINK) || !fp) + return; + + nftnl_flowtable_fprintf(fp, flo, 0, 0); + fprintf(fp, "\n"); +} + +int netlink_add_flowtable(struct netlink_ctx *ctx, const struct handle *h, + struct flowtable *ft, uint32_t flags) +{ + struct nftnl_flowtable *flo; + const char *dev_array[8]; + struct expr *expr; + int i = 0, err; + + flo = alloc_nftnl_flowtable(h, ft); + nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_HOOKNUM, ft->hooknum); + nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_PRIO, ft->priority); + + list_for_each_entry(expr, &ft->dev_expr->expressions, list) + dev_array[i++] = expr->identifier; + + dev_array[i] = NULL; + nftnl_flowtable_set_array(flo, NFTNL_FLOWTABLE_DEVICES, dev_array); + + netlink_dump_flowtable(flo, ctx); + + err = mnl_nft_flowtable_batch_add(flo, ctx->batch, flags, ctx->seqnum); + if (err < 0) + netlink_io_error(ctx, &ft->location, "Could not add flowtable: %s", + strerror(errno)); + nftnl_flowtable_free(flo); + + return err; +} + static int list_obj_cb(struct nftnl_obj *nls, void *arg) { struct netlink_ctx *ctx = arg; diff --git a/src/parser_bison.y b/src/parser_bison.y index 4cfa8076cfc4..45cc3b4114ff 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -145,6 +145,7 @@ int nft_lex(void *, void *, void *); struct expr *expr; struct set *set; struct obj *obj; + struct flowtable *flowtable; struct counter *counter; struct quota *quota; struct ct *ct; @@ -189,6 +190,7 @@ int nft_lex(void *, void *, void *); %token HOOK "hook" %token DEVICE "device" +%token DEVICES "devices" %token TABLE "table" %token TABLES "tables" %token CHAIN "chain" @@ -200,6 +202,7 @@ int nft_lex(void *, void *, void *); %token ELEMENT "element" %token MAP "map" %token MAPS "maps" +%token FLOWTABLE "flowtable" %token HANDLE "handle" %token RULESET "ruleset" %token TRACE "trace" @@ -499,9 +502,9 @@ int nft_lex(void *, void *, void *); %type base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd %destructor { cmd_free($$); } base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd -%type table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec -%destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec -%type set_spec set_identifier obj_spec obj_identifier +%type table_spec chain_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec +%destructor { handle_free(&$$); } table_spec chain_spec flowtable_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec +%type set_spec set_identifier flowtable_identifier obj_spec obj_identifier %destructor { handle_free(&$$); } set_spec set_identifier obj_spec obj_identifier %type family_spec family_spec_explicit chain_policy prio_spec @@ -525,6 +528,9 @@ int nft_lex(void *, void *, void *); %type map_block_alloc map_block %destructor { set_free($$); } map_block_alloc +%type flowtable_block_alloc flowtable_block +%destructor { flowtable_free($$); } flowtable_block_alloc + %type obj_block_alloc counter_block quota_block ct_helper_block limit_block %destructor { obj_free($$); } obj_block_alloc @@ -605,8 +611,8 @@ int nft_lex(void *, void *, void *); %type verdict_map_expr verdict_map_list_expr verdict_map_list_member_expr %destructor { expr_free($$); } verdict_map_expr verdict_map_list_expr verdict_map_list_member_expr -%type set_expr set_block_expr set_list_expr set_list_member_expr -%destructor { expr_free($$); } set_expr set_block_expr set_list_expr set_list_member_expr +%type set_expr set_block_expr set_list_expr set_list_member_expr flowtable_expr flowtable_list_expr flowtable_expr_member +%destructor { expr_free($$); } set_expr set_block_expr set_list_expr set_list_member_expr flowtable_expr flowtable_list_expr flowtable_expr_member %type set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr %destructor { expr_free($$); } set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr %type set_elem_expr_stmt set_elem_expr_stmt_alloc @@ -871,6 +877,13 @@ add_cmd : TABLE table_spec { $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SETELEM, &$2, &@$, $3); } + | FLOWTABLE flowtable_spec flowtable_block_alloc + '{' flowtable_block '}' + { + $5->location = @5; + handle_merge(&$3->handle, &$2); + $$ = cmd_alloc(CMD_ADD, CMD_OBJ_FLOWTABLE, &$2, &@$, $5); + } | COUNTER obj_spec { struct obj *obj; @@ -946,6 +959,13 @@ create_cmd : TABLE table_spec { $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SETELEM, &$2, &@$, $3); } + | FLOWTABLE flowtable_spec flowtable_block_alloc + '{' flowtable_block '}' + { + $5->location = @5; + handle_merge(&$3->handle, &$2); + $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_FLOWTABLE, &$2, &@$, $5); + } | COUNTER obj_spec { struct obj *obj; @@ -1316,6 +1336,17 @@ table_block : /* empty */ { $$ = $-1; } list_add_tail(&$4->list, &$1->sets); $$ = $1; } + + | table_block FLOWTABLE flowtable_identifier + flowtable_block_alloc '{' flowtable_block '}' + stmt_separator + { + $4->location = @3; + handle_merge(&$4->handle, &$3); + handle_free(&$3); + list_add_tail(&$4->list, &$1->flowtables); + $$ = $1; + } | table_block COUNTER obj_identifier obj_block_alloc '{' counter_block '}' stmt_separator @@ -1506,6 +1537,62 @@ set_policy_spec : PERFORMANCE { $$ = NFT_SET_POL_PERFORMANCE; } | MEMORY { $$ = NFT_SET_POL_MEMORY; } ; +flowtable_block_alloc : /* empty */ + { + $$ = flowtable_alloc(NULL); + } + ; + +flowtable_block : /* empty */ { $$ = $-1; } + | flowtable_block common_block + | flowtable_block stmt_separator + | flowtable_block HOOK STRING PRIORITY prio_spec stmt_separator + { + $$->hookstr = chain_hookname_lookup($3); + if ($$->hookstr == NULL) { + erec_queue(error(&@3, "unknown chain hook %s", $3), + state->msgs); + xfree($3); + YYERROR; + } + xfree($3); + + $$->priority = $5; + } + | flowtable_block DEVICES '=' flowtable_expr stmt_separator + { + $$->dev_expr = $4; + } + ; + +flowtable_expr : '{' flowtable_list_expr '}' + { + $2->location = @$; + $$ = $2; + } + ; + +flowtable_list_expr : flowtable_expr_member + { + $$ = compound_expr_alloc(&@$, NULL); + compound_expr_add($$, $1); + } + | flowtable_list_expr COMMA flowtable_expr_member + { + compound_expr_add($1, $3); + $$ = $1; + } + | flowtable_list_expr COMMA opt_newline + ; + +flowtable_expr_member : STRING + { + $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE, + current_scope(state), + $1); + } + ; + data_type_atom_expr : type_identifier { const struct datatype *dtype = datatype_lookup_byname($1); @@ -1714,6 +1801,21 @@ set_identifier : identifier } ; + +flowtable_spec : table_spec identifier + { + $$ = $1; + $$.flowtable = $2; + } + ; + +flowtable_identifier : identifier + { + memset(&$$, 0, sizeof($$)); + $$.flowtable = $1; + } + ; + obj_spec : table_spec identifier { $$ = $1; diff --git a/src/rule.c b/src/rule.c index 08ea2c3c9fb5..8a38bcc66a66 100644 --- a/src/rule.c +++ b/src/rule.c @@ -45,6 +45,8 @@ void handle_merge(struct handle *dst, const struct handle *src) dst->chain = xstrdup(src->chain); if (dst->set == NULL && src->set != NULL) dst->set = xstrdup(src->set); + if (dst->flowtable == NULL && src->flowtable != NULL) + dst->flowtable = xstrdup(src->flowtable); if (dst->obj == NULL && src->obj != NULL) dst->obj = xstrdup(src->obj); if (dst->handle.id == 0) @@ -854,6 +856,7 @@ struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj, void nft_cmd_expand(struct cmd *cmd) { struct list_head new_cmds; + struct flowtable *ft; struct table *table; struct chain *chain; struct rule *rule; @@ -893,6 +896,14 @@ void nft_cmd_expand(struct cmd *cmd) &set->location, set_get(set)); list_add_tail(&new->list, &new_cmds); } + list_for_each_entry(ft, &table->flowtables, list) { + handle_merge(&ft->handle, &table->handle); + memset(&h, 0, sizeof(h)); + handle_merge(&h, &ft->handle); + new = cmd_alloc(CMD_ADD, CMD_OBJ_FLOWTABLE, &h, + &ft->location, flowtable_get(ft)); + list_add_tail(&new->list, &new_cmds); + } list_for_each_entry(chain, &table->chains, list) { list_for_each_entry(rule, &chain->rules, list) { memset(&h, 0, sizeof(h)); @@ -979,6 +990,9 @@ void cmd_free(struct cmd *cmd) case CMD_OBJ_LIMIT: obj_free(cmd->object); break; + case CMD_OBJ_FLOWTABLE: + flowtable_free(cmd->flowtable); + break; default: BUG("invalid command object type %u\n", cmd->obj); } @@ -1068,6 +1082,9 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl) case CMD_OBJ_CT_HELPER: case CMD_OBJ_LIMIT: return netlink_add_obj(ctx, &cmd->handle, cmd->object, flags); + case CMD_OBJ_FLOWTABLE: + return netlink_add_flowtable(ctx, &cmd->handle, cmd->flowtable, + flags); default: BUG("invalid command object type %u\n", cmd->obj); } diff --git a/src/scanner.l b/src/scanner.l index 6a1f2f685615..ca74650cdd1f 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -238,6 +238,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "hook" { return HOOK; } "device" { return DEVICE; } +"devices" { return DEVICES; } "table" { return TABLE; } "tables" { return TABLES; } "chain" { return CHAIN; } @@ -249,6 +250,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "element" { return ELEMENT; } "map" { return MAP; } "maps" { return MAPS; } +"flowtable" { return FLOWTABLE; } "handle" { return HANDLE; } "ruleset" { return RULESET; } "trace" { return TRACE; } From patchwork Tue Jan 23 12:16:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 864743 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zQnN561B3z9t3p for ; Tue, 23 Jan 2018 23:16:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751419AbeAWMQg (ORCPT ); Tue, 23 Jan 2018 07:16:36 -0500 Received: from mail.us.es ([193.147.175.20]:44790 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751393AbeAWMQc (ORCPT ); Tue, 23 Jan 2018 07:16:32 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id 168492519A6 for ; Tue, 23 Jan 2018 13:16:31 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id 04FFEDA808 for ; Tue, 23 Jan 2018 13:16:31 +0100 (CET) Received: by antivirus1-rhel7.int (Postfix, from userid 99) id ED522DA7E0; Tue, 23 Jan 2018 13:16:30 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on antivirus1-rhel7.int X-Spam-Level: X-Spam-Status: No, score=-108.2 required=7.5 tests=ALL_TRUSTED,BAYES_50, SMTPAUTH_US2,USER_IN_WHITELIST autolearn=disabled version=3.4.1 Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id F0E1DDA809 for ; Tue, 23 Jan 2018 13:16:28 +0100 (CET) Received: from 192.168.1.97 (192.168.1.97) by antivirus1-rhel7.int (F-Secure/fsigk_smtp/550/antivirus1-rhel7.int); Tue, 23 Jan 2018 13:16:28 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/550/antivirus1-rhel7.int) Received: from salvia.here (129.166.216.87.static.jazztel.es [87.216.166.129]) (Authenticated sender: pneira@us.es) by entrada.int (Postfix) with ESMTPA id BA7F241E4817 for ; Tue, 23 Jan 2018 13:16:28 +0100 (CET) X-SMTPAUTHUS: auth mail.us.es From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nft 3/6] src: delete flowtable Date: Tue, 23 Jan 2018 13:16:19 +0100 Message-Id: <20180123121622.16287-3-pablo@netfilter.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180123121622.16287-1-pablo@netfilter.org> References: <20180123121622.16287-1-pablo@netfilter.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch allows you to delete an existing flowtable: # nft delete flowtable x m Signed-off-by: Pablo Neira Ayuso --- include/mnl.h | 3 +++ include/netlink.h | 3 +++ src/evaluate.c | 1 + src/mnl.c | 16 ++++++++++++++++ src/netlink.c | 18 ++++++++++++++++++ src/parser_bison.y | 4 ++++ src/rule.c | 3 +++ 7 files changed, 48 insertions(+) diff --git a/include/mnl.h b/include/mnl.h index 470b29787fa6..1b2450a9388e 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -95,6 +95,9 @@ mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table); int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo, struct nftnl_batch *batch, unsigned int flags, uint32_t seqnum); +int mnl_nft_flowtable_batch_del(struct nftnl_flowtable *flow, + struct nftnl_batch *batch, unsigned int flags, + uint32_t seqnum); struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx, uint32_t family); diff --git a/include/netlink.h b/include/netlink.h index b80acbabe80f..9ae021a8dd49 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -188,6 +188,9 @@ extern int netlink_list_flowtables(struct netlink_ctx *ctx, extern int netlink_add_flowtable(struct netlink_ctx *ctx, const struct handle *h, struct flowtable *ft, uint32_t flags); +extern int netlink_delete_flowtable(struct netlink_ctx *ctx, + const struct handle *h, + struct location *loc); extern void netlink_dump_chain(const struct nftnl_chain *nlc, struct netlink_ctx *ctx); diff --git a/src/evaluate.c b/src/evaluate.c index 70a61c72838a..892d1e0c8c5b 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -3118,6 +3118,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd) case CMD_OBJ_RULE: case CMD_OBJ_CHAIN: case CMD_OBJ_TABLE: + case CMD_OBJ_FLOWTABLE: case CMD_OBJ_COUNTER: case CMD_OBJ_QUOTA: case CMD_OBJ_CT_HELPER: diff --git a/src/mnl.c b/src/mnl.c index be6e05da5936..f620a3bda8d5 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -1027,6 +1027,22 @@ int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo, return 0; } +int mnl_nft_flowtable_batch_del(struct nftnl_flowtable *flo, + struct nftnl_batch *batch, unsigned int flags, + uint32_t seqnum) +{ + struct nlmsghdr *nlh; + + nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), + NFT_MSG_DELFLOWTABLE, + nftnl_flowtable_get_u32(flo, NFTNL_FLOWTABLE_FAMILY), + flags, seqnum); + nftnl_flowtable_nlmsg_build_payload(nlh, flo); + mnl_nft_batch_continue(batch); + + return 0; +} + /* * ruleset */ diff --git a/src/netlink.c b/src/netlink.c index 89513584a50f..56c6b6a3725e 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1820,6 +1820,24 @@ int netlink_add_flowtable(struct netlink_ctx *ctx, const struct handle *h, return err; } +int netlink_delete_flowtable(struct netlink_ctx *ctx, const struct handle *h, + struct location *loc) +{ + struct nftnl_flowtable *flo; + int err; + + flo = alloc_nftnl_flowtable(h, NULL); + netlink_dump_flowtable(flo, ctx); + + err = mnl_nft_flowtable_batch_del(flo, ctx->batch, 0, ctx->seqnum); + if (err < 0) + netlink_io_error(ctx, loc, "Could not delete flowtable: %s", + strerror(errno)); + nftnl_flowtable_free(flo); + + return err; +} + static int list_obj_cb(struct nftnl_obj *nls, void *arg) { struct netlink_ctx *ctx = arg; diff --git a/src/parser_bison.y b/src/parser_bison.y index 45cc3b4114ff..0623cd12aeb5 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1023,6 +1023,10 @@ delete_cmd : TABLE table_spec { $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SETELEM, &$2, &@$, $3); } + | FLOWTABLE flowtable_spec + { + $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL); + } | COUNTER obj_spec { $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_COUNTER, &$2, &@$, NULL); diff --git a/src/rule.c b/src/rule.c index 8a38bcc66a66..b06f30eb5528 100644 --- a/src/rule.c +++ b/src/rule.c @@ -1174,6 +1174,9 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd) case CMD_OBJ_LIMIT: return netlink_delete_obj(ctx, &cmd->handle, &cmd->location, NFT_OBJECT_LIMIT); + case CMD_OBJ_FLOWTABLE: + return netlink_delete_flowtable(ctx, &cmd->handle, + &cmd->location); default: BUG("invalid command object type %u\n", cmd->obj); } From patchwork Tue Jan 23 12:16:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 864746 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zQnNC5dzlz9t3J for ; Tue, 23 Jan 2018 23:16:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751427AbeAWMQk (ORCPT ); Tue, 23 Jan 2018 07:16:40 -0500 Received: from mail.us.es ([193.147.175.20]:44794 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751394AbeAWMQd (ORCPT ); Tue, 23 Jan 2018 07:16:33 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id E4BE82519A2 for ; Tue, 23 Jan 2018 13:16:31 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id D2479DA811 for ; Tue, 23 Jan 2018 13:16:31 +0100 (CET) Received: by antivirus1-rhel7.int (Postfix, from userid 99) id C7BC2DA808; Tue, 23 Jan 2018 13:16:31 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on antivirus1-rhel7.int X-Spam-Level: X-Spam-Status: No, score=-108.2 required=7.5 tests=ALL_TRUSTED,BAYES_50, SMTPAUTH_US2,USER_IN_WHITELIST autolearn=disabled version=3.4.1 Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id BF159DA86B for ; Tue, 23 Jan 2018 13:16:29 +0100 (CET) Received: from 192.168.1.97 (192.168.1.97) by antivirus1-rhel7.int (F-Secure/fsigk_smtp/550/antivirus1-rhel7.int); Tue, 23 Jan 2018 13:16:29 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/550/antivirus1-rhel7.int) Received: from salvia.here (129.166.216.87.static.jazztel.es [87.216.166.129]) (Authenticated sender: pneira@us.es) by entrada.int (Postfix) with ESMTPA id 862C241E4817 for ; Tue, 23 Jan 2018 13:16:29 +0100 (CET) X-SMTPAUTHUS: auth mail.us.es From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nft 4/6] src: flow offload support Date: Tue, 23 Jan 2018 13:16:20 +0100 Message-Id: <20180123121622.16287-4-pablo@netfilter.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180123121622.16287-1-pablo@netfilter.org> References: <20180123121622.16287-1-pablo@netfilter.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch allows us to refer to existing flowtables: # nft add rule x x flow offload @m Packets matching this rule create an entry in the flow table 'm', hence, follow up packets that get to the flowtable at ingress bypass the classic forwarding path. Signed-off-by: Pablo Neira Ayuso --- include/ct.h | 2 ++ include/statement.h | 9 +++++++++ src/ct.c | 23 +++++++++++++++++++++++ src/evaluate.c | 1 + src/netlink_delinearize.c | 11 +++++++++++ src/netlink_linearize.c | 13 +++++++++++++ src/parser_bison.y | 5 +++++ src/scanner.l | 1 + 8 files changed, 65 insertions(+) diff --git a/include/ct.h b/include/ct.h index ec5d55d85dd0..2c3392d36c94 100644 --- a/include/ct.h +++ b/include/ct.h @@ -29,6 +29,8 @@ extern struct expr *ct_expr_alloc(const struct location *loc, extern void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr); extern struct stmt *notrack_stmt_alloc(const struct location *loc); +extern struct stmt *flow_offload_stmt_alloc(const struct location *loc, + const char *table_name); extern const struct datatype ct_dir_type; extern const struct datatype ct_state_type; diff --git a/include/statement.h b/include/statement.h index 23a551b67f2b..993727c933f2 100644 --- a/include/statement.h +++ b/include/statement.h @@ -10,6 +10,12 @@ extern struct stmt *expr_stmt_alloc(const struct location *loc, extern struct stmt *verdict_stmt_alloc(const struct location *loc, struct expr *expr); +struct flow_stmt { + const char *table_name; +}; + +struct stmt *flow_stmt_alloc(const struct location *loc, const char *name); + struct objref_stmt { uint32_t type; struct expr *expr; @@ -229,6 +235,7 @@ struct xt_stmt { * @STMT_NOTRACK: notrack statement * @STMT_OBJREF: stateful object reference statement * @STMT_EXTHDR: extension header statement + * @STMT_FLOW_OFFLOAD: flow offload statement */ enum stmt_types { STMT_INVALID, @@ -254,6 +261,7 @@ enum stmt_types { STMT_NOTRACK, STMT_OBJREF, STMT_EXTHDR, + STMT_FLOW_OFFLOAD, }; /** @@ -314,6 +322,7 @@ struct stmt { struct fwd_stmt fwd; struct xt_stmt xt; struct objref_stmt objref; + struct flow_stmt flow; }; }; diff --git a/src/ct.c b/src/ct.c index d5347974bd0d..fb908531862b 100644 --- a/src/ct.c +++ b/src/ct.c @@ -456,3 +456,26 @@ struct stmt *notrack_stmt_alloc(const struct location *loc) { return stmt_alloc(loc, ¬rack_stmt_ops); } + +static void flow_offload_stmt_print(const struct stmt *stmt, + struct output_ctx *octx) +{ + printf("flow offload @%s", stmt->flow.table_name); +} + +static const struct stmt_ops flow_offload_stmt_ops = { + .type = STMT_FLOW_OFFLOAD, + .name = "flow_offload", + .print = flow_offload_stmt_print, +}; + +struct stmt *flow_offload_stmt_alloc(const struct location *loc, + const char *table_name) +{ + struct stmt *stmt; + + stmt = stmt_alloc(loc, &flow_offload_stmt_ops); + stmt->flow.table_name = table_name; + + return stmt; +} diff --git a/src/evaluate.c b/src/evaluate.c index 892d1e0c8c5b..14fadd538850 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2773,6 +2773,7 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt) case STMT_LIMIT: case STMT_QUOTA: case STMT_NOTRACK: + case STMT_FLOW_OFFLOAD: return 0; case STMT_EXPRESSION: return stmt_evaluate_expr(ctx, stmt); diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 2637f4baaec4..bbc9ccead1bf 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -677,6 +677,16 @@ static void netlink_parse_notrack(struct netlink_parse_ctx *ctx, ctx->stmt = notrack_stmt_alloc(loc); } +static void netlink_parse_flow_offload(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nftnl_expr *nle) +{ + const char *table_name; + + table_name = xstrdup(nftnl_expr_get_str(nle, NFTNL_EXPR_FLOW_TABLE_NAME)); + ctx->stmt = flow_offload_stmt_alloc(loc, table_name); +} + static void netlink_parse_ct_stmt(struct netlink_parse_ctx *ctx, const struct location *loc, const struct nftnl_expr *nle) @@ -1252,6 +1262,7 @@ static const struct { { .name = "hash", .parse = netlink_parse_hash }, { .name = "fib", .parse = netlink_parse_fib }, { .name = "tcpopt", .parse = netlink_parse_exthdr }, + { .name = "flow_offload", .parse = netlink_parse_flow_offload }, }; static int netlink_parse_expr(const struct nftnl_expr *nle, diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 99a4dde22adb..a6eb3aaf1c6b 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -1201,6 +1201,17 @@ static void netlink_gen_notrack_stmt(struct netlink_linearize_ctx *ctx, nftnl_rule_add_expr(ctx->nlr, nle); } +static void netlink_gen_flow_offload_stmt(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) +{ + struct nftnl_expr *nle; + + nle = alloc_nft_expr("flow_offload"); + nftnl_expr_set_str(nle, NFTNL_EXPR_FLOW_TABLE_NAME, + stmt->flow.table_name); + nftnl_rule_add_expr(ctx->nlr, nle); +} + static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { @@ -1300,6 +1311,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, break; case STMT_NOTRACK: return netlink_gen_notrack_stmt(ctx, stmt); + case STMT_FLOW_OFFLOAD: + return netlink_gen_flow_offload_stmt(ctx, stmt); case STMT_OBJREF: return netlink_gen_objref_stmt(ctx, stmt); default: diff --git a/src/parser_bison.y b/src/parser_bison.y index 0623cd12aeb5..c9796acf7539 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -247,6 +247,7 @@ int nft_lex(void *, void *, void *); %token SIZE "size" %token FLOW "flow" +%token OFFLOAD "offload" %token METER "meter" %token METERS "meters" @@ -3378,6 +3379,10 @@ meta_stmt : META meta_key SET stmt_expr { $$ = notrack_stmt_alloc(&@$); } + | FLOW OFFLOAD AT string + { + $$ = flow_offload_stmt_alloc(&@$, $4); + } ; offset_opt : /* empty */ { $$ = 0; } diff --git a/src/scanner.l b/src/scanner.l index ca74650cdd1f..f51687bd2929 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -295,6 +295,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "memory" { return MEMORY; } "flow" { return FLOW; } +"offload" { return OFFLOAD; } "meter" { return METER; } "meters" { return METERS; } From patchwork Tue Jan 23 12:16:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 864744 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zQnN93xDBz9t3J for ; Tue, 23 Jan 2018 23:16:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751431AbeAWMQl (ORCPT ); Tue, 23 Jan 2018 07:16:41 -0500 Received: from mail.us.es ([193.147.175.20]:44828 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751393AbeAWMQh (ORCPT ); Tue, 23 Jan 2018 07:16:37 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id EA1002519A6 for ; Tue, 23 Jan 2018 13:16:35 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id D4A45DA842 for ; Tue, 23 Jan 2018 13:16:35 +0100 (CET) Received: by antivirus1-rhel7.int (Postfix, from userid 99) id D3DC0DA819; Tue, 23 Jan 2018 13:16:35 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on antivirus1-rhel7.int X-Spam-Level: X-Spam-Status: No, score=-108.2 required=7.5 tests=ALL_TRUSTED,BAYES_50, SMTPAUTH_US2,USER_IN_WHITELIST autolearn=disabled version=3.4.1 Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id 693D6DA845 for ; Tue, 23 Jan 2018 13:16:30 +0100 (CET) Received: from 192.168.1.97 (192.168.1.97) by antivirus1-rhel7.int (F-Secure/fsigk_smtp/550/antivirus1-rhel7.int); Tue, 23 Jan 2018 13:16:30 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/550/antivirus1-rhel7.int) Received: from salvia.here (129.166.216.87.static.jazztel.es [87.216.166.129]) (Authenticated sender: pneira@us.es) by entrada.int (Postfix) with ESMTPA id 327D441E4817 for ; Tue, 23 Jan 2018 13:16:30 +0100 (CET) X-SMTPAUTHUS: auth mail.us.es From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nft 5/6] tests: shell: add flowtable tests Date: Tue, 23 Jan 2018 13:16:21 +0100 Message-Id: <20180123121622.16287-5-pablo@netfilter.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180123121622.16287-1-pablo@netfilter.org> References: <20180123121622.16287-1-pablo@netfilter.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Add basic flowtable tests. Signed-off-by: Pablo Neira Ayuso --- tests/shell/run-tests.sh | 4 ++- tests/shell/testcases/flowtable/0001flowtable_0 | 33 ++++++++++++++++++++++ .../testcases/flowtable/0002create_flowtable_0 | 12 ++++++++ .../testcases/flowtable/0003add_after_flush_0 | 8 ++++++ .../testcases/flowtable/0004delete_after_add0 | 6 ++++ .../shell/testcases/flowtable/0005delete_in_use_1 | 9 ++++++ 6 files changed, 71 insertions(+), 1 deletion(-) create mode 100755 tests/shell/testcases/flowtable/0001flowtable_0 create mode 100755 tests/shell/testcases/flowtable/0002create_flowtable_0 create mode 100755 tests/shell/testcases/flowtable/0003add_after_flush_0 create mode 100755 tests/shell/testcases/flowtable/0004delete_after_add0 create mode 100755 tests/shell/testcases/flowtable/0005delete_in_use_1 diff --git a/tests/shell/run-tests.sh b/tests/shell/run-tests.sh index fe30115e0807..3eee99dfb739 100755 --- a/tests/shell/run-tests.sh +++ b/tests/shell/run-tests.sh @@ -68,7 +68,9 @@ kernel_cleanup() { nft_set_hash nft_set_rbtree nft_set_bitmap \ nft_chain_nat_ipv4 nft_chain_nat_ipv6 \ nf_tables_inet nf_tables_bridge nf_tables_arp \ - nf_tables_ipv4 nf_tables_ipv6 nf_tables + nf_tables_ipv4 nf_tables_ipv6 nf_tables \ + nf_flow_table nf_flow_table_ipv4 nf_flow_tables_ipv6 \ + nf_flow_table_inet nft_flow_offload } find_tests() { diff --git a/tests/shell/testcases/flowtable/0001flowtable_0 b/tests/shell/testcases/flowtable/0001flowtable_0 new file mode 100755 index 000000000000..307f06f62ebd --- /dev/null +++ b/tests/shell/testcases/flowtable/0001flowtable_0 @@ -0,0 +1,33 @@ +#!/bin/bash + +tmpfile=$(mktemp) +if [ ! -w $tmpfile ] ; then + echo "Failed to create tmp file" >&2 + exit 0 +fi + +trap "rm -rf $tmpfile" EXIT # cleanup if aborted + + +EXPECTED='table inet t { + flowtable f { + hook ingress priority 10 + devices = { eth0, wlan0 } + } + + chain c { + flow offload @f + } +}' + +echo "$EXPECTED" > $tmpfile +set -e +$NFT -f $tmpfile + +GET="$($NFT list ruleset)" + +if [ "$EXPECTED" != "$GET" ] ; then + DIFF="$(which diff)" + [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") + exit 1 +fi diff --git a/tests/shell/testcases/flowtable/0002create_flowtable_0 b/tests/shell/testcases/flowtable/0002create_flowtable_0 new file mode 100755 index 000000000000..b6941c58eea9 --- /dev/null +++ b/tests/shell/testcases/flowtable/0002create_flowtable_0 @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e +$NFT add table t +$NFT add flowtable t f { hook ingress priority 10 \; devices = { eth0, wlan0 }\; } +if $NFT create flowtable t f { hook ingress priority 10 \; devices = { eth0, wlan0 }\; } 2>/dev/null ; then + echo "E: flowtable creation not failing on existing set" >&2 + exit 1 +fi +$NFT add flowtable t f { hook ingress priority 10 \; devices = { eth0, wlan0 }\; } + +exit 0 diff --git a/tests/shell/testcases/flowtable/0003add_after_flush_0 b/tests/shell/testcases/flowtable/0003add_after_flush_0 new file mode 100755 index 000000000000..1f3cb18a46d9 --- /dev/null +++ b/tests/shell/testcases/flowtable/0003add_after_flush_0 @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e +$NFT add table x +$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;} +$NFT flush ruleset +$NFT add table x +$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;} diff --git a/tests/shell/testcases/flowtable/0004delete_after_add0 b/tests/shell/testcases/flowtable/0004delete_after_add0 new file mode 100755 index 000000000000..b72977b37ce6 --- /dev/null +++ b/tests/shell/testcases/flowtable/0004delete_after_add0 @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +$NFT add table x +$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;} +$NFT delete flowtable x y diff --git a/tests/shell/testcases/flowtable/0005delete_in_use_1 b/tests/shell/testcases/flowtable/0005delete_in_use_1 new file mode 100755 index 000000000000..ce39e24e601d --- /dev/null +++ b/tests/shell/testcases/flowtable/0005delete_in_use_1 @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e +$NFT add table x +$NFT add chain x x +$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;} +$NFT add rule x x flow offload @y +$NFT delete flowtable x y +echo "E: delete flowtable in use" From patchwork Tue Jan 23 12:16:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 864747 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zQnNF1MFmz9t3p for ; Tue, 23 Jan 2018 23:16:45 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751420AbeAWMQj (ORCPT ); Tue, 23 Jan 2018 07:16:39 -0500 Received: from mail.us.es ([193.147.175.20]:44816 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751323AbeAWMQe (ORCPT ); Tue, 23 Jan 2018 07:16:34 -0500 Received: from antivirus1-rhel7.int (unknown [192.168.2.11]) by mail.us.es (Postfix) with ESMTP id 2477C2519A9 for ; Tue, 23 Jan 2018 13:16:33 +0100 (CET) Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id 117ACDA7F7 for ; Tue, 23 Jan 2018 13:16:33 +0100 (CET) Received: by antivirus1-rhel7.int (Postfix, from userid 99) id 10827DA729; Tue, 23 Jan 2018 13:16:33 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on antivirus1-rhel7.int X-Spam-Level: X-Spam-Status: No, score=-108.2 required=7.5 tests=ALL_TRUSTED,BAYES_50, SMTPAUTH_US2,USER_IN_WHITELIST autolearn=disabled version=3.4.1 Received: from antivirus1-rhel7.int (localhost [127.0.0.1]) by antivirus1-rhel7.int (Postfix) with ESMTP id 0DBF1DA809 for ; Tue, 23 Jan 2018 13:16:31 +0100 (CET) Received: from 192.168.1.97 (192.168.1.97) by antivirus1-rhel7.int (F-Secure/fsigk_smtp/550/antivirus1-rhel7.int); Tue, 23 Jan 2018 13:16:31 +0100 (CET) X-Virus-Status: clean(F-Secure/fsigk_smtp/550/antivirus1-rhel7.int) Received: from salvia.here (129.166.216.87.static.jazztel.es [87.216.166.129]) (Authenticated sender: pneira@us.es) by entrada.int (Postfix) with ESMTPA id C8FCB41E4817 for ; Tue, 23 Jan 2018 13:16:30 +0100 (CET) X-SMTPAUTHUS: auth mail.us.es From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nft 6/6] doc: nft: document flowtable Date: Tue, 23 Jan 2018 13:16:22 +0100 Message-Id: <20180123121622.16287-6-pablo@netfilter.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180123121622.16287-1-pablo@netfilter.org> References: <20180123121622.16287-1-pablo@netfilter.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Document the new flowtable objects available since Linux kernel 4.16-rc. Signed-off-by: Pablo Neira Ayuso --- doc/nft.xml | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/doc/nft.xml b/doc/nft.xml index 9e979af3c280..1b901c17b5a0 100644 --- a/doc/nft.xml +++ b/doc/nft.xml @@ -1160,6 +1160,91 @@ filter input iif $int_ifs accept + Flowtables + + + + add + create + + flowtable + family + table + flowtable + + hook hook + priority priority ; + devices = { device[,...] } ; + + + + + delete + list + + flowtable + family + table + flowtable + + + + + Flowtables allow you to accelerate packet forwarding in software. + Flowtables entries are represented through a tuple that is composed of the + input interface, source and destination address, source and destination + port; and layer 3/4 protocols. Each entry also caches the destination + interface and the gateway address - to update the destination link-layer + address - to forward packets. The ttl and hoplimit fields are also + decremented. Hence, flowtables provides an alternative path that allow + packets to bypass the classic forwarding path. Flowtables reside in the + ingress hook, that is located before the prerouting hook. You can select + what flows you want to offload through the flow offload + expression from the forward chain. Flowtables are + identified by their address family and their name. The address family + must be one of + + + ip + ip6 + inet + . + + The inet address family is a dummy family which is used to create + hybrid IPv4/IPv6 tables. + + When no address family is specified, ip is used by default. + + + + + + + + Add a new flowtable for the given family with the given name. + + + + + + + + Delete the specified flowtable. + + + + + + + + List all flowtables. + + + + + + + Stateful objects @@ -4917,6 +5002,24 @@ add rule nat prerouting tcp dport 22 redirect to :2222 + + + Flow offload statement + + A flow offload statement allows us to select what flows + you want to accelerate forwarding through layer 3 network + stack bypass. You have to specify the flowtable name where + you want to offload this flow. + + + + flow offload + @flowtable + + + + + Queue statement