* Intdodoce list_compare() to compare clist and eclist as arrays of u32. eclist stored as u64 with MSB first, so we could compare it also as u32.
* Introduce path_compare() to compare bgppath type. Compares path length, and element by element, considering AS_PATH_SET more longer. --- filter/filter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ nest/a-path.c | 7 ----- nest/attrs.h | 4 +++ 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/filter/filter.c b/filter/filter.c index f92ee9a..6f59193 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -130,6 +130,77 @@ u64_cmp(u64 i1, u64 i2) return (i1 > i2) - (i1 < i2); } +static int +list_compare(struct adata *a1, struct adata *a2) +{ + u32 *l1, *l2; + int l, rc; + + rc = (a1 > a2) - (a1 < a2); + if (!rc) + return rc; + if ((!!a1) != (!!a2)) + return rc; + + rc = uint_cmp(a1->length, a2->length); + if (rc) + return rc; + + l1 = int_set_get_data(a1); + l2 = int_set_get_data(a2); + l = int_set_get_size(a1); + + while (l--) { + rc = uint_cmp(*l1++, *l2++); + if (rc) + return rc; + } + + return rc; +} + +static int +path_compare(struct adata *a1, struct adata *a2) +{ + u8 *p1, *q1; + u8 *p2, *q2; + int l, rc; + + rc = (a1 > a2) - (a1 < a2); + if (!rc) + return rc; + if ((!!a1) != (!!a2)) + return rc; + + rc = int_cmp(as_path_getlen(a1), as_path_getlen(a2)); + if (rc) + return rc; + + p1 = a1->data; + q1 = p1 + a1->length; + p2 = a2->data; + q2 = p2 + a2->length; + + while ((p1 < q1) && (p2 < q2)) { + rc = uint_cmp(*p1++, *p2++); + if (rc) + return -rc; /* AS_PATH_SET longer */ + + l = *p1++; + rc = int_cmp(l, *p2++); + if (rc) + return rc; + + while (l--) { + rc = uint_cmp(get_as(p1++), get_as(p2++)); + if (rc) + return rc; + } + } + + return int_cmp((p1 < q1), (p2 < q2)); +} + /** * val_compare - compare two values * @v1: first value @@ -180,6 +251,11 @@ val_compare(struct f_val v1, struct f_val v2) return pm_path_compare(v1.val.path_mask, v2.val.path_mask); case T_STRING: return strcmp(v1.val.s, v2.val.s); + case T_CLIST: + case T_ECLIST: + return list_compare(v1.val.ad, v2.val.ad); + case T_PATH: + return path_compare(v1.val.ad, v2.val.ad); case T_VOID: return 0; default: diff --git a/nest/a-path.c b/nest/a-path.c index b181298..1679886 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -15,13 +15,6 @@ #include "lib/string.h" #include "filter/filter.h" -// static inline void put_as(byte *data, u32 as) { put_u32(data, as); } -// static inline u32 get_as(byte *data) { return get_u32(data); } - -#define put_as put_u32 -#define get_as get_u32 -#define BS 4 - struct adata * as_path_prepend(struct linpool *pool, struct adata *olda, u32 as) { diff --git a/nest/attrs.h b/nest/attrs.h index 44a23e1..38639ae 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -25,6 +25,10 @@ * to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details */ +#define put_as put_u32 +#define get_as get_u32 +#define BS 4 + struct f_tree; struct adata *as_path_prepend(struct linpool *pool, struct adata *olda, u32 as); -- 1.7.10.4