[PATCH nft 09/10] src: meta priority support using tc classid

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds the missing bits to scan and parse the meta priority
handle as expressed by tc classid major:minor syntax.

The :minor syntax is not support for two reason: major is always >= 1
and this clashes with port syntax in nat.

Here below, several example on how to match the packet priority field:

   nft add rule filter forward meta priority abcd:0
   nft add rule filter forward meta priority abcd:1234

and to set it, you have to:

   nft add rule filter forward meta priority set abcd:1234

The priority expression in flex looks ahead to restrict the pattern to
avoid problems with mappings:

{classid}/[ \t\n:\-},]

So the following doesn't break:

   ... vmap { 25:accept }
              ^^^^^

The lookahead expression requires a slight change to extend the input
string in one byte.

This patch is conservative as you always have to explicity indicate
major and minor numbers even if zero.

We could consider supporting this shortcut in the future:

	abcd:

However, with regards to this:

	:abcd

We don't need to support it since major number is assumed to be >= 1.
However, if we ever decide to support this, we'll have problems since
this clashes with our port representation in redirect and mangle.

So let's keep this simple and start with this approach.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/cli.c                   |  8 +++++
 src/erec.c                  |  1 +
 src/main.c                  |  3 +-
 src/meta.c                  | 39 +++++++++++++++++-------
 src/scanner.l               |  6 ++++
 src/statement.c             |  2 +-
 tests/py/any/meta.t         | 22 ++++++++------
 tests/py/any/meta.t.payload | 73 +++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 132 insertions(+), 22 deletions(-)

diff --git a/src/cli.c b/src/cli.c
index adffd6b..a74411a 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -92,6 +92,8 @@ static void cli_complete(char *line)
 	const HIST_ENTRY *hist;
 	const char *c;
 	LIST_HEAD(msgs);
