From: Philippe Guibert Date: Wed, 13 Jun 2018 09:59:07 +0000 (+0200) Subject: *: add flowspec dscp handling X-Git-Tag: frr-5.0.1~2^2~11 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=d7e3bf1b65195fb36e84e93b93587047546b1063;p=matthieu%2Ffrr.git *: add flowspec dscp handling Only one dscp value is accepted as filtering option. Signed-off-by: Philippe Guibert --- diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 75605cd10c..20aa6773ee 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -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 ? "" : 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; diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index 6a06ba3893..8a95b85df3 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -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; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 9387a0d777..9036bfbab6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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. */ diff --git a/lib/pbr.h b/lib/pbr.h index 72a870f1f3..8bc189edad 100644 --- 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); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 119476a382..65626b79cd 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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); diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index ea66689fad..2e232f4db1 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -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; } diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 8d06aa8594..a1509091a5 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -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;