]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add ecn support
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 10 May 2016 22:22:11 +0000 (00:22 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 11 May 2016 21:01:31 +0000 (23:01 +0200)
This supports both IPv4:

 # nft --debug=netlink add rule ip filter forward ip ecn ce counter
 ip filter forward
  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = (reg=1 & 0x00000003 ) ^ 0x00000000 ]
  [ cmp eq reg 1 0x00000003 ]
  [ counter pkts 0 bytes 0 ]

For IPv6:

 # nft --debug=netlink add rule ip6 filter forward ip6 ecn ce counter
 ip6 filter forward
  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = (reg=1 & 0x00000030 ) ^ 0x00000000 ]
  [ cmp eq reg 1 0x00000030 ]
  [ counter pkts 0 bytes 0 ]

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
doc/nft.xml
include/datatype.h
include/proto.h
src/parser_bison.y
src/proto.c
src/scanner.l

index a2770bfa94b787a210980b389234fc465da98108..22d023e8d456ca8698309671eb1df90d7cd1c8dd 100644 (file)
@@ -1397,6 +1397,11 @@ filter output oif eth0
                                                                <entry>Differentiated Services Code Point</entry>
                                                                <entry>integer (6 bit)</entry>
                                                        </row>
+                                                       <row>
+                                                               <entry>ecn</entry>
+                                                               <entry>Explicit Congestion Notification</entry>
+                                                               <entry>integer (2 bit)</entry>
+                                                       </row>
                                                        <row>
                                                                <entry>length</entry>
                                                                <entry>Total packet length</entry>
@@ -1481,6 +1486,11 @@ filter output oif eth0
                                                                <entry>Differentiated Services Code Point</entry>
                                                                <entry>integer (6 bit)</entry>
                                                        </row>
+                                                       <row>
+                                                               <entry>ecn</entry>
+                                                               <entry>Explicit Congestion Notification</entry>
+                                                               <entry>integer (2 bit)</entry>
+                                                       </row>
                                                        <row>
                                                                <entry>flowlabel</entry>
                                                                <entry>Flow label</entry>
index e385bac10d496684b7730706fc99c1d43e5f2d49..c7e110f5af88f72f3bece4090705f0503d20ad97 100644 (file)
@@ -80,6 +80,7 @@ enum datatypes {
        TYPE_ICMPX_CODE,
        TYPE_DEVGROUP,
        TYPE_DSCP,
+       TYPE_ECN,
        __TYPE_MAX
 };
 #define TYPE_MAX               (__TYPE_MAX - 1)
index 14af9653dceadbfc4288acb4cac1dc1ee97a24c7..4fa54a74b00c1eb4ca219d4e1c5730340c9db1e3 100644 (file)
@@ -184,6 +184,7 @@ enum ip_hdr_fields {
        IPHDR_VERSION,
        IPHDR_HDRLENGTH,
        IPHDR_DSCP,
+       IPHDR_ECN,
        IPHDR_LENGTH,
        IPHDR_ID,
        IPHDR_FRAG_OFF,
@@ -221,6 +222,7 @@ enum ip6_hdr_fields {
        IP6HDR_INVALID,
        IP6HDR_VERSION,
        IP6HDR_DSCP,
+       IP6HDR_ECN,
        IP6HDR_FLOWLABEL,
        IP6HDR_LENGTH,
        IP6HDR_NEXTHDR,
index 490047b9d3ba8da6dd17189a1e1485572126d72a..b8d33861aca1c96150eb810211ade52e0fb02bdb 100644 (file)
@@ -249,6 +249,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token HDRVERSION              "version"
 %token HDRLENGTH               "hdrlength"
 %token DSCP                    "dscp"
+%token ECN                     "ecn"
 %token LENGTH                  "length"
 %token FRAG_OFF                        "frag-off"
 %token TTL                     "ttl"
@@ -1103,6 +1104,7 @@ type_identifier_list      :       type_identifier
 type_identifier                :       STRING  { $$ = $1; }
                        |       MARK    { $$ = xstrdup("mark"); }
                        |       DSCP    { $$ = xstrdup("dscp"); }
+                       |       ECN     { $$ = xstrdup("ecn"); }
                        ;
 
 hook_spec              :       TYPE            STRING          HOOK            STRING          dev_spec        PRIORITY        prio_spec
@@ -2187,6 +2189,12 @@ primary_rhs_expr :       symbol_expr             { $$ = $1; }
                                                       current_scope(state),
                                                       "dnat");
                        }
+                       |       ECN
+                       {
+                               $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
+                                                      current_scope(state),
+                                                      "ecn");
+                       }
                        ;
 
 relational_op          :       EQ              { $$ = OP_EQ; }
@@ -2405,6 +2413,7 @@ ip_hdr_expr               :       IP      ip_hdr_field
 ip_hdr_field           :       HDRVERSION      { $$ = IPHDR_VERSION; }
                        |       HDRLENGTH       { $$ = IPHDR_HDRLENGTH; }
                        |       DSCP            { $$ = IPHDR_DSCP; }
+                       |       ECN             { $$ = IPHDR_ECN; }
                        |       LENGTH          { $$ = IPHDR_LENGTH; }
                        |       ID              { $$ = IPHDR_ID; }
                        |       FRAG_OFF        { $$ = IPHDR_FRAG_OFF; }