+	int len;
+	char *s;
 
 	if (line == NULL) {
 		printf("\n");
@@ -119,6 +121,12 @@ static void cli_complete(char *line)
 	if (hist == NULL || strcmp(hist->line, line))
 		add_history(line);
 
+	len = strlen(line);
+	s = xmalloc(len + 2);
+	snprintf(s, len + 2, "%s\n", line);
+	xfree(line);
+	line = s;
+
 	parser_init(state, &msgs);
 	scanner_push_buffer(scanner, &indesc_cli, line);
 	nft_run(scanner, state, &msgs);
diff --git a/src/erec.c b/src/erec.c
index 0a1e6c7..3603216 100644
--- a/src/erec.c
+++ b/src/erec.c
@@ -92,6 +92,7 @@ void erec_print(FILE *f, const struct error_record *erec)
 	case INDESC_BUFFER:
 	case INDESC_CLI:
 		line = indesc->data;
+		*strchrnul(line, '\n') = '\0';
 		break;
 	case INDESC_FILE:
 		memset(buf, 0, sizeof(buf));
diff --git a/src/main.c b/src/main.c
index ad73d80..39a47bb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -328,12 +328,13 @@ int main(int argc, char * const *argv)
 		for (len = 0, i = optind; i < argc; i++)
 			len += strlen(argv[i]) + strlen(" ");
 
-		buf = xzalloc(len + 1);
+		buf = xzalloc(len + 2);
 		for (i = optind; i < argc; i++) {
 			strcat(buf, argv[i]);
 			if (i + 1 < argc)
 				strcat(buf, " ");
 		}
+		strcat(buf, "\n");
 		parser_init(&state, &msgs);
 		scanner = scanner_init(&state);
 		scanner_push_buffer(scanner, &indesc_cmdline, buf);
diff --git a/src/meta.c b/src/meta.c
index 1b17819..5a6fee5 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -10,6 +10,7 @@
  * Development of this code funded by Astaro AG (http://www.astaro.com/)
  */
 
+#include <errno.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -89,34 +90,50 @@ static struct error_record *tchandle_type_parse(const struct expr *sym,
 						struct expr **res)
 {
 	uint32_t handle;
+	char *str;
 
 	if (strcmp(sym->identifier, "root") == 0)
 		handle = TC_H_ROOT;
 	else if (strcmp(sym->identifier, "none") == 0)
 		handle = TC_H_UNSPEC;
-	else if (sym->identifier[0] == ':') {
-		if (sscanf(sym->identifier, ":%04x", &handle) != 1)
+	else if (strchr(sym->identifier, ':')) {
+		uint16_t tmp;
+		char *colon;
+
+		str = xstrdup(sym->identifier);
+
+		colon = strchr(str, ':');
+		if (!colon)
 			goto err;
-	} else if (sym->identifier[strlen(sym->identifier)-1] == ':') {
-		if (sscanf(sym->identifier, "%04x:", &handle) != 1)
+
+		*colon = '\0';
+
+		errno = 0;
+		tmp = strtoull(str, NULL, 16);
+		if (errno != 0)
 			goto err;
 
-		handle <<= 16;
-	} else {
-		uint32_t min, max;
+		handle = (tmp << 16);
+		if (str[strlen(str) - 1] == ':')
+			goto out;
 
-		if (sscanf(sym->identifier, "%04x:%04x", &max, &min) != 2)
+		errno = 0;
+		tmp = strtoull(colon + 1, NULL, 16);
+		if (errno != 0)
 			goto err;
 
-		handle = max << 16 | min;
+		handle |= tmp;
+	} else {
+		handle = strtoull(sym->identifier, NULL, 0);
 	}
+out:
 	*res = constant_expr_alloc(&sym->location, sym->dtype,
 				   BYTEORDER_HOST_ENDIAN,
 				   sizeof(handle) * BITS_PER_BYTE, &handle);
 	return NULL;
 err:
-	return error(&sym->location, "Could not parse %s",
-		     sym->dtype->desc);
+	xfree(str);
+	return error(&sym->location, "Could not parse %s", sym->dtype->desc);
 }
 
 static const struct datatype tchandle_type = {
diff --git a/src/scanner.l b/src/scanner.l
index b1420f3..e9384fd 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -170,6 +170,7 @@ ip4addr		(([[:digit:]]{1,3}"."){3}([[:digit:]]{1,3}))
 ip6addr		({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
 ip6addr_rfc2732	(\[{ip6addr}\])
 
+classid		({hexdigit}{1,4}:{hexdigit}{1,4})
 addrstring	({macaddr}|{ip4addr}|{ip6addr})
 
 %option prefix="nft_"
@@ -506,6 +507,11 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 				return NUM;
 			}
 
+{classid}/[ \t\n:\-},]	{
+				yylval->string = xstrdup(yytext);
+				return STRING;
+			}
+
 {quotedstring}		{
 				yytext[yyleng - 1] = '\0';
 				yylval->string = xstrdup(yytext + 1);
diff --git a/src/statement.c b/src/statement.c
index fbe74a6..59b133c 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -477,7 +477,7 @@ static void redir_stmt_print(const struct stmt *stmt)
 	printf("redirect");
 
 	if (stmt->redir.proto) {
-		printf(" to ");
+		printf(" to :");
 		expr_print(stmt->redir.proto);
 	}
 
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
index 11ebf75..86ed719 100644
--- a/tests/py/any/meta.t
+++ b/tests/py/any/meta.t
@@ -38,15 +38,19 @@ meta l4proto { 33, 55, 67, 88};ok;meta l4proto { 33, 55, 67, 88}
 meta l4proto { 33-55};ok
 - meta l4proto != { 33-55};ok
 
-- meta priority :aabb;ok
-- meta priority bcad:dadc;ok
-- meta priority aabb:;ok
-- meta priority != :aabb;ok
-- meta priority != bcad:dadc;ok
-- meta priority != aabb:;ok
-- meta priority bcad:dada-bcad:dadc;ok
-- meta priority != bcad:dada-bcad:dadc;ok
-- meta priority {bcad:dada, bcad:dadc, aaaa:bbbb};ok
+meta priority root;ok
+meta priority none;ok
+meta priority 0x87654321;ok;meta priority 8765:4321
+meta priority 2271560481;ok;meta priority 8765:4321
+meta priority 1:1234;ok
+meta priority bcad:dadc;ok
+meta priority aabb:0;ok
+meta priority != bcad:dadc;ok
+meta priority != aabb:0;ok
+meta priority bcad:dada-bcad:dadc;ok
+meta priority != bcad:dada-bcad:dadc;ok
+meta priority {bcad:dada, bcad:dadc, aaaa:bbbb};ok
+meta priority set cafe:beef;ok
 - meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb};ok
 
 meta mark 0x4;ok;mark 0x00000004
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
index d10d0e6..1b0a057 100644
--- a/tests/py/any/meta.t.payload
+++ b/tests/py/any/meta.t.payload
@@ -790,3 +790,76 @@ ip test-ip4 input
 ip test-ip4 input
   [ meta load prandom => reg 1 ]
   [ cmp gt reg 1 0x40420f00 ]
+
+# meta priority root
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0xffffffff ]
+
+# meta priority none
+netdev test-netdev ingress 
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0x00000000 ]
+
+# meta priority 1:1234
+ip test-ip4 input
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0x00011234 ]
+
+# meta priority bcad:dadc
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0xbcaddadc ]
+
+# meta priority aabb:0
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0xaabb0000 ]
+
+# meta priority != bcad:dadc
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ cmp neq reg 1 0xbcaddadc ]
+
+# meta priority != aabb:0
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ cmp neq reg 1 0xaabb0000 ]
+
+# meta priority bcad:dada-bcad:dadc
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+  [ cmp gte reg 1 0xdadaadbc ]
+  [ cmp lte reg 1 0xdcdaadbc ]
+
+# meta priority != bcad:dada-bcad:dadc
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+  [ cmp lt reg 1 0xdadaadbc ]
+  [ cmp gt reg 1 0xdcdaadbc ]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+__set%d test-ip4 3
+__set%d test-ip4 0
+	element bcaddada  : 0 [end]	element bcaddadc  : 0 [end]	element aaaabbbb  : 0 [end]
+ip test-ip4 input 
+  [ meta load priority => reg 1 ]
+  [ lookup reg 1 set __set%d ]
+
+# meta priority set cafe:beef
+ip test-ip4 input 
+  [ immediate reg 1 0xcafebeef ]
+  [ meta set priority with reg 1 ]
+
+# meta priority 0x87654321
+ip test-ip4 input
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0x87654321 ]
+
+# meta priority 2271560481
+ip test-ip4 input
+  [ meta load priority => reg 1 ]
+  [ cmp eq reg 1 0x87654321 ]
+
-- 
2.1.4

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



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux