forked from Mirror/frr
bgpd: support for enumerate pkt len
The packet length can be injected from fs entry with an enumerate list; the negation of the value is also taken into account. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
56707a36d0
commit
cfaf18ce52
107
bgpd/bgp_pbr.c
107
bgpd/bgp_pbr.c
|
@ -208,6 +208,7 @@ struct bgp_pbr_filter {
|
||||||
struct bgp_pbr_range_port *dst_port;
|
struct bgp_pbr_range_port *dst_port;
|
||||||
struct bgp_pbr_val_mask *tcp_flags;
|
struct bgp_pbr_val_mask *tcp_flags;
|
||||||
struct bgp_pbr_val_mask *dscp;
|
struct bgp_pbr_val_mask *dscp;
|
||||||
|
struct bgp_pbr_val_mask *pkt_len_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* this structure is used to contain OR instructions
|
/* this structure is used to contain OR instructions
|
||||||
|
@ -217,6 +218,7 @@ struct bgp_pbr_filter {
|
||||||
struct bgp_pbr_or_filter {
|
struct bgp_pbr_or_filter {
|
||||||
struct list *tcpflags;
|
struct list *tcpflags;
|
||||||
struct list *dscp;
|
struct list *dscp;
|
||||||
|
struct list *pkt_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TCP : FIN and SYN -> val = ALL; mask = 3
|
/* TCP : FIN and SYN -> val = ALL; mask = 3
|
||||||
|
@ -255,7 +257,8 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
|
||||||
and_valmask->mask |=
|
and_valmask->mask |=
|
||||||
TCP_HEADER_ALL_FLAGS &
|
TCP_HEADER_ALL_FLAGS &
|
||||||
~(list[i].value);
|
~(list[i].value);
|
||||||
} else if (type_entry == FLOWSPEC_DSCP) {
|
} else if (type_entry == FLOWSPEC_DSCP ||
|
||||||
|
type_entry == FLOWSPEC_PKT_LEN) {
|
||||||
and_valmask->val = list[i].value;
|
and_valmask->val = list[i].value;
|
||||||
and_valmask->mask = 1; /* inverse */
|
and_valmask->mask = 1; /* inverse */
|
||||||
}
|
}
|
||||||
|
@ -267,7 +270,8 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
|
||||||
and_valmask->mask |=
|
and_valmask->mask |=
|
||||||
TCP_HEADER_ALL_FLAGS &
|
TCP_HEADER_ALL_FLAGS &
|
||||||
~(list[i].value);
|
~(list[i].value);
|
||||||
} else if (type_entry == FLOWSPEC_DSCP) {
|
} else if (type_entry == FLOWSPEC_DSCP ||
|
||||||
|
type_entry == FLOWSPEC_PKT_LEN) {
|
||||||
and_valmask->val = list[i].value;
|
and_valmask->val = list[i].value;
|
||||||
and_valmask->mask = 1; /* inverse */
|
and_valmask->mask = 1; /* inverse */
|
||||||
}
|
}
|
||||||
|
@ -288,7 +292,8 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
|
||||||
and_valmask->val = TCP_HEADER_ALL_FLAGS;
|
and_valmask->val = TCP_HEADER_ALL_FLAGS;
|
||||||
and_valmask->mask |=
|
and_valmask->mask |=
|
||||||
TCP_HEADER_ALL_FLAGS & list[i].value;
|
TCP_HEADER_ALL_FLAGS & list[i].value;
|
||||||
} else if (type_entry == FLOWSPEC_DSCP)
|
} else if (type_entry == FLOWSPEC_DSCP ||
|
||||||
|
type_entry == FLOWSPEC_PKT_LEN)
|
||||||
and_valmask->val = list[i].value;
|
and_valmask->val = list[i].value;
|
||||||
listnode_add(or_valmask, and_valmask);
|
listnode_add(or_valmask, and_valmask);
|
||||||
}
|
}
|
||||||
|
@ -488,11 +493,23 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
|
||||||
"too complex. ignoring.");
|
"too complex. ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!bgp_pbr_extract(api->packet_length, api->match_packet_length_num, NULL)) {
|
if (api->match_packet_length_num) {
|
||||||
if (BGP_DEBUG(pbr, PBR))
|
bool ret;
|
||||||
zlog_debug("BGP: match packet length operations:"
|
|
||||||
|
ret = bgp_pbr_extract(api->packet_length,
|
||||||
|
api->match_packet_length_num, NULL);
|
||||||
|
if (!ret)
|
||||||
|
ret = bgp_pbr_extract_enumerate(api->packet_length,
|
||||||
|
api->match_packet_length_num,
|
||||||
|
OPERATOR_UNARY_OR
|
||||||
|
| OPERATOR_UNARY_AND,
|
||||||
|
NULL, FLOWSPEC_PKT_LEN);
|
||||||
|
if (!ret) {
|
||||||
|
if (BGP_DEBUG(pbr, PBR))
|
||||||
|
zlog_debug("BGP: match packet length operations:"
|
||||||
"too complex. ignoring.");
|
"too complex. ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (api->match_dscp_num) {
|
if (api->match_dscp_num) {
|
||||||
if (!bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
|
if (!bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
|
||||||
|
@ -1253,10 +1270,15 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp,
|
||||||
}
|
}
|
||||||
temp2.proto = bpf->protocol;
|
temp2.proto = bpf->protocol;
|
||||||
|
|
||||||
if (pkt_len)
|
if (pkt_len) {
|
||||||
temp.pkt_len_min = pkt_len->min_port;
|
temp.pkt_len_min = pkt_len->min_port;
|
||||||
if (pkt_len && pkt_len->max_port)
|
if (pkt_len->max_port)
|
||||||
temp.pkt_len_max = pkt_len->max_port;
|
temp.pkt_len_max = pkt_len->max_port;
|
||||||
|
} else if (bpf->pkt_len_val) {
|
||||||
|
if (bpf->pkt_len_val->mask)
|
||||||
|
temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
|
||||||
|
temp.pkt_len_min = bpf->pkt_len_val->val;
|
||||||
|
}
|
||||||
if (bpf->tcp_flags) {
|
if (bpf->tcp_flags) {
|
||||||
temp.tcp_flags = bpf->tcp_flags->val;
|
temp.tcp_flags = bpf->tcp_flags->val;
|
||||||
temp.tcp_mask_flags = bpf->tcp_flags->mask;
|
temp.tcp_mask_flags = bpf->tcp_flags->mask;
|
||||||
|
@ -1324,9 +1346,13 @@ static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
|
||||||
orig_list = bpof->tcpflags;
|
orig_list = bpof->tcpflags;
|
||||||
target_val = &bpf->tcp_flags;
|
target_val = &bpf->tcp_flags;
|
||||||
} else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
|
} else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
|
||||||
next_type_entry = 0;
|
next_type_entry = FLOWSPEC_PKT_LEN;
|
||||||
orig_list = bpof->dscp;
|
orig_list = bpof->dscp;
|
||||||
target_val = &bpf->dscp;
|
target_val = &bpf->dscp;
|
||||||
|
} else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
|
||||||
|
next_type_entry = 0;
|
||||||
|
orig_list = bpof->pkt_len;
|
||||||
|
target_val = &bpf->pkt_len_val;
|
||||||
} else {
|
} else {
|
||||||
return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||||
bpf, bpof, 0);
|
bpf, bpof, 0);
|
||||||
|
@ -1356,6 +1382,10 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
|
||||||
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||||
bpf, bpof,
|
bpf, bpof,
|
||||||
FLOWSPEC_DSCP);
|
FLOWSPEC_DSCP);
|
||||||
|
else if (bpof->pkt_len)
|
||||||
|
bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
|
||||||
|
bpf, bpof,
|
||||||
|
FLOWSPEC_PKT_LEN);
|
||||||
else
|
else
|
||||||
bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
|
bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
|
||||||
/* flush bpof */
|
/* flush bpof */
|
||||||
|
@ -1363,6 +1393,8 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
|
||||||
list_delete_all_node(bpof->tcpflags);
|
list_delete_all_node(bpof->tcpflags);
|
||||||
if (bpof->dscp)
|
if (bpof->dscp)
|
||||||
list_delete_all_node(bpof->dscp);
|
list_delete_all_node(bpof->dscp);
|
||||||
|
if (bpof->pkt_len)
|
||||||
|
list_delete_all_node(bpof->pkt_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||||
|
@ -1436,6 +1468,14 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||||
pkt_len->max_port ?
|
pkt_len->max_port ?
|
||||||
pkt_len->max_port :
|
pkt_len->max_port :
|
||||||
pkt_len->min_port);
|
pkt_len->min_port);
|
||||||
|
} else if (bpf->pkt_len_val) {
|
||||||
|
remaining_len += snprintf(buffer + remaining_len,
|
||||||
|
sizeof(buffer)
|
||||||
|
- remaining_len,
|
||||||
|
" %s len %u",
|
||||||
|
bpf->pkt_len_val->mask
|
||||||
|
? "!" : "",
|
||||||
|
bpf->pkt_len_val->val);
|
||||||
}
|
}
|
||||||
if (bpf->tcp_flags) {
|
if (bpf->tcp_flags) {
|
||||||
remaining_len += snprintf(buffer + remaining_len,
|
remaining_len += snprintf(buffer + remaining_len,
|
||||||
|
@ -1516,10 +1556,15 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||||
temp.flags |= MATCH_PORT_SRC_RANGE_SET;
|
temp.flags |= MATCH_PORT_SRC_RANGE_SET;
|
||||||
if (dst_port && dst_port->max_port)
|
if (dst_port && dst_port->max_port)
|
||||||
temp.flags |= MATCH_PORT_DST_RANGE_SET;
|
temp.flags |= MATCH_PORT_DST_RANGE_SET;
|
||||||
if (pkt_len)
|
if (pkt_len) {
|
||||||
temp.pkt_len_min = pkt_len->min_port;
|
temp.pkt_len_min = pkt_len->min_port;
|
||||||
if (pkt_len && pkt_len->max_port)
|
if (pkt_len->max_port)
|
||||||
temp.pkt_len_max = pkt_len->max_port;
|
temp.pkt_len_max = pkt_len->max_port;
|
||||||
|
} else if (bpf->pkt_len_val) {
|
||||||
|
if (bpf->pkt_len_val->mask)
|
||||||
|
temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
|
||||||
|
temp.pkt_len_min = bpf->pkt_len_val->val;
|
||||||
|
}
|
||||||
if (bpf->tcp_flags) {
|
if (bpf->tcp_flags) {
|
||||||
temp.tcp_flags = bpf->tcp_flags->val;
|
temp.tcp_flags = bpf->tcp_flags->val;
|
||||||
temp.tcp_mask_flags = bpf->tcp_flags->mask;
|
temp.tcp_mask_flags = bpf->tcp_flags->mask;
|
||||||
|
@ -1649,9 +1694,13 @@ static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
|
||||||
orig_list = bpof->tcpflags;
|
orig_list = bpof->tcpflags;
|
||||||
target_val = &bpf->tcp_flags;
|
target_val = &bpf->tcp_flags;
|
||||||
} else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
|
} else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
|
||||||
next_type_entry = 0;
|
next_type_entry = FLOWSPEC_PKT_LEN;
|
||||||
orig_list = bpof->dscp;
|
orig_list = bpof->dscp;
|
||||||
target_val = &bpf->dscp;
|
target_val = &bpf->dscp;
|
||||||
|
} else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
|
||||||
|
next_type_entry = 0;
|
||||||
|
orig_list = bpof->pkt_len;
|
||||||
|
target_val = &bpf->pkt_len_val;
|
||||||
} else {
|
} else {
|
||||||
return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||||
bpf, bpof, nh, rate, 0);
|
bpf, bpof, nh, rate, 0);
|
||||||
|
@ -1685,6 +1734,11 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
|
||||||
bpf, bpof,
|
bpf, bpof,
|
||||||
nh, rate,
|
nh, rate,
|
||||||
FLOWSPEC_DSCP);
|
FLOWSPEC_DSCP);
|
||||||
|
else if (bpof->pkt_len)
|
||||||
|
bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
|
||||||
|
bpf, bpof,
|
||||||
|
nh, rate,
|
||||||
|
FLOWSPEC_PKT_LEN);
|
||||||
else
|
else
|
||||||
bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
|
bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
|
||||||
nh, rate);
|
nh, rate);
|
||||||
|
@ -1693,6 +1747,8 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
|
||||||
list_delete_all_node(bpof->tcpflags);
|
list_delete_all_node(bpof->tcpflags);
|
||||||
if (bpof->dscp)
|
if (bpof->dscp)
|
||||||
list_delete_all_node(bpof->dscp);
|
list_delete_all_node(bpof->dscp);
|
||||||
|
if (bpof->pkt_len)
|
||||||
|
list_delete_all_node(bpof->pkt_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct message icmp_code_unreach_str[] = {
|
static const struct message icmp_code_unreach_str[] = {
|
||||||
|
@ -1938,11 +1994,22 @@ static void bgp_pbr_handle_entry(struct bgp *bgp,
|
||||||
FLOWSPEC_TCP_FLAGS);
|
FLOWSPEC_TCP_FLAGS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (api->match_packet_length_num >= 1) {
|
if (api->match_packet_length_num) {
|
||||||
bgp_pbr_extract(api->packet_length,
|
bool ret;
|
||||||
api->match_packet_length_num,
|
|
||||||
&pkt_len);
|
ret = bgp_pbr_extract(api->packet_length,
|
||||||
bpf.pkt_len = &pkt_len;
|
api->match_packet_length_num,
|
||||||
|
&pkt_len);
|
||||||
|
if (ret)
|
||||||
|
bpf.pkt_len = &pkt_len;
|
||||||
|
else {
|
||||||
|
bpof.pkt_len = list_new();
|
||||||
|
bgp_pbr_extract_enumerate(api->packet_length,
|
||||||
|
api->match_packet_length_num,
|
||||||
|
OPERATOR_UNARY_OR,
|
||||||
|
bpof.pkt_len,
|
||||||
|
FLOWSPEC_PKT_LEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (api->match_dscp_num >= 1) {
|
if (api->match_dscp_num >= 1) {
|
||||||
bpof.dscp = list_new();
|
bpof.dscp = list_new();
|
||||||
|
|
|
@ -114,6 +114,7 @@ struct pbr_rule {
|
||||||
#define MATCH_PORT_DST_RANGE_SET (1 << 5)
|
#define MATCH_PORT_DST_RANGE_SET (1 << 5)
|
||||||
#define MATCH_DSCP_SET (1 << 6)
|
#define MATCH_DSCP_SET (1 << 6)
|
||||||
#define MATCH_DSCP_INVERSE_SET (1 << 7)
|
#define MATCH_DSCP_INVERSE_SET (1 << 7)
|
||||||
|
#define MATCH_PKT_LEN_INVERSE_SET (1 << 8)
|
||||||
|
|
||||||
extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
|
extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
|
||||||
struct pbr_rule *zrule);
|
struct pbr_rule *zrule);
|
||||||
|
|
Loading…
Reference in a new issue