summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nf_tables.h20
-rw-r--r--include/statement.h11
-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
8 files changed, 170 insertions, 6 deletions
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index a236cc31..1d5a9253 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -587,6 +587,26 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_queue_attributes - nf_tables queue expression netlink attributes
+ *
+ * @NFTA_QUEUE_NUM: netlink group to send messages to (NLA_U32)
+ * @NFTA_QUEUE_TOTAL: prefix to prepend to log messages (NLA_STRING)
+ * @NFTA_QUEUE_FLAGS: length of payload to include in netlink message (NLA_U32)
+ */
+enum nft_queue_attributes {
+ NFTA_QUEUE_UNSPEC,
+ NFTA_QUEUE_NUM,
+ NFTA_QUEUE_TOTAL,
+ NFTA_QUEUE_FLAGS,
+ __NFTA_QUEUE_MAX
+};
+#define NFTA_QUEUE_MAX (__NFTA_QUEUE_MAX - 1)
+
+#define NFT_QUEUE_FLAG_BYPASS 0x01 /* for compatibility with v2 */
+#define NFT_QUEUE_FLAG_CPU_FANOUT 0x02 /* use current CPU (no hashing) */
+#define NFT_QUEUE_FLAG_MASK 0x03
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
diff --git a/include/statement.h b/include/statement.h
index 6ecbb18d..14a66df6 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -59,6 +59,14 @@ struct nat_stmt {
extern struct stmt *nat_stmt_alloc(const struct location *loc);
+struct queue_stmt {
+ uint16_t queuenum;
+ uint16_t queues_total;
+ uint16_t flags;
+};
+
+extern struct stmt *queue_stmt_alloc(const struct location *loc);
+
/**
* enum stmt_types - statement types
*
@@ -71,6 +79,7 @@ extern struct stmt *nat_stmt_alloc(const struct location *loc);
* @STMT_LOG: log statement
* @STMT_REJECT: REJECT statement
* @STMT_NAT: NAT statement
+ * @STMT_QUEUE: QUEUE statement
*/
enum stmt_types {
STMT_INVALID,
@@ -82,6 +91,7 @@ enum stmt_types {
STMT_LOG,
STMT_REJECT,
STMT_NAT,
+ STMT_QUEUE,
};
/**
@@ -127,6 +137,7 @@ struct stmt {
struct limit_stmt limit;
struct reject_stmt reject;
struct nat_stmt nat;
+ struct queue_stmt queue;
};
};
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");