]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: meta priority support using tc classid
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 16 Aug 2016 21:30:18 +0000 (23:30 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 18 Aug 2016 01:14:58 +0000 (03:14 +0200)
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@netfilter.org>
src/cli.c
src/erec.c
src/main.c
src/meta.c
src/scanner.l
src/statement.c
tests/py/any/meta.t
tests/py/any/meta.t.payload

index adffd6b9e7c0d600c7bdac993d238b3456a53037..a74411a07890a2a50b7368fcc35de3c3441a44e9 100644 (file)
--- 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);
index 0a1e6c74781dc38a6467443d10d02aa7401d6695..36032165bcd9c3489e2d8c01d8323a49eb9adf7c 100644 (file)
@@ -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));
index ad73d800de410cd7629871959e3e4e15d5f75bcf..39a47bbc250a304b1785310119dda14f273a5abf 100644 (file)
@@ -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);
index 1b17819798c1aa1b0ce1f9f354b9cbd9111e3a69..5a6fee5cdf793d0d3980a0469b2185ed82b3cc52 100644 (file)
@@ -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 = {
index b1420f352f10d67516655936e995d321649b8e79..e9384fd66b3c9fb1bd74341ed0f4150b928b799b 100644 (file)
@@ -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);
index fbe74a64eec8a1abe71356459186a3588e14b91b..59b133c22c07e31805a5603d933a40e0c2b07105 100644 (file)
@@ -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);
        }
 
index 9015a219187d8ad93f672eb3d45f535af9061e46..ceeac4851b801c60c20133c68fb16da67b3f36c3 100644 (file)
@@ -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
index 0affd9258966269bec64783ae95311d914754d8a..19bb17c08c14733181c171bfe2021873808646ba 100644 (file)
@@ -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 ]
+