]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Adding support for segment routing header 'srh'
authorAhmed Abdelsalam <amsalam20@gmail.com>
Tue, 27 Feb 2018 10:04:14 +0000 (11:04 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 11 Mar 2018 21:59:46 +0000 (22:59 +0100)
Segment Routing Header "SRH" is new type of IPv6 Routing extension
header (type 4).

SRH contains a list of segments (each is represented as an IPv6 address)
to be visited by packets during the journey from source to destination.

The SRH specification are defined in the below IETF SRH draft.
https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07

Signed-off-by: Ahmed Abdelsalam <amsalam20@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/exthdr.h
include/headers.h
src/exthdr.c
src/parser_bison.y
src/scanner.l

index 06bf628512a9b6ec6e6c6a65651d70b089e330c0..32f99c9c5f85f098a3ff90625dff918dfd98ee41 100644 (file)
@@ -57,6 +57,14 @@ enum rt2_hdr_fields {
        RT2HDR_ADDR,
 };
 
+enum rt4_hdr_fields {
+       RT4HDR_INVALID,
+       RT4HDR_LASTENT,
+       RT4HDR_FLAGS,
+       RT4HDR_TAG,
+       RT4HDR_SID_1,
+};
+
 enum frag_hdr_fields {
        FRAGHDR_INVALID,
        FRAGHDR_NEXTHDR,
@@ -87,6 +95,7 @@ extern const struct exthdr_desc exthdr_hbh;
 extern const struct exthdr_desc exthdr_rt;
 extern const struct exthdr_desc exthdr_rt0;
 extern const struct exthdr_desc exthdr_rt2;
+extern const struct exthdr_desc exthdr_rt4;
 extern const struct exthdr_desc exthdr_frag;
 extern const struct exthdr_desc exthdr_dst;
 extern const struct exthdr_desc exthdr_mh;
index 469d674073088799b1048e0cdd2ea9104da46ab8..3d564debf8b0916df5b61e56d49b661cab3773c1 100644 (file)
@@ -112,6 +112,18 @@ struct ip6_mh {
        uint8_t         data[0];
 };
 
+/* Type 4 Routing header - well known as srh */
+struct ip6_rt4 {
+       uint8_t         ip6r4_nxt;              /* next header                  */
+       uint8_t         ip6r4_len;              /* length in units of 8 octets  */
+       uint8_t         ip6r4_type;             /* always zero                  */
+       uint8_t         ip6r4_segleft;          /* segments left                */
+       uint8_t         ip6r4_last_entry;       /* last entry                   */
+       uint8_t         ip6r4_flags;            /* flags                        */
+       uint16_t        ip6r4_tag;              /* tag                          */
+       struct in6_addr ip6r4_segments[0];      /* SID list                     */
+};
+
 /* RFC 3775 */
 #define IP6_MH_TYPE_BRR                0       /* Binding Refresh Request      */
 #define IP6_MH_TYPE_HOTI       1       /* HOTI Message                 */
index 3757f3354bd85cd02dedcc8a7ef60774806ecf90..cbe0da86a156ac9177f0678da2c4984d4f934145 100644 (file)
@@ -101,6 +101,9 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
                case 2:
                        expr->exthdr.op = NFT_EXTHDR_OP_RT2;
                        break;
+               case 4:
+                       expr->exthdr.op = NFT_EXTHDR_OP_RT4;
+                       break;
                }
        }
        return expr;
@@ -165,6 +168,8 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
                expr->exthdr.desc = &exthdr_rt0;
        else if (op == NFT_EXTHDR_OP_RT2)
                expr->exthdr.desc = &exthdr_rt2;
+       else if (op == NFT_EXTHDR_OP_RT4)
+               expr->exthdr.desc = &exthdr_rt4;
        else if (type < array_size(exthdr_protocols))
                expr->exthdr.desc = exthdr_protocols[type];
 
@@ -274,6 +279,24 @@ const struct exthdr_desc exthdr_rt0 = {
        },
 };
 
