]> 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>
Mon, 2 Jul 2018 07:20:39 +0000 (09:20 +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 9387a0d777fb2e087c30638a689f079ec6f46251..9036bfbab6229bf9c73cea4fb50b46cb6d5d18b1 100644 (file)
@@ -2237,6 +2237,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 72a870f1f3b2211f535dc6262679bcead072af7d..8bc189edad6ace7a663760e1692df5fcb63acc6c 100644 (file)
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -106,6 +106,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 119476a38285394a20c30cdf94dc55158ea3c23c..65626b79cde854b4bf2261daaa72fd5e4cdcbde4 100644 (file)
@@ -2910,6 +2910,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 ea66689fad92f16f4cd852e70b17569b1d7de174..2e232f4db13b41a4bab18c27ed556bd0d44433f6 100644 (file)
@@ -374,6 +374,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);
 }
@@ -406,6 +407,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 8d06aa85949c1a16b7241c05472645cddd5a01a9..a1509091a592a7bc2dffbb03e7ee6f6d9dc19b84 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;