From 079041bd477f444d29e02c6442351c0ed6ffaa1e Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sun, 29 Dec 2013 19:28:10 +0100 Subject: src: add support for queue This patch adds support for the queue target. It is now possible to specify rule sending packet to a given queue and using load balancing: nft add rule filter output queue num 3 total 2 options fanout Signed-off-by: Eric Leblond Signed-off-by: Pablo Neira Ayuso --- src/evaluate.c | 2 ++ src/netlink_delinearize.c | 15 +++++++++++ src/netlink_linearize.c | 22 ++++++++++++++++ src/parser.y | 67 +++++++++++++++++++++++++++++++++++++++++++---- src/scanner.l | 8 +++++- src/statement.c | 31 ++++++++++++++++++++++ 6 files changed, 139 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/evaluate.c b/src/evaluate.c index 94fee64b..d4f83396 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1174,6 +1174,8 @@ static int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt) return stmt_evaluate_reject(ctx, stmt); case STMT_NAT: return stmt_evaluate_nat(ctx, stmt); + case STMT_QUEUE: + return 0; default: BUG("unknown statement type %s\n", stmt->ops->name); } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index d1d35f85..b771da59 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -508,6 +508,20 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx, list_add_tail(&stmt->list, &ctx->rule->stmts); } +static void netlink_parse_queue(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nft_rule_expr *nle) +{ + struct stmt *stmt; + + stmt = queue_stmt_alloc(loc); + stmt->queue.queuenum = nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_NUM); + stmt->queue.queues_total = + nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_TOTAL); + stmt->queue.flags = nft_rule_expr_get_u16(nle, NFT_EXPR_QUEUE_FLAGS); + list_add_tail(&stmt->list, &ctx->rule->stmts); +} + static const struct { const char *name; void (*parse)(struct netlink_parse_ctx *ctx, @@ -528,6 +542,7 @@ static const struct { { .name = "limit", .parse = netlink_parse_limit }, { .name = "reject", .parse = netlink_parse_reject }, { .name = "nat", .parse = netlink_parse_nat }, + { .name = "queue", .parse = netlink_parse_queue }, }; static const struct input_descriptor indesc_netlink = { diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 0ac0218d..9ae9bb76 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -636,6 +636,26 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx, nft_rule_add_expr(ctx->nlr, nle); } +static void netlink_gen_queue_stmt(struct netlink_linearize_ctx *ctx, + const struct stmt *stmt) +{ + struct nft_rule_expr *nle; + + nle = alloc_nft_expr("queue"); + + nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_NUM, + stmt->queue.queuenum); + if (stmt->queue.queues_total) { + nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_TOTAL, + stmt->queue.queues_total); + } + if (stmt->queue.flags) { + nft_rule_expr_set_u16(nle, NFT_EXPR_QUEUE_FLAGS, + stmt->queue.flags); + } + nft_rule_add_expr(ctx->nlr, nle); +} + static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { @@ -656,6 +676,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx, return netlink_gen_reject_stmt(ctx, stmt); case STMT_NAT: return netlink_gen_nat_stmt(ctx, stmt); + case STMT_QUEUE: + return netlink_gen_queue_stmt(ctx, stmt); default: BUG("unknown statement type %s\n", stmt->ops->name); } diff --git a/src/parser.y b/src/parser.y index 26e71e37..9320f2dd 100644 --- a/src/parser.y +++ b/src/parser.y @@ -180,7 +180,6 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token JUMP "jump" %token GOTO "goto" %token RETURN "return" -%token QUEUE "queue" %token NUM "number" %token STRING "string" @@ -330,6 +329,13 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SNAT "snat" %token DNAT "dnat" +%token QUEUE "queue" +%token QUEUENUM "num" +%token QUEUETOTAL "total" +%token QUEUEBYPASS "bypass" +%token QUEUECPUFANOUT "fanout" +%token OPTIONS "options" + %token POSITION "position" %type identifier string @@ -377,6 +383,9 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { stmt_free($$); } reject_stmt %type nat_stmt nat_stmt_alloc %destructor { stmt_free($$); } nat_stmt nat_stmt_alloc +%type queue_stmt queue_stmt_alloc +%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc +%type queue_flags queue_flag %type symbol_expr verdict_expr integer_expr %destructor { expr_free($$); } symbol_expr verdict_expr integer_expr @@ -927,6 +936,7 @@ stmt : verdict_stmt | limit_stmt | reject_stmt | nat_stmt + | queue_stmt ; verdict_stmt : verdict_expr @@ -1051,6 +1061,57 @@ nat_stmt_args : expr } ; +queue_stmt : queue_stmt_alloc + | queue_stmt_alloc queue_args + ; + +queue_stmt_alloc : QUEUE + { + $$ = queue_stmt_alloc(&@$); + } + ; + +queue_args : queue_arg + { + $$ = $0; + } + | queue_args queue_arg + ; + +queue_arg : QUEUENUM NUM + { + $0->queue.queuenum = $2; + } + | QUEUETOTAL NUM + { + $0->queue.queues_total = $2; + } + | OPTIONS queue_flags + { + $0->queue.flags = $2; + } + ; + +queue_flags : queue_flag + { + $$ = $1; + } + | queue_flags COMMA queue_flag + { + $$ |= $1 | $3; + } + ; + +queue_flag : QUEUEBYPASS + { + $$ = NFT_QUEUE_FLAG_BYPASS; + } + | QUEUECPUFANOUT + { + $$ = NFT_QUEUE_FLAG_CPU_FANOUT; + } + ; + match_stmt : relational_expr { $$ = expr_stmt_alloc(&@$, $1); @@ -1287,10 +1348,6 @@ verdict_expr : ACCEPT { $$ = verdict_expr_alloc(&@$, NF_DROP, NULL); } - | QUEUE - { - $$ = verdict_expr_alloc(&@$, NF_QUEUE, NULL); - } | CONTINUE { $$ = verdict_expr_alloc(&@$, NFT_CONTINUE, NULL); diff --git a/src/scanner.l b/src/scanner.l index cee6aa6e..8c4f25d2 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -234,7 +234,6 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "jump" { return JUMP; } "goto" { return GOTO; } "return" { return RETURN; } -"queue" { return QUEUE; } "add" { return ADD; } "insert" { return INSERT; } @@ -255,6 +254,13 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "snaplen" { return SNAPLEN; } "queue-threshold" { return QUEUE_THRESHOLD; } +"queue" { return QUEUE;} +"num" { return QUEUENUM;} +"total" { return QUEUETOTAL;} +"bypass" { return QUEUEBYPASS;} +"fanout" { return QUEUECPUFANOUT;} +"options" { return OPTIONS;} + "limit" { return LIMIT; } "rate" { return RATE; } diff --git a/src/statement.c b/src/statement.c index d18e0340..3fdd9e2d 100644 --- a/src/statement.c +++ b/src/statement.c @@ -172,6 +172,37 @@ struct stmt *limit_stmt_alloc(const struct location *loc) return stmt_alloc(loc, &limit_stmt_ops); } +static void queue_stmt_print(const struct stmt *stmt) +{ + int one = 0; + + printf("queue num %u total %u", + stmt->queue.queuenum, stmt->queue.queues_total); + if (stmt->queue.flags) + printf(" options "); + if (stmt->queue.flags & NFT_QUEUE_FLAG_BYPASS) { + printf("bypass"); + one = 1; + } + if (stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT) { + if (one) + printf (","); + printf("fanout"); + } + +} + +static const struct stmt_ops queue_stmt_ops = { + .type = STMT_QUEUE, + .name = "queue", + .print = queue_stmt_print, +}; + +struct stmt *queue_stmt_alloc(const struct location *loc) +{ + return stmt_alloc(loc, &queue_stmt_ops); +} + static void reject_stmt_print(const struct stmt *stmt) { printf("reject"); -- cgit v1.2.3