+#define RT4_FIELD(__name, __member, __dtype) \
+       HDR_TEMPLATE(__name, __dtype, struct ip6_rt4, __member)
+
+const struct exthdr_desc exthdr_rt4 = {
+       .name           = "srh",
+       .type           = IPPROTO_ROUTING,
+       .proto_key      = 4,
+       .templates      = {
+               [RT4HDR_LASTENT]        = RT4_FIELD("last-entry", ip6r4_last_entry, &integer_type),
+               [RT4HDR_FLAGS]          = RT4_FIELD("flags", ip6r4_flags, &integer_type),
+               [RT4HDR_TAG]            = RT4_FIELD("tag", ip6r4_tag, &integer_type),
+               [RT4HDR_SID_1]          = RT4_FIELD("sid[1]", ip6r4_segments[0], &ip6addr_type),
+               [RT4HDR_SID_1 + 1]      = RT4_FIELD("sid[1]", ip6r4_segments[0], &ip6addr_type),
+               // ...
+       },
+};
+
+
 #define RT_FIELD(__name, __member, __dtype) \
        HDR_TEMPLATE(__name, __dtype, struct ip6_rthdr, __member)
 
index 2ccaf9abd7513244f845589cbcbbd82c2fbc9bb8..5f84d794079a76e18911bfb13a32c881c791c13a 100644 (file)
@@ -364,8 +364,12 @@ int nft_lex(void *, void *, void *);
 %token RT                      "rt"
 %token RT0                     "rt0"
 %token RT2                     "rt2"
+%token RT4                     "srh"
 %token SEG_LEFT                        "seg-left"
 %token ADDR                    "addr"
+%token LAST_ENT                        "last-entry"
+%token TAG                     "tag"
+%token SID                     "sid"
 
 %token HBH                     "hbh"
 
@@ -674,9 +678,9 @@ int nft_lex(void *, void *, void *);
 %type <expr>                   hbh_hdr_expr    frag_hdr_expr           dst_hdr_expr
 %destructor { expr_free($$); } hbh_hdr_expr    frag_hdr_expr           dst_hdr_expr
 %type <val>                    hbh_hdr_field   frag_hdr_field          dst_hdr_field
-%type <expr>                   rt_hdr_expr     rt0_hdr_expr            rt2_hdr_expr
-%destructor { expr_free($$); } rt_hdr_expr     rt0_hdr_expr            rt2_hdr_expr
-%type <val>                    rt_hdr_field    rt0_hdr_field           rt2_hdr_field
+%type <expr>                   rt_hdr_expr     rt0_hdr_expr            rt2_hdr_expr    rt4_hdr_expr
+%destructor { expr_free($$); } rt_hdr_expr     rt0_hdr_expr            rt2_hdr_expr    rt4_hdr_expr
+%type <val>                    rt_hdr_field    rt0_hdr_field           rt2_hdr_field   rt4_hdr_field
 %type <expr>                   mh_hdr_expr
 %destructor { expr_free($$); } mh_hdr_expr
 %type <val>                    mh_hdr_field
@@ -3921,6 +3925,7 @@ exthdr_expr               :       hbh_hdr_expr
                        |       rt_hdr_expr
                        |       rt0_hdr_expr
                        |       rt2_hdr_expr
+                       |       rt4_hdr_expr
                        |       frag_hdr_expr
                        |       dst_hdr_expr
                        |       mh_hdr_expr
@@ -3969,6 +3974,21 @@ rt2_hdr_expr             :       RT2     rt2_hdr_field
 rt2_hdr_field          :       ADDR            { $$ = RT2HDR_ADDR; }
                        ;
 
+rt4_hdr_expr           :       RT4     rt4_hdr_field
+                       {
+                               $$ = exthdr_expr_alloc(&@$, &exthdr_rt4, $2);
+                       }
+                       ;
+
+rt4_hdr_field          :       LAST_ENT        { $$ = RT4HDR_LASTENT; }
+                       |       FLAGS           { $$ = RT4HDR_FLAGS; }
+                       |       TAG             { $$ = RT4HDR_TAG; }
+                       |       SID             '['     NUM     ']'
+                       {
+                               $$ = RT4HDR_SID_1 + $3 - 1;
+                       }
+                       ;
+
 frag_hdr_expr          :       FRAG    frag_hdr_field
                        {
                                $$ = exthdr_expr_alloc(&@$, &exthdr_frag, $2);
index ab10738b9a953465b74b47d78453804573862fad..1d8e8ba0ecf42ad5fed879bbf2448de9e7b66a80 100644 (file)
@@ -456,8 +456,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
 "rt"                   { return RT; }
 "rt0"                  { return RT0; }
 "rt2"                  { return RT2; }
+"srh"                  { return RT4; }
 "seg-left"             { return SEG_LEFT; }
 "addr"                 { return ADDR; }
+"last-entry"           { return LAST_ENT; }
+"tag"                  { return TAG; }
+"sid"                  { return SID; }
 
 "hbh"                  { return HBH; }