summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-06-18 11:18:21 +0200
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-06-28 08:52:15 +0200
commitf7b2e630e4dcad491d20337df357d16b42967c3c (patch)
tree4a91767290b933e7f25d899e662dc4bb5ea9f590
parent1a1f4a4c69f5ea36a72a6c824fe7c0f797d41649 (diff)
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>
-rw-r--r--bgpd/bgp_pbr.c101
1 files changed, 90 insertions, 11 deletions
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 779bf2de6d..2065d03356 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -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;
-
- if (valmask)
- memset(valmask, 0, sizeof(struct bgp_pbr_val_mask));
+ struct bgp_pbr_val_mask *and_valmask = NULL;
+ struct list *or_valmask = NULL;
+
+ 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[],