*: add flowspec dscp handling

Only one dscp value is accepted as filtering option.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2018-06-13 11:59:07 +02:00
parent 9bba145596
commit 4977bd6c19
7 changed files with 50 additions and 9 deletions

View 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;

View 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;

View 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. */

View File

@ -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);

View 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);

View 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;
}

View 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;