summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Leblond <eric@regit.org>2013-12-29 19:28:10 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2014-01-04 01:07:39 +0100
commit079041bd477f444d29e02c6442351c0ed6ffaa1e (patch)
treeb4472282e4aaab269d4425af453e957c1e82a008 /src
parent35f9338e6ae0169b9a8fd665d4f02608224010c5 (diff)
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 <eric@regit.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c2
-rw-r--r--src/netlink_delinearize.c15
-rw-r--r--src/netlink_linearize.c22
-rw-r--r--src/parser.y67
-rw-r--r--src/scanner.l8
-rw-r--r--src/statement.c31
6 files changed, 139 insertions, 6 deletions
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 <val> NUM "number"
%token <string> 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 <string> identifier string
@@ -377,6 +383,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%destructor { stmt_free($$); } reject_stmt
%type <stmt> nat_stmt nat_stmt_alloc
%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc
+%type <stmt> queue_stmt queue_stmt_alloc
+%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
+%type <val> queue_flags queue_flag
%type <expr> 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
+ {
+ $<stmt>$ = $<stmt>0;
+ }
+ | queue_args queue_arg
+ ;
+
+queue_arg : QUEUENUM NUM
+ {
+ $<stmt>0->queue.queuenum = $2;
+ }
+ | QUEUETOTAL NUM
+ {
+ $<stmt>0->queue.queues_total = $2;
+ }
+ | OPTIONS queue_flags
+ {
+ $<stmt>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");