0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

WIP Nest: Making the clist/eclist/lclist even more generic

This commit is contained in:
Jan Maria Matejka 2018-06-07 15:02:05 +02:00
parent 7365219609
commit 9ca8847305
4 changed files with 87 additions and 135 deletions

View File

@ -301,14 +301,10 @@ eclist_match_set(struct adata *list, struct f_tree *set)
if (!eclist_set_type(set))
return CMP_ERROR;
struct f_val v;
u32 *l = int_set_get_data(list);
int len = int_set_get_size(list);
int i;
struct f_val v = { .type = T_EC };
v.type = T_EC;
for (i = 0; i < len; i += 2) {
v.val.ec = ec_get(l, i);
for (void *p = list->data, *end = p + list->length; p < end; p += sizeof(u64)) {
memcpy(&v.val.ec, p, sizeof(u64));
if (find_tree(set, v))
return 1;
}
@ -325,14 +321,10 @@ lclist_match_set(struct adata *list, struct f_tree *set)
if (!lclist_set_type(set))
return CMP_ERROR;
struct f_val v;
u32 *l = int_set_get_data(list);
int len = int_set_get_size(list);
int i;
struct f_val v = { .type = T_LC };
v.type = T_LC;
for (i = 0; i < len; i += 3) {
v.val.lc = lc_get(l, i);
for (void *p = list->data, *end = p + list->length; p < end; p += sizeof(lcomm)) {
memcpy(&v.val.ec, p, sizeof(lcomm));
if (find_tree(set, v))
return 1;
}
@ -353,8 +345,8 @@ clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos
else
v.type = T_PAIR;
int len = int_set_get_size(list);
u32 *l = int_set_get_data(list);
int len = list->length / 4;
u32 *l = (u32 *) list->data;
u32 tmp[len];
u32 *k = tmp;
u32 *end = l + len;
@ -384,15 +376,15 @@ eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int po
int tree = (set.type == T_SET); /* 1 -> set is T_SET, 0 -> set is T_CLIST */
struct f_val v;
int len = int_set_get_size(list);
u32 *l = int_set_get_data(list);
int len = list->length / 4;
u32 *l = (u32 *) list->data;
u32 tmp[len];
u32 *k = tmp;
int i;
v.type = T_EC;
for (i = 0; i < len; i += 2) {
v.val.ec = ec_get(l, i);
memcpy(&(v.val.ec), &(l[i]), sizeof(u64));
/* pos && member(val, set) || !pos && !member(val, set), member() depends on tree */
if ((tree ? !!find_tree(set.val.t, v) : ec_set_contains(set.val.ad, v.val.ec)) == pos) {
*k++ = l[i];
@ -418,18 +410,21 @@ lclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int po
int tree = (set.type == T_SET); /* 1 -> set is T_SET, 0 -> set is T_CLIST */
struct f_val v;
int len = int_set_get_size(list);
u32 *l = int_set_get_data(list);
int len = list->length / 4;
u32 *l = (u32 *) list->data;
u32 tmp[len];
u32 *k = tmp;
int i;
v.type = T_LC;
for (i = 0; i < len; i += 3) {
v.val.lc = lc_get(l, i);
memcpy(&(v.val.lc), &(l[i]), sizeof(lcomm));
/* pos && member(val, set) || !pos && !member(val, set), member() depends on tree */
if ((tree ? !!find_tree(set.val.t, v) : lc_set_contains(set.val.ad, v.val.lc)) == pos)
k = lc_copy(k, l+i);
if ((tree ? !!find_tree(set.val.t, v) : lc_set_contains(set.val.ad, v.val.lc)) != pos)
continue;
memcpy(k, &(l[i]), sizeof(lcomm));
k += sizeof(lcomm)/sizeof(u32);
}
uint nl = (k - tmp) * sizeof(u32);
@ -871,9 +866,9 @@ interpret(struct f_inst *what)
switch(v1.type) {
case T_NET: res.val.i = net_pxlen(v1.val.net); break;
case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break;
case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break;
case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
case T_LCLIST: res.val.i = lc_set_get_size(v1.val.ad); break;
case T_CLIST: res.val.i = v1.val.ad->length / 4; break;
case T_ECLIST: res.val.i = v1.val.ad->length / 8; break;
case T_LCLIST: res.val.i = v1.val.ad->length / 12; break;
default: runtime( "Prefix, path, clist, eclist or lclist expected" );
}
break;

View File

@ -117,10 +117,10 @@ ec_format(byte *buf, u64 ec)
int
ec_set_format(struct adata *set, int from, byte *buf, uint size)
{
u32 *z = int_set_get_data(set);
u32 *z = (u32 *) set->data;
byte *end = buf + size - 64;
int from2 = MAX(from, 0);
int to = int_set_get_size(set);
int to = set->length / 4;
int i;
for (i = from2; i < to; i += 2)
@ -137,7 +137,9 @@ ec_set_format(struct adata *set, int from, byte *buf, uint size)
if (i > from2)
*buf++ = ' ';
buf += ec_format(buf, ec_get(z, i));
u64 ec;
memcpy(&ec, &(z[i]), sizeof(u64));
buf += ec_format(buf, ec);
}
*buf = 0;
return 0;
@ -181,16 +183,16 @@ lc_set_format(struct adata *set, int from, byte *buf, uint bufsize)
}
int
set_position(struct adata *list, u32 *val, int skip)
set_position(struct adata *list, void *val, int size)
{
if (!list)
return -1;
u32 *l = int_set_get_data(list);
int len = list->length / (skip * 4);
int len = list->length / size;
void *l = list->data;
for (int i = 0; i < len; i++)
if (!memcmp(&(l[i*skip]), val, skip * 4))
if (!memcmp(l + i * size, val, size))
return i;
return -1;
@ -218,7 +220,7 @@ int_set_prepend(struct linpool *pool, struct adata *list, u32 val)
}
struct adata *
set_add(struct linpool *pool, struct adata *list, u32 *val, int size)
set_add(struct linpool *pool, struct adata *list, void *val, int size)
{
struct adata *res;
int len;
@ -227,30 +229,30 @@ set_add(struct linpool *pool, struct adata *list, u32 *val, int size)
return list;
len = list ? list->length : 0;
res = lp_alloc(pool, sizeof(struct adata) + len + size * 4);
res->length = len + size * 4;
res = lp_alloc(pool, sizeof(struct adata) + len + size);
res->length = len + size;
if (list)
memcpy(res->data, list->data, len);
memcpy(res->data + len, val, size * 4);
memcpy(res->data + len, val, size);
return res;
}
struct adata *
set_del(struct linpool *pool, struct adata *list, u32 *val, int size)
set_del(struct linpool *pool, struct adata *list, void *val, int size)
{
int pos = set_position(list, val, size);
if (pos == -1)
return list;
int len = list->length - 4*size;
int len = list->length - size;
struct adata *res = lp_alloc(pool, sizeof(struct adata) + len);
res->length = len;
u32 *dest = int_set_get_data(res);
u32 *src = int_set_get_data(list);
void *dest = res->data;
void *src = list->data;
memcpy(dest, src, size * pos);
memcpy(dest + size * pos, src + size * (pos + 1), size * (len - pos));
@ -267,15 +269,15 @@ set_union(struct linpool *pool, struct adata *l1, struct adata *l2, int size)
/* Filter out duplicit data from l2 */
struct adata *res;
int len = l2->length / (size * 4);
u32 *l = int_set_get_data(l2);
u32 tmp[len*size];
u32 *k = tmp;
int len = l2->length / size;
void *l = l2->data;
u32 tmp[len*size/sizeof(u32)];
void *k = tmp;
for (int i = 0; i < len; i++)
if (!set_contains(l1, l + i*size, size))
{
memcpy(k, l + i*size, size * 4);
memcpy(k, l + i*size, size);
k += size;
}
@ -283,7 +285,7 @@ set_union(struct linpool *pool, struct adata *l1, struct adata *l2, int size)
if (k == tmp)
return l1;
len = (k - tmp) * 4;
len = (k - (void*)tmp);
res = lp_alloc(pool, sizeof(struct adata) + l1->length + len);
res->length = l1->length + len;
memcpy(res->data, l1->data, l1->length);
@ -296,9 +298,9 @@ struct adata *
ec_set_del_nontrans(struct linpool *pool, struct adata *set)
{
adata *res = lp_alloc_adata(pool, set->length);
u32 *src = int_set_get_data(set);
u32 *dst = int_set_get_data(res);
int len = int_set_get_size(set);
u32 *src = (u32 *) set->data;
u32 *dst = (u32 *) res->data;
int len = set->length / 4;
int i;
/* Remove non-transitive communities (EC_TBIT set) */
@ -336,8 +338,8 @@ int_set_sort(struct linpool *pool, struct adata *src)
static int
ec_set_cmp(const void *X, const void *Y)
{
u64 x = ec_get(X, 0);
u64 y = ec_get(Y, 0);
u64 x = *((u64 *) X);
u64 y = *((u64 *) Y);
return (x < y) ? -1 : (x > y) ? 1 : 0;
}
@ -376,6 +378,6 @@ lc_set_sort(struct linpool *pool, struct adata *src)
{
struct adata *dst = lp_alloc_adata(pool, src->length);
memcpy(dst->data, src->data, src->length);
qsort(dst->data, dst->length / LCOMM_LENGTH, LCOMM_LENGTH, lc_set_cmp);
qsort(dst->data, dst->length / sizeof(lcomm), sizeof(lcomm), lc_set_cmp);
return dst;
}

View File

@ -69,21 +69,21 @@ generate_set_sequence(enum set_type type)
static int
t_set_int_contains(void)
{
int i;
u32 i;
resource_init();
generate_set_sequence(SET_TYPE_INT);
bt_assert(int_set_get_size(set_sequence) == SET_SIZE);
bt_assert(set_sequence->length / 4 == SET_SIZE);
for (i = 0; i < SET_SIZE; i++)
bt_assert(int_set_contains(set_sequence, i));
bt_assert(int_set_contains(set_sequence, -1) == 0);
bt_assert(int_set_contains(set_sequence, SET_SIZE) == 0);
int *data = int_set_get_data(set_sequence);
u32 *data = (u32 *) set_sequence->data;
for (i = 0; i < SET_SIZE; i++)
bt_assert_msg(data[i] == i, "(data[i] = %d) == i = %d)", data[i], i);
bt_assert_msg(data[i] == i, "(data[i] = %u) == i = %u)", data[i], i);
rfree(lp);
return 1;
@ -97,11 +97,11 @@ t_set_int_union(void)
struct adata *set_union;
set_union = int_set_union(lp, set_sequence, set_sequence_same);
bt_assert(int_set_get_size(set_union) == SET_SIZE);
bt_assert(set_union->length / 4 == SET_SIZE);
bt_assert(int_set_format(set_union, 0, 2, buf, BUFFER_SIZE) == 0);
set_union = int_set_union(lp, set_sequence, set_sequence_higher);
bt_assert_msg(int_set_get_size(set_union) == SET_SIZE*2, "int_set_get_size(set_union) %d, SET_SIZE*2 %d", int_set_get_size(set_union), SET_SIZE*2);
bt_assert_msg(set_union->length / 4 == SET_SIZE*2, "set_union->length/4 %d, SET_SIZE*2 %d", set_union->length / 4, SET_SIZE*2);
bt_assert(int_set_format(set_union, 0, 2, buf, BUFFER_SIZE) == 0);
rfree(lp);
@ -141,13 +141,13 @@ t_set_int_delete(void)
for (i = 0; i < SET_SIZE; i++)
{
deleting_sequence = int_set_del(lp, deleting_sequence, i);
bt_assert_msg(int_set_get_size(deleting_sequence) == (int) (SET_SIZE-1-i),
"int_set_get_size(deleting_sequence) %d == SET_SIZE-1-i %d",
int_set_get_size(deleting_sequence),
bt_assert_msg(deleting_sequence->length / 4 == (uint) (SET_SIZE-1-i),
"deleting_sequence->length/4 %d == SET_SIZE-1-i %d",
deleting_sequence->length / 4,
SET_SIZE-1-i);
}
bt_assert(int_set_get_size(set_sequence) == SET_SIZE);
bt_assert(set_sequence->length/4 == SET_SIZE);
return 1;
}
@ -164,7 +164,7 @@ t_set_ec_contains(void)
resource_init();
generate_set_sequence(SET_TYPE_EC);
bt_assert(ec_set_get_size(set_sequence) == SET_SIZE);
bt_assert(set_sequence->length/8 == SET_SIZE);
for (i = 0; i < SET_SIZE; i++)
bt_assert(ec_set_contains(set_sequence, i));
@ -187,11 +187,11 @@ t_set_ec_union(void)
struct adata *set_union;
set_union = ec_set_union(lp, set_sequence, set_sequence_same);
bt_assert(ec_set_get_size(set_union) == SET_SIZE);
bt_assert(set_union->length/8 == SET_SIZE);
bt_assert(ec_set_format(set_union, 0, buf, BUFFER_SIZE) == 0);
set_union = ec_set_union(lp, set_sequence, set_sequence_higher);
bt_assert_msg(ec_set_get_size(set_union) == SET_SIZE*2, "ec_set_get_size(set_union) %d, SET_SIZE*2 %d", ec_set_get_size(set_union), SET_SIZE*2);
bt_assert_msg(set_union->length/8 == SET_SIZE*2, "set_union->length/8 %d, SET_SIZE*2 %d", set_union->length/8, SET_SIZE*2);
bt_assert(ec_set_format(set_union, 0, buf, BUFFER_SIZE) == 0);
rfree(lp);
@ -231,12 +231,12 @@ t_set_ec_delete(void)
for (i = 0; i < SET_SIZE; i++)
{
deleting_sequence = ec_set_del(lp, deleting_sequence, i);
bt_assert_msg(ec_set_get_size(deleting_sequence) == (int) (SET_SIZE-1-i),
bt_assert_msg(deleting_sequence->length/8 == (uint) (SET_SIZE-1-i),
"ec_set_get_size(deleting_sequence) %d == SET_SIZE-1-i %d",
ec_set_get_size(deleting_sequence), SET_SIZE-1-i);
deleting_sequence->length/8, SET_SIZE-1-i);
}
bt_assert(ec_set_get_size(set_sequence) == SET_SIZE);
bt_assert(set_sequence->length/8 == SET_SIZE);
return 1;
}

View File

@ -119,23 +119,6 @@ aggregator_to_old(struct linpool *pool, struct adata *a)
#define ECOMM_LENGTH 8
static inline int int_set_get_size(struct adata *list)
{ return list->length / 4; }
static inline int ec_set_get_size(struct adata *list)
{ return list->length / 8; }
static inline int lc_set_get_size(struct adata *list)
{ return list->length / 12; }
static inline u32 *int_set_get_data(struct adata *list)
{ return (u32 *) list->data; }
static inline u32 ec_hi(u64 ec) { return ec >> 32; }
static inline u32 ec_lo(u64 ec) { return ec; }
static inline u64 ec_get(const u32 *l, int i)
{ return (((u64) l[i]) << 32) | l[i+1]; }
/* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
static inline u64 ec_as2(u64 kind, u64 key, u64 val)
{ return ((kind | 0x0000) << 48) | (key << 32) | val; }
@ -158,19 +141,8 @@ typedef struct lcomm {
u32 ldp2;
} lcomm;
#define LCOMM_LENGTH 12
static inline lcomm lc_get(const u32 *l, int i)
{ return (lcomm) { l[i], l[i+1], l[i+2] }; }
static inline void lc_put(u32 *l, lcomm v)
{ l[0] = v.asn; l[1] = v.ldp1; l[2] = v.ldp2; }
static inline int lc_match(const u32 *l, int i, lcomm v)
{ return (l[i] == v.asn && l[i+1] == v.ldp1 && l[i+2] == v.ldp2); }
static inline u32 *lc_copy(u32 *dst, const u32 *src)
{ memcpy(dst, src, LCOMM_LENGTH); return dst + 3; }
static inline int int_set_get_size(struct adata *set)
{ return set->length / 4; }
int int_set_format(struct adata *set, int way, int from, byte *buf, uint size);
int ec_format(byte *buf, u64 ec);
@ -178,59 +150,42 @@ int ec_set_format(struct adata *set, int from, byte *buf, uint size);
int lc_format(byte *buf, lcomm lc);
int lc_set_format(struct adata *set, int from, byte *buf, uint size);
int set_position(struct adata *list, u32 *val, int skip);
static inline int set_contains(struct adata *list, u32 *val, int skip)
{ return set_position(list, val, skip) != -1; }
int set_position(struct adata *list, void *val, int size);
static inline int set_contains(struct adata *list, void *val, int size)
{ return set_position(list, val, size) != -1; }
static inline int int_set_contains(struct adata *list, u32 val)
{ return set_contains(list, &val, 1); }
{ return set_contains(list, &val, sizeof(val)); }
static inline int ec_set_contains(struct adata *list, u64 val)
{
u32 ec[2] = { ec_hi(val), ec_lo(val) };
return set_contains(list, ec, 2);
}
{ return set_contains(list, &val, sizeof(val)); }
static inline int lc_set_contains(struct adata *list, lcomm val)
{
u32 lc[3] = { val.asn, val.ldp1, val.ldp2 };
return set_contains(list, lc, 3);
}
{ return set_contains(list, &val, sizeof(val)); }
struct adata *int_set_prepend(struct linpool *pool, struct adata *list, u32 val);
struct adata *set_add(struct linpool *pool, struct adata *list, u32 *val, int size);
struct adata *set_add(struct linpool *pool, struct adata *list, void *val, int size);
static inline struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val)
{ return set_add(pool, list, &val, 1); };
{ return set_add(pool, list, &val, sizeof(val)); };
static inline struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val)
{
u32 ec[2] = { ec_hi(val), ec_lo(val) };
return set_add(pool, list, ec, 2);
}
{ return set_add(pool, list, &val, sizeof(val)); };
static inline struct adata *lc_set_add(struct linpool *pool, struct adata *list, lcomm val)
{
u32 lc[3] = { val.asn, val.ldp1, val.ldp2 };
return set_add(pool, list, lc, 3);
}
{ return set_add(pool, list, &val, sizeof(val)); };
struct adata *set_del(struct linpool *pool, struct adata *list, u32 *val, int size);
struct adata *set_del(struct linpool *pool, struct adata *list, void *val, int size);
static inline struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val)
{ return set_del(pool, list, &val, 1); }
{ return set_del(pool, list, &val, sizeof(val)); }
static inline struct adata *ec_set_del(struct linpool *pool, struct adata *list, u64 val)
{
u32 ec[2] = { ec_hi(val), ec_lo(val) };
return set_del(pool, list, ec, 2);
}
{ return set_del(pool, list, &val, sizeof(val)); }
static inline struct adata *lc_set_del(struct linpool *pool, struct adata *list, lcomm val)
{
u32 lc[3] = { val.asn, val.ldp1, val.ldp2 };
return set_del(pool, list, lc, 3);
}
{ return set_del(pool, list, &val, sizeof(val)); }
struct adata *set_union(struct linpool *pool, struct adata *l1, struct adata *l2, int size);
static inline struct adata *int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
{ return set_union(pool, l1, l2, 1); }
{ return set_union(pool, l1, l2, sizeof(u32)); }
static inline struct adata *ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
{ return set_union(pool, l1, l2, 2); }
{ return set_union(pool, l1, l2, sizeof(u64)); }
static inline struct adata *lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2)
{ return set_union(pool, l1, l2, 3); }
{ return set_union(pool, l1, l2, sizeof(lcomm)); }
struct adata *ec_set_del_nontrans(struct linpool *pool, struct adata *set);
struct adata *int_set_sort(struct linpool *pool, struct adata *src);