@@ -2438,6 +2447,7 @@ ip6_hdr_expr              :       IP6     ip6_hdr_field
 
 ip6_hdr_field          :       HDRVERSION      { $$ = IP6HDR_VERSION; }
                        |       DSCP            { $$ = IP6HDR_DSCP; }
+                       |       ECN             { $$ = IP6HDR_ECN; }
                        |       FLOWLABEL       { $$ = IP6HDR_FLOWLABEL; }
                        |       LENGTH          { $$ = IP6HDR_LENGTH; }
                        |       NEXTHDR         { $$ = IP6HDR_NEXTHDR; }
index 4c65e1c312573385bd4d4b819675d0a9e5e8ba2c..4c12977cef082bfac7832db9f048badcc4d6f671 100644 (file)
@@ -552,6 +552,27 @@ static const struct datatype dscp_type = {
        .sym_tbl        = &dscp_type_tbl,
 };
 
+static const struct symbol_table ecn_type_tbl = {
+       .symbols        = {
+               SYMBOL("not-ect",       0x00),
+               SYMBOL("ect1",          0x01),
+               SYMBOL("ect0",          0x02),
+               SYMBOL("ce",            0x03),
+               SYMBOL_LIST_END
+       },
+};
+
+static const struct datatype ecn_type = {
+       .type           = TYPE_ECN,
+       .name           = "ecn",
+       .desc           = "Explicit Congestion Notification",
+       .byteorder      = BYTEORDER_BIG_ENDIAN,
+       .size           = 2,
+       .basetype       = &integer_type,
+       .basefmt        = "0x%.1Zx",
+       .sym_tbl        = &ecn_type_tbl,
+};
+
 #define IPHDR_FIELD(__name, __member) \
        HDR_FIELD(__name, struct iphdr, __member)
 #define IPHDR_ADDR(__name, __member) \
@@ -577,6 +598,7 @@ const struct proto_desc proto_ip = {
                [IPHDR_VERSION]         = HDR_BITFIELD("version", &integer_type, 0, 4),
                [IPHDR_HDRLENGTH]       = HDR_BITFIELD("hdrlength", &integer_type, 4, 4),
                [IPHDR_DSCP]            = HDR_BITFIELD("dscp", &dscp_type, 8, 6),
+               [IPHDR_ECN]             = HDR_BITFIELD("ecn", &ecn_type, 14, 2),
                [IPHDR_LENGTH]          = IPHDR_FIELD("length",         tot_len),
                [IPHDR_ID]              = IPHDR_FIELD("id",             id),
                [IPHDR_FRAG_OFF]        = IPHDR_FIELD("frag-off",       frag_off),
@@ -588,8 +610,8 @@ const struct proto_desc proto_ip = {
        },
        .format         = {
                .order  = {
-                       IPHDR_SADDR, IPHDR_DADDR, IPHDR_DSCP, IPHDR_TTL,
-                       IPHDR_ID, IPHDR_PROTOCOL, IPHDR_LENGTH,
+                       IPHDR_SADDR, IPHDR_DADDR, IPHDR_DSCP, IPHDR_ECN,
+                       IPHDR_TTL, IPHDR_ID, IPHDR_PROTOCOL, IPHDR_LENGTH,
                },
                .filter = (1 << IPHDR_VERSION)  | (1 << IPHDR_HDRLENGTH) |
                          (1 << IPHDR_FRAG_OFF),
@@ -683,6 +705,7 @@ const struct proto_desc proto_ip6 = {
        .templates      = {
                [IP6HDR_VERSION]        = HDR_BITFIELD("version", &integer_type, 0, 4),
                [IP6HDR_DSCP]           = HDR_BITFIELD("dscp", &dscp_type, 4, 6),
+               [IP6HDR_ECN]            = HDR_BITFIELD("ecn", &ecn_type, 10, 2),
                [IP6HDR_FLOWLABEL]      = HDR_BITFIELD("flowlabel", &integer_type, 12, 20),
                [IP6HDR_LENGTH]         = IP6HDR_FIELD("length",        payload_len),
                [IP6HDR_NEXTHDR]        = INET_PROTOCOL("nexthdr", struct ipv6hdr, nexthdr),
@@ -692,7 +715,7 @@ const struct proto_desc proto_ip6 = {
        },
        .format         = {
                .order  = {
-                       IP6HDR_SADDR, IP6HDR_DADDR, IP6HDR_DSCP,
+                       IP6HDR_SADDR, IP6HDR_DADDR, IP6HDR_DSCP, IP6HDR_ECN,
                        IP6HDR_HOPLIMIT, IP6HDR_FLOWLABEL, IP6HDR_NEXTHDR,
                        IP6HDR_LENGTH,
                },
@@ -923,4 +946,5 @@ static void __init proto_init(void)
        datatype_register(&ethertype_type);
        datatype_register(&icmp6_type_type);
        datatype_register(&dscp_type);
+       datatype_register(&ecn_type);
 }
index 275beaa178600582dcbce089809b766be1cef754..e8b216ef6ae8a6ee0dc0c6d6df07636e59560dff 100644 (file)
@@ -363,6 +363,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "version"              { return HDRVERSION; }
 "hdrlength"            { return HDRLENGTH; }
 "dscp"                 { return DSCP; }
+"ecn"                  { return ECN; }
 "length"               { return LENGTH; }
 "frag-off"             { return FRAG_OFF; }
 "ttl"                  { return TTL; }