This patch introduces a map as a numgen attribute, which permits
to lookup a value based on the numgen result as the key.

This approach only supports named maps.

Signed-off-by: Laura Garcia Liebana <nev...@gmail.com>
---
 include/expression.h                |  1 +
 include/linux/netfilter/nf_tables.h |  4 ++++
 include/numgen.h                    |  2 +-
 src/expression.c                    |  3 ++-
 src/netlink_delinearize.c           | 18 ++++++++++++++++--
 src/netlink_linearize.c             |  8 ++++++++
 src/numgen.c                        | 13 +++++++++++--
 src/parser_bison.y                  | 16 ++++++++++++----
 8 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/include/expression.h b/include/expression.h
index f0ba6fc..8158579 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -309,6 +309,7 @@ struct expr {
                        enum nft_ng_types       type;
                        uint32_t                mod;
                        uint32_t                offset;
+                       struct expr             *ng_map;
                } numgen;
                struct {
                        /* EXPR_HASH */
diff --git a/include/linux/netfilter/nf_tables.h 
b/include/linux/netfilter/nf_tables.h
index 517a39a..8612fe1 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1382,6 +1382,8 @@ enum nft_trace_types {
  * @NFTA_NG_MODULUS: maximum counter value (NLA_U32)
  * @NFTA_NG_TYPE: operation type (NLA_U32)
  * @NFTA_NG_OFFSET: offset to be added to the counter (NLA_U32)
+ * @NFTA_NG_SET_NAME: name of the map to lookup (NLA_STRING)
+ * @NFTA_NG_SET_ID: if of the map (NLA_U32)
  */
 enum nft_ng_attributes {
        NFTA_NG_UNSPEC,
@@ -1389,6 +1391,8 @@ enum nft_ng_attributes {
        NFTA_NG_MODULUS,
        NFTA_NG_TYPE,
        NFTA_NG_OFFSET,
+       NFTA_NG_SET_NAME,
+       NFTA_NG_SET_ID,
        __NFTA_NG_MAX
 };
 #define NFTA_NG_MAX    (__NFTA_NG_MAX - 1)
diff --git a/include/numgen.h b/include/numgen.h
index b230620..60eaa37 100644
--- a/include/numgen.h
+++ b/include/numgen.h
@@ -3,6 +3,6 @@
 
 extern struct expr *numgen_expr_alloc(const struct location *loc,
                                      enum nft_ng_types type, uint32_t until,
-                                     uint32_t offset);
+                                     uint32_t offset, struct expr *mappings);
 
 #endif /* NFTABLES_NUMGEN_H */
diff --git a/src/expression.c b/src/expression.c
index e698b14..53393ec 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -945,7 +945,8 @@ static void map_expr_print(const struct expr *expr, struct 
output_ctx *octx)
 
 static void map_expr_clone(struct expr *new, const struct expr *expr)
 {
-       new->map      = expr_clone(expr->map);
+       if (expr->map)
+               new->map = expr_clone(expr->map);
        new->mappings = expr_clone(expr->mappings);
 }
 
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 2126cf2..a270a92 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -668,13 +668,27 @@ static void netlink_parse_numgen(struct netlink_parse_ctx 
*ctx,
 {
        enum nft_registers dreg;
        uint32_t type, until, offset;
-       struct expr *expr;
+       const char *name;
+       struct expr *expr, *right, *map_expr = NULL;
+       struct set *map;
 
        type  = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_TYPE);
        until = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_MODULUS);
        offset = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_OFFSET);
 
-       expr = numgen_expr_alloc(loc, type, until, offset);
+       name = nftnl_expr_get_str(nle, NFTNL_EXPR_NG_SET_NAME);
+       if (name != NULL) {
+               map  = set_lookup(ctx->table, name);
+               if (map == NULL) {
+                       return netlink_error(ctx, loc,
+                                       "Unknown map '%s' in numgen expression",
+                                       name);
+               }
+               right = set_ref_expr_alloc(loc, map);
+               map_expr = map_expr_alloc(loc, NULL, right);
+       }
+
+       expr = numgen_expr_alloc(loc, type, until, offset, map_expr);
        dreg = netlink_parse_register(nle, NFTNL_EXPR_NG_DREG);
        netlink_set_register(ctx, dreg, expr);
 }
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 6c49969..6f8fdc7 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -218,6 +218,14 @@ static void netlink_gen_numgen(struct 
netlink_linearize_ctx *ctx,
        nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_TYPE, expr->numgen.type);
        nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_MODULUS, expr->numgen.mod);
        nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_OFFSET, expr->numgen.offset);
