summaryrefslogtreecommitdiff
path: root/nest/a-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/a-path.c')
-rw-r--r--nest/a-path.c90
1 files changed, 89 insertions, 1 deletions
diff --git a/nest/a-path.c b/nest/a-path.c
index 63ac402e..dc36e653 100644
--- a/nest/a-path.c
+++ b/nest/a-path.c
@@ -244,10 +244,11 @@ as_path_get_first(struct adata *path, u32 *last_as)
}
int
-as_path_is_member(struct adata *path, u32 as)
+as_path_contains(struct adata *path, u32 as, int min)
{
u8 *p = path->data;
u8 *q = p+path->length;
+ int num = 0;
int i, n;
while (p<q)
@@ -257,13 +258,100 @@ as_path_is_member(struct adata *path, u32 as)
for(i=0; i<n; i++)
{
if (get_as(p) == as)
+ if (++num == min)
+ return 1;
+ p += BS;
+ }
+ }
+ return 0;
+}
+
+int
+as_path_match_set(struct adata *path, struct f_tree *set)
+{
+ u8 *p = path->data;
+ u8 *q = p+path->length;
+ int i, n;
+
+ while (p<q)
+ {
+ n = p[1];
+ p += 2;
+ for (i=0; i<n; i++)
+ {
+ struct f_val v = {T_INT, .val.i = get_as(p)};
+ if (find_tree(set, v))
return 1;
p += BS;
}
}
+
return 0;
}
+struct adata *
+as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos)
+{
+ if (!path)
+ return NULL;
+
+ int len = path->length;
+ u8 *p = path->data;
+ u8 *q = path->data + len;
+ u8 *d, *d2;
+ int i, bt, sn, dn;
+ u8 buf[len];
+
+ d = buf;
+ while (p<q)
+ {
+ /* Read block header (type and length) */
+ bt = p[0];
+ sn = p[1];
+ dn = 0;
+ p += 2;
+ d2 = d + 2;
+
+ for (i = 0; i < sn; i++)
+ {
+ u32 as = get_as(p);
+ int match;
+
+ if (set)
+ match = !!find_tree(set, (struct f_val){T_INT, .val.i = as});
+ else
+ match = (as == key);
+
+ if (match == pos)
+ {
+ put_as(d2, as);
+ d2 += BS;
+ dn++;
+ }
+
+ p += BS;
+ }
+
+ if (dn > 0)
+ {
+ /* Nonempty block, set block header and advance */
+ d[0] = bt;
+ d[1] = dn;
+ d = d2;
+ }
+ }
+
+ int nl = d - buf;
+ if (nl == path->length)
+ return path;
+
+ struct adata *res = lp_alloc(pool, sizeof(struct adata) + nl);
+ res->length = nl;
+ memcpy(res->data, buf, nl);
+
+ return res;
+}
+
struct pm_pos
{