The flow statement contains a stateful per flow statement, which is not
directly part of the rule. Allow generating these statements without adding
them to the rule and mark the supported statements using a new flag
STMT_F_STATEFUL.

Signed-off-by: Patrick McHardy <[email protected]>
---
 include/statement.h     |  1 +
 src/netlink_linearize.c | 80 ++++++++++++++++++++++++++++++-------------------
 src/statement.c         | 12 ++++++--
 3 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/include/statement.h b/include/statement.h
index e7872b0..a6a86f9 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -197,6 +197,7 @@ struct stmt_ops {
 
 enum stmt_flags {
        STMT_F_TERMINAL         = 0x1,
+       STMT_F_STATEFUL         = 0x2,
 };
 
 /**
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 3263043..28feecf 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -718,14 +718,9 @@ static void netlink_gen_expr(struct netlink_linearize_ctx 
*ctx,
        }
 }
 
-static void netlink_gen_verdict_stmt(struct netlink_linearize_ctx *ctx,
-                                    const struct stmt *stmt)
-{
-       return netlink_gen_expr(ctx, stmt->expr, NFT_REG_VERDICT);
-}
-
-static void netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx,
-                                    const struct stmt *stmt)
+static struct nftnl_expr *
+netlink_gen_counter_stmt(struct netlink_linearize_ctx *ctx,
+                        const struct stmt *stmt)
 {
        struct nftnl_expr *nle;
 
@@ -738,7 +733,46 @@ static void netlink_gen_counter_stmt(struct 
netlink_linearize_ctx *ctx,
                nftnl_expr_set_u64(nle, NFTNL_EXPR_CTR_BYTES,
                                   stmt->counter.bytes);
        }
-       nftnl_rule_add_expr(ctx->nlr, nle);
+
+       return nle;
+}
+
+static struct nftnl_expr *
+netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx,
+                      const struct stmt *stmt)
+{
+       struct nftnl_expr *nle;
+
+       nle = alloc_nft_expr("limit");
+       nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_RATE, stmt->limit.rate);
+       nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_UNIT, stmt->limit.unit);
+       nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_TYPE, stmt->limit.type);
+       if (stmt->limit.burst > 0)
+               nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_BURST,
+                                  stmt->limit.burst);
+       nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_FLAGS, stmt->limit.flags);
+
+       return nle;
+}
+
+static struct nftnl_expr *
+netlink_gen_stmt_stateful(struct netlink_linearize_ctx *ctx,
+                         const struct stmt *stmt)
+{
+       switch (stmt->ops->type) {
+       case STMT_COUNTER:
+               return netlink_gen_counter_stmt(ctx, stmt);
+       case STMT_LIMIT:
+               return netlink_gen_limit_stmt(ctx, stmt);
+       default:
+               BUG("unknown stateful statement type %s\n", stmt->ops->name);
+       }
+}
+
+static void netlink_gen_verdict_stmt(struct netlink_linearize_ctx *ctx,
+                                    const struct stmt *stmt)
+{
+       return netlink_gen_expr(ctx, stmt->expr, NFT_REG_VERDICT);
 }
 
 static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
@@ -821,23 +855,6 @@ static void netlink_gen_log_stmt(struct 
netlink_linearize_ctx *ctx,
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
-static void netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx,
-                                  const struct stmt *stmt)
-{
-       struct nftnl_expr *nle;
-
-       nle = alloc_nft_expr("limit");
-       nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_RATE, stmt->limit.rate);
-       nftnl_expr_set_u64(nle, NFTNL_EXPR_LIMIT_UNIT, stmt->limit.unit);
-       nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_TYPE, stmt->limit.type);
-       if (stmt->limit.burst > 0)
-               nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_BURST,
-                                  stmt->limit.burst);
-       nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_FLAGS, stmt->limit.flags);
-
-       nftnl_rule_add_expr(ctx->nlr, nle);
-}
-
 static void netlink_gen_reject_stmt(struct netlink_linearize_ctx *ctx,
                                    const struct stmt *stmt)
 {
@@ -1121,21 +1138,19 @@ static void netlink_gen_set_stmt(struct 
netlink_linearize_ctx *ctx,
 static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
                             const struct stmt *stmt)
 {
+       struct nftnl_expr *nle;
+
        switch (stmt->ops->type) {
        case STMT_EXPRESSION:
                return netlink_gen_expr(ctx, stmt->expr, NFT_REG_VERDICT);
        case STMT_VERDICT:
                return netlink_gen_verdict_stmt(ctx, stmt);
-       case STMT_COUNTER:
-               return netlink_gen_counter_stmt(ctx, stmt);
        case STMT_PAYLOAD:
                return netlink_gen_payload_stmt(ctx, stmt);
        case STMT_META:
                return netlink_gen_meta_stmt(ctx, stmt);
        case STMT_LOG:
                return netlink_gen_log_stmt(ctx, stmt);
-       case STMT_LIMIT:
-               return netlink_gen_limit_stmt(ctx, stmt);
        case STMT_REJECT:
                return netlink_gen_reject_stmt(ctx, stmt);
        case STMT_NAT:
@@ -1154,6 +1169,11 @@ static void netlink_gen_stmt(struct 
netlink_linearize_ctx *ctx,
                return netlink_gen_set_stmt(ctx, stmt);
        case STMT_FWD:
                return netlink_gen_fwd_stmt(ctx, stmt);
+       case STMT_COUNTER:
+       case STMT_LIMIT:
+               nle = netlink_gen_stmt_stateful(ctx, stmt);
+               nftnl_rule_add_expr(ctx->nlr, nle);
+               break;
        default:
                BUG("unknown statement type %s\n", stmt->ops->name);
        }
diff --git a/src/statement.c b/src/statement.c
index 2a6f19f..4149841 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -117,7 +117,11 @@ static const struct stmt_ops counter_stmt_ops = {
 
 struct stmt *counter_stmt_alloc(const struct location *loc)
 {
-       return stmt_alloc(loc, &counter_stmt_ops);
+       struct stmt *stmt;
+
+       stmt = stmt_alloc(loc, &counter_stmt_ops);
+       stmt->flags |= STMT_F_STATEFUL;
+       return stmt;
 }
 
 static const char *syslog_level[LOG_DEBUG + 1] = {
@@ -249,7 +253,11 @@ static const struct stmt_ops limit_stmt_ops = {
 
 struct stmt *limit_stmt_alloc(const struct location *loc)
 {
-       return stmt_alloc(loc, &limit_stmt_ops);
+       struct stmt *stmt;
+
+       stmt = stmt_alloc(loc, &limit_stmt_ops);
+       stmt->flags |= STMT_F_STATEFUL;
+       return stmt;
 }
 
 static void queue_stmt_print(const struct stmt *stmt)
-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to