forked from Mirror/frr
bgpd: extend enumerate API to handle or operations
The flowspec enumerate list can either be and values or or values. In the latter case, a list is created that will be used later. Also, the API supports the check for both and or or operations. This API does not permit to handle both and and or operations at the same time. The list will have to be either and or or. An other API retrieves the operator unary value that is used: and or or. or 0 is the two operators are used at the same time. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
1a1f4a4c69
commit
f7b2e630e4
|
@ -37,6 +37,7 @@ DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH_ENTRY, "PBR match entry")
|
|||
DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH, "PBR match")
|
||||
DEFINE_MTYPE_STATIC(BGPD, PBR_ACTION, "PBR action")
|
||||
DEFINE_MTYPE_STATIC(BGPD, PBR, "BGP PBR Context")
|
||||
DEFINE_MTYPE_STATIC(BGPD, PBR_VALMASK, "BGP PBR Val Mask Value")
|
||||
|
||||
RB_GENERATE(bgp_pbr_interface_head, bgp_pbr_interface,
|
||||
id_entry, bgp_pbr_interface_compare);
|
||||
|
@ -210,14 +211,22 @@ struct bgp_pbr_filter {
|
|||
/* TCP : FIN and SYN -> val = ALL; mask = 3
|
||||
* TCP : not (FIN and SYN) -> val = ALL; mask = ALL & ~(FIN|RST)
|
||||
*/
|
||||
static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
|
||||
int num, uint8_t unary_operator,
|
||||
struct bgp_pbr_val_mask *valmask)
|
||||
static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
|
||||
int num, uint8_t unary_operator,
|
||||
void *valmask)
|
||||
{
|
||||
int i = 0;
|
||||
struct bgp_pbr_val_mask *and_valmask = NULL;
|
||||
struct list *or_valmask = NULL;
|
||||
|
||||
if (valmask)
|
||||
memset(valmask, 0, sizeof(struct bgp_pbr_val_mask));
|
||||
if (valmask) {
|
||||
if (unary_operator == OPERATOR_UNARY_AND) {
|
||||
and_valmask = (struct bgp_pbr_val_mask *)valmask;
|
||||
memset(and_valmask, 0, sizeof(struct bgp_pbr_val_mask));
|
||||
} else if (unary_operator == OPERATOR_UNARY_OR) {
|
||||
or_valmask = (struct list *)valmask;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i != 0 && list[i].unary_operator !=
|
||||
unary_operator)
|
||||
|
@ -230,21 +239,91 @@ static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
|
|||
OPERATOR_COMPARE_LESS_THAN) &&
|
||||
(list[i].compare_operator &
|
||||
OPERATOR_COMPARE_GREATER_THAN)) {
|
||||
if (valmask)
|
||||
valmask->mask |=
|
||||
if (unary_operator == OPERATOR_UNARY_AND && and_valmask)
|
||||
and_valmask->mask |=
|
||||
TCP_HEADER_ALL_FLAGS &
|
||||
~(list[i].value);
|
||||
else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
|
||||
and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
|
||||
sizeof(struct bgp_pbr_val_mask));
|
||||
and_valmask->val = TCP_HEADER_ALL_FLAGS;
|
||||
and_valmask->mask |=
|
||||
TCP_HEADER_ALL_FLAGS &
|
||||
~(list[i].value);
|
||||
listnode_add (or_valmask, and_valmask);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (valmask)
|
||||
valmask->mask |= list[i].value;
|
||||
if (unary_operator == OPERATOR_UNARY_AND && and_valmask)
|
||||
and_valmask->mask |=
|
||||
TCP_HEADER_ALL_FLAGS & list[i].value;
|
||||
else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
|
||||
and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
|
||||
sizeof(struct bgp_pbr_val_mask));
|
||||
and_valmask->val = TCP_HEADER_ALL_FLAGS;
|
||||
and_valmask->mask |=
|
||||
TCP_HEADER_ALL_FLAGS & list[i].value;
|
||||
listnode_add(or_valmask, and_valmask);
|
||||
}
|
||||
}
|
||||
valmask->mask = TCP_HEADER_ALL_FLAGS;
|
||||
if (unary_operator == OPERATOR_UNARY_AND && and_valmask)
|
||||
and_valmask->mask = TCP_HEADER_ALL_FLAGS;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* if unary operator can either be UNARY_OR/AND/OR-AND.
|
||||
* in the latter case, combinationf of both is not handled
|
||||
*/
|
||||
static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
|
||||
int num, uint8_t unary_operator,
|
||||
void *valmask)
|
||||
{
|
||||
bool ret;
|
||||
uint8_t unary_operator_val;
|
||||
bool double_check = false;
|
||||
|
||||
if ((unary_operator & OPERATOR_UNARY_OR) &&
|
||||
(unary_operator & OPERATOR_UNARY_AND)) {
|
||||
unary_operator_val = OPERATOR_UNARY_AND;
|
||||
double_check = true;
|
||||
} else
|
||||
unary_operator_val = unary_operator;
|
||||
ret = bgp_pbr_extract_enumerate_unary(list, num, unary_operator_val,
|
||||
valmask);
|
||||
if (!ret && double_check)
|
||||
ret = bgp_pbr_extract_enumerate_unary(list, num,
|
||||
OPERATOR_UNARY_OR,
|
||||
valmask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns the unary operator that is in the list
|
||||
* return 0 if both operators are used
|
||||
*/
|
||||
static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[],
|
||||
int num)
|
||||
|
||||
{
|
||||
int i;
|
||||
uint8_t unary_operator = OPERATOR_UNARY_AND;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
if (list[i].unary_operator & OPERATOR_UNARY_OR)
|
||||
unary_operator = OPERATOR_UNARY_OR;
|
||||
if ((list[i].unary_operator & OPERATOR_UNARY_AND
|
||||
&& unary_operator == OPERATOR_UNARY_OR) ||
|
||||
(list[i].unary_operator & OPERATOR_UNARY_OR
|
||||
&& unary_operator == OPERATOR_UNARY_AND))
|
||||
return 0;
|
||||
}
|
||||
return unary_operator;
|
||||
}
|
||||
|
||||
|
||||
/* return true if extraction ok
|
||||
*/
|
||||
static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
|
||||
|
|
Loading…
Reference in a new issue