Nest: Cleanups in as_path_filter()

Use struct f_val as a common argument for as_path_filter(), as suggested
by Alexander Zubkov. That allows to use NULL sets as valid arguments.
This commit is contained in:
Ondrej Zajicek (work) 2022-03-04 02:01:34 +01:00 committed by Ondrej Zajicek
parent 9b302c133f
commit 8f3c6151b4
5 changed files with 21 additions and 23 deletions

View file

@ -282,6 +282,8 @@ static inline int eclist_set_type(const struct f_tree *set)
{ return set->from.type == T_EC; } { return set->from.type == T_EC; }
static inline int lclist_set_type(const struct f_tree *set) static inline int lclist_set_type(const struct f_tree *set)
{ return set->from.type == T_LC; } { return set->from.type == T_LC; }
static inline int path_set_type(const struct f_tree *set)
{ return set->from.type == T_INT; }
const struct adata *clist_filter(struct linpool *pool, const struct adata *list, const struct f_val *set, int pos); const struct adata *clist_filter(struct linpool *pool, const struct adata *list, const struct f_val *set, int pos);
const struct adata *eclist_filter(struct linpool *pool, const struct adata *list, const struct f_val *set, int pos); const struct adata *eclist_filter(struct linpool *pool, const struct adata *list, const struct f_val *set, int pos);

View file

@ -1035,7 +1035,7 @@
RESULT(T_INT, i, v1.val.lc.ldp2); RESULT(T_INT, i, v1.val.lc.ldp2);
} }
INST(FI_MIN, 1, 1) { /* Get minimum element from set */ INST(FI_MIN, 1, 1) { /* Get minimum element from list */
ARG_ANY(1); ARG_ANY(1);
RESULT_TYPE(f_type_element_type(v1.type)); RESULT_TYPE(f_type_element_type(v1.type));
switch(v1.type) switch(v1.type)
@ -1069,7 +1069,7 @@
} }
} }
INST(FI_MAX, 1, 1) { /* Get maximum element from set */ INST(FI_MAX, 1, 1) { /* Get maximum element from list */
ARG_ANY(1); ARG_ANY(1);
RESULT_TYPE(f_type_element_type(v1.type)); RESULT_TYPE(f_type_element_type(v1.type));
switch(v1.type) switch(v1.type)
@ -1291,17 +1291,10 @@
if (v1.type == T_PATH) if (v1.type == T_PATH)
{ {
const struct f_tree *set = NULL; if ((v2.type == T_SET) && path_set_type(v2.val.t) || (v2.type == T_INT))
u32 key = 0; RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
if (v2.type == T_INT)
key = v2.val.i;
else if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT))
set = v2.val.t;
else else
runtime("Can't delete non-integer (set)"); runtime("Can't delete non-integer (set)");
RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, 0) ]]);
} }
else if (v1.type == T_CLIST) else if (v1.type == T_CLIST)
@ -1353,10 +1346,8 @@
if (v1.type == T_PATH) if (v1.type == T_PATH)
{ {
u32 key = 0; if ((v2.type == T_SET) && path_set_type(v2.val.t))
RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]);
if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT))
RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, v2.val.t, key, 1) ]]);
else else
runtime("Can't filter integer"); runtime("Can't filter integer");
} }

View file

@ -602,8 +602,10 @@ as_path_match_set(const struct adata *path, const struct f_tree *set)
} }
const struct adata * const struct adata *
as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos) as_path_filter(struct linpool *pool, const struct adata *path, const struct f_val *set, int pos)
{ {
ASSERT((set->type == T_SET) || (set->type == T_INT));
if (!path) if (!path)
return NULL; return NULL;
@ -629,13 +631,13 @@ as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tr
u32 as = get_as(p); u32 as = get_as(p);
int match; int match;
if (set) if (set->type == T_SET)
{ {
struct f_val v = {T_INT, .val.i = as}; struct f_val v = {T_INT, .val.i = as};
match = !!find_tree(set, &v); match = !!find_tree(set->val.t, &v);
} }
else else /* T_INT */
match = (as == key); match = (as == set->val.i);
if (match == pos) if (match == pos)
{ {

View file

@ -12,6 +12,7 @@
#include "nest/route.h" #include "nest/route.h"
#include "nest/attrs.h" #include "nest/attrs.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "filter/data.h"
#define TESTS_NUM 30 #define TESTS_NUM 30
#define AS_PATH_LENGTH 1000 #define AS_PATH_LENGTH 1000
@ -136,8 +137,9 @@ t_path_include(void)
int counts_of_contains = count_asn_in_array(as_nums, as_nums[i]); int counts_of_contains = count_asn_in_array(as_nums, as_nums[i]);
bt_assert_msg(as_path_contains(as_path, as_nums[i], counts_of_contains), "AS Path should contains %d-times number %d", counts_of_contains, as_nums[i]); bt_assert_msg(as_path_contains(as_path, as_nums[i], counts_of_contains), "AS Path should contains %d-times number %d", counts_of_contains, as_nums[i]);
bt_assert(as_path_filter(lp, as_path, NULL, as_nums[i], 0) != NULL); struct f_val v = { .type = T_INT, .val.i = as_nums[i] };
bt_assert(as_path_filter(lp, as_path, NULL, as_nums[i], 1) != NULL); bt_assert(as_path_filter(lp, as_path, &v, 0) != NULL);
bt_assert(as_path_filter(lp, as_path, &v, 1) != NULL);
} }
for (i = 0; i < 10000; i++) for (i = 0; i < 10000; i++)

View file

@ -28,6 +28,7 @@
* to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details * to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details
*/ */
struct f_val;
struct f_tree; struct f_tree;
int as_path_valid(byte *data, uint len, int bs, int sets, int confed, char *err, uint elen); int as_path_valid(byte *data, uint len, int bs, int sets, int confed, char *err, uint elen);
@ -49,7 +50,7 @@ int as_path_get_last(const struct adata *path, u32 *last_as);
u32 as_path_get_last_nonaggregated(const struct adata *path); u32 as_path_get_last_nonaggregated(const struct adata *path);
int as_path_contains(const struct adata *path, u32 as, int min); int as_path_contains(const struct adata *path, u32 as, int min);
int as_path_match_set(const struct adata *path, const struct f_tree *set); int as_path_match_set(const struct adata *path, const struct f_tree *set);
const struct adata *as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos); const struct adata *as_path_filter(struct linpool *pool, const struct adata *path, const struct f_val *set, int pos);
static inline struct adata *as_path_prepend(struct linpool *pool, const struct adata *path, u32 as) static inline struct adata *as_path_prepend(struct linpool *pool, const struct adata *path, u32 as)
{ return as_path_prepend2(pool, path, AS_PATH_SEQUENCE, as); } { return as_path_prepend2(pool, path, AS_PATH_SEQUENCE, as); }