]> git.puffer.fish Git - matthieu/frr.git/commitdiff
*: add flowspec dscp handling
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 13 Jun 2018 09:59:07 +0000 (11:59 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 28 Jun 2018 09:08:55 +0000 (11:08 +0200)
Only one dscp value is accepted as filtering option.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_pbr.c
bgpd/bgp_pbr.h
bgpd/bgp_zebra.c
lib/pbr.h
zebra/zapi_msg.c
zebra/zebra_pbr.c
zebra/zebra_pbr.h

index 75605cd10cf88852da4a273bfed0db1ecd877359..20aa6773eebb9a56e609bfec525fcbe05900467f 100644 (file)
@@ -206,6 +206,7 @@ struct bgp_pbr_filter {
        struct bgp_pbr_range_port *src_port;
        struct bgp_pbr_range_port *dst_port;
        struct bgp_pbr_val_mask *tcp_flags;
+       struct bgp_pbr_val_mask *dscp;
 };
 
 /* this structure is used to contain OR instructions
@@ -394,15 +395,6 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
         * - combination src/dst => drop
         * - combination srcport + @IP
         */
-       if (api->match_dscp_num) {
-               if (BGP_DEBUG(pbr, PBR)) {
-                       bgp_pbr_print_policy_route(api);
-                       zlog_debug("BGP: some SET actions not supported by Zebra. ignoring.");
-                       zlog_debug("BGP: case icmp or length or dscp or tcp flags");
-               }
-               return 0;
-       }
-
        if (api->match_protocol_num > 1) {
                if (BGP_DEBUG(pbr, PBR))
                        zlog_debug("BGP: match protocol operations:"
@@ -481,6 +473,15 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
                                   "too complex. ignoring.");
                return 0;
        }
+       if (api->match_dscp_num > 1 ||
+           !bgp_pbr_extract_enumerate(api->dscp,
+                                      api->match_dscp_num,
+                                      OPERATOR_UNARY_OR, NULL)) {
+               if (BGP_DEBUG(pbr, PBR))
+                       zlog_debug("BGP: match DSCP operations:"
+                                  "too complex. ignoring.");
+               return 0;
+       }
        /* no combinations with both src_port and dst_port
         * or port with src_port and dst_port
         */
@@ -727,6 +728,7 @@ uint32_t bgp_pbr_match_hash_key(void *arg)
        key = jhash_1word(pbm->pkt_len_max, key);
        key = jhash_1word(pbm->tcp_flags, key);
        key = jhash_1word(pbm->tcp_mask_flags, key);
+       key = jhash_1word(pbm->dscp_value, key);
        return jhash_1word(pbm->type, key);
 }
 
@@ -761,6 +763,8 @@ int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
        if (r1->tcp_mask_flags != r2->tcp_mask_flags)
                return 0;
 
+       if (r1->dscp_value != r2->dscp_value)
+               return 0;
        return 1;
 }
 
@@ -1235,6 +1239,13 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp,
                temp.tcp_flags = bpf->tcp_flags->val;
                temp.tcp_mask_flags = bpf->tcp_flags->mask;
        }
+       if (bpf->dscp) {
+               if (bpf->dscp->mask)
+                       temp.flags |= MATCH_DSCP_INVERSE_SET;
+               else
+                       temp.flags |= MATCH_DSCP_SET;
+               temp.dscp_value = bpf->dscp->val;
+       }
 
        if (bpf->src == NULL || bpf->dst == NULL) {
                if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
@@ -1372,6 +1383,15 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
                                                  bpf->tcp_flags->val,
                                                  bpf->tcp_flags->mask);
                }
+               if (bpf->dscp) {
+                       snprintf(buffer + remaining_len,
+                                sizeof(buffer)
+                                - remaining_len,
+                                "%s dscp %d",
+                                bpf->dscp->mask
+                                ? "!" : "",
+                                bpf->dscp->val);
+               }
                zlog_info("BGP: adding FS PBR from %s to %s, %s %s",
                          bpf->src == NULL ? "<all>" :
                          prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
@@ -1442,6 +1462,13 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
                temp.tcp_flags = bpf->tcp_flags->val;
                temp.tcp_mask_flags = bpf->tcp_flags->mask;
        }