+
+       if (expr->numgen.ng_map) {
+               nftnl_expr_set_str(nle, NFTNL_EXPR_NG_SET_NAME,
+                                  expr->numgen.ng_map->mappings->identifier);
+               nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_SET_ID,
+                                  
expr->numgen.ng_map->mappings->set->handle.set_id);
+       }
+
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
diff --git a/src/numgen.c b/src/numgen.c
index aa6da49..cf35a407 100644
--- a/src/numgen.c
+++ b/src/numgen.c
@@ -35,13 +35,18 @@ static void numgen_expr_print(const struct expr *expr, 
struct output_ctx *octx)
                  expr->numgen.mod);
        if (expr->numgen.offset)
                nft_print(octx, " offset %u", expr->numgen.offset);
+       if (expr->numgen.ng_map) {
+               nft_print(octx, " ");
+               expr_print(expr->numgen.ng_map->mappings, octx);
+       }
 }
 
 static bool numgen_expr_cmp(const struct expr *e1, const struct expr *e2)
 {
        return e1->numgen.type == e2->numgen.type &&
               e1->numgen.mod == e2->numgen.mod &&
-              e1->numgen.offset == e2->numgen.offset;
+              e1->numgen.offset == e2->numgen.offset &&
+              expr_cmp(e1->numgen.ng_map, e2->numgen.ng_map);
 }
 
 static void numgen_expr_clone(struct expr *new, const struct expr *expr)
@@ -49,6 +54,8 @@ static void numgen_expr_clone(struct expr *new, const struct 
expr *expr)
        new->numgen.type = expr->numgen.type;
        new->numgen.mod = expr->numgen.mod;
        new->numgen.offset = expr->numgen.offset;
+       if (expr->numgen.ng_map)
+               new->numgen.ng_map = expr_clone(expr->numgen.ng_map);
 }
 
 static const struct expr_ops numgen_expr_ops = {
@@ -61,7 +68,7 @@ static const struct expr_ops numgen_expr_ops = {
 
 struct expr *numgen_expr_alloc(const struct location *loc,
                               enum nft_ng_types type, uint32_t mod,
-                              uint32_t offset)
+                              uint32_t offset, struct expr *mappings)
 {
        struct expr *expr;
 
@@ -70,6 +77,8 @@ struct expr *numgen_expr_alloc(const struct location *loc,
        expr->numgen.type  = type;
        expr->numgen.mod   = mod;
        expr->numgen.offset = offset;
+       if (mappings)
+               expr->numgen.ng_map = mappings;
 
        return expr;
 }
diff --git a/src/parser_bison.y b/src/parser_bison.y
index f546b9e..4a010e6 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -660,8 +660,8 @@ int nft_lex(void *, void *, void *);
 %type <expr>                   arp_hdr_expr
 %destructor { expr_free($$); } arp_hdr_expr
 %type <val>                    arp_hdr_field
-%type <expr>                   ip_hdr_expr     icmp_hdr_expr           
numgen_expr     hash_expr
-%destructor { expr_free($$); } ip_hdr_expr     icmp_hdr_expr           
numgen_expr     hash_expr
+%type <expr>                   ip_hdr_expr     icmp_hdr_expr           
numgen_expr     numgen_map_expr         hash_expr
+%destructor { expr_free($$); } ip_hdr_expr     icmp_hdr_expr           
numgen_expr     numgen_map_expr         hash_expr
 %type <val>                    ip_hdr_field    icmp_hdr_field
 %type <expr>                   ip6_hdr_expr    icmp6_hdr_expr
 %destructor { expr_free($$); } ip6_hdr_expr    icmp6_hdr_expr
@@ -3509,12 +3509,20 @@ numgen_type             :       INC             { $$ = 
NFT_NG_INCREMENTAL; }
                        |       RANDOM          { $$ = NFT_NG_RANDOM; }
                        ;
 
-numgen_expr            :       NUMGEN  numgen_type     MOD     NUM     
offset_opt
+numgen_map_expr                :       /* empty */     { $$ = NULL; }
+                       |       symbol_expr
                        {
-                               $$ = numgen_expr_alloc(&@$, $2, $4, $5);
+                               $$ = map_expr_alloc(&@$, NULL, $1);
+                               $$->flags  |= NFT_SET_OBJECT;
                        }
                        ;
 
+numgen_expr            :       NUMGEN  numgen_type     MOD     NUM     
offset_opt      numgen_map_expr
+                       {
+                               $$ = numgen_expr_alloc(&@$, $2, $4, $5, $6);
+                        }
+                       ;
+
 hash_expr              :       JHASH           expr    MOD     NUM     SEED    
NUM     offset_opt
                        {
                                $$ = hash_expr_alloc(&@$, $4, true, $6, $7, 
NFT_HASH_JENKINS);
-- 
2.11.0

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

Reply via email to