+       if (bpf->dscp) {
+               if (bpf->dscp->mask)
+                       temp.flags |= MATCH_DSCP_INVERSE_SET;
+               else
+                       temp.flags |= MATCH_DSCP_SET;
+               temp.dscp_value = bpf->dscp->val;
+       }
        temp.action = bpa;
        bpm = hash_get(bgp->pbr_match_hash, &temp,
                       bgp_pbr_match_alloc_intern);
@@ -1805,6 +1832,11 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
                                &pkt_len);
                bpf.pkt_len = &pkt_len;
        }
+       if (api->match_dscp_num >= 1) {
+               bpf.dscp_presence = true;
+               bpf.dscp_value = api->dscp[0].value;
+
+       }
        bpf.vrf_id = api->vrf_id;
        bpf.src = src;
        bpf.dst = dst;
index 6a06ba3893ed312f7eb1427e6e1d94409f07309c..8a95b85df3e6f49d28f64d8e5f7d036aa36febef 100644 (file)
@@ -184,6 +184,7 @@ struct bgp_pbr_match {
        uint16_t pkt_len_max;
        uint16_t tcp_flags;
        uint16_t tcp_mask_flags;
+       uint8_t dscp_value;
 
        vrf_id_t vrf_id;
 
index d201b48bad7d77f105d4e2ff6d3885dfbae16f7c..0ca9774b7ff22be343ee5ed01bd0ce16af6748d6 100644 (file)
@@ -2223,6 +2223,7 @@ static void bgp_encode_pbr_iptable_match(struct stream *s,
        stream_putw(s, pbm->pkt_len_max);
        stream_putw(s, pbm->tcp_flags);
        stream_putw(s, pbm->tcp_mask_flags);
+       stream_putc(s, pbm->dscp_value);
 }
 
 /* BGP has established connection with Zebra. */
index 5936851e4e17840e0df835b71f71e4747338833f..36a47d049bf22b5bcda92adfbd5d09f5387e8c3d 100644 (file)
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -112,6 +112,8 @@ struct pbr_rule {
 #define MATCH_PORT_DST_SET             (1 << 3)
 #define MATCH_PORT_SRC_RANGE_SET       (1 << 4)
 #define MATCH_PORT_DST_RANGE_SET       (1 << 5)
+#define MATCH_DSCP_SET                 (1 << 6)
+#define MATCH_DSCP_INVERSE_SET         (1 << 7)
 
 extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
                                struct pbr_rule *zrule);
index f0741412132336d45157949ac06536d50d958c95..dfbbb8e61f8fac2f9f2607894a1d67fef62ca9d2 100644 (file)
@@ -2942,6 +2942,7 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS)
        STREAM_GETW(s, zpi.pkt_len_max);
        STREAM_GETW(s, zpi.tcp_flags);
        STREAM_GETW(s, zpi.tcp_mask_flags);
+       STREAM_GETC(s, zpi.dscp_value);
        STREAM_GETL(s, zpi.nb_interface);
        zebra_pbr_iptable_update_interfacelist(s, &zpi);
 
index 12000e7755f6312aaf3d7cf96383fef2089431ec..9f75516106b647843a12e273618dda031534316d 100644 (file)
@@ -375,6 +375,7 @@ uint32_t zebra_pbr_iptable_hash_key(void *arg)
        key = jhash_1word(iptable->pkt_len_max, key);
        key = jhash_1word(iptable->tcp_flags, key);
        key = jhash_1word(iptable->tcp_mask_flags, key);
+       key = jhash_1word(iptable->dscp_value, key);
        return jhash_3words(iptable->filter_bm, iptable->type,
                            iptable->unique, key);
 }
@@ -407,6 +408,8 @@ int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
                return 0;
        if (r1->tcp_mask_flags != r2->tcp_mask_flags)
                return 0;
+       if (r1->dscp_value != r2->dscp_value)
+               return 0;
        return 1;
 }
 
index 960768e15cebec9ba3d43a643ac7a0ede0586698..58c71f4d9729a21bac676ec35c8e059b8c173c89 100644 (file)
@@ -137,6 +137,7 @@ struct zebra_pbr_iptable {
        uint16_t pkt_len_max;
        uint16_t tcp_flags;
        uint16_t tcp_mask_flags;
+       uint8_t dscp_value;
 
        uint32_t nb_interface;