diff options
Diffstat (limited to 'nest')
-rw-r--r-- | nest/route.h | 6 | ||||
-rw-r--r-- | nest/rt-attr.c | 76 |
2 files changed, 82 insertions, 0 deletions
diff --git a/nest/route.h b/nest/route.h index fccc571b..87f10ae3 100644 --- a/nest/route.h +++ b/nest/route.h @@ -461,8 +461,14 @@ static inline void rt_lock_source(struct rte_src *src) { src->uc++; } static inline void rt_unlock_source(struct rte_src *src) { src->uc--; } void rt_prune_sources(void); +struct ea_walk_state { + ea_list *eattrs; /* Ccurrent ea_list, initially set by caller */ + eattr *ea; /* Current eattr, initially NULL */ + u32 visited[4]; /* Bitfield, limiting max to 128 */ +}; eattr *ea_find(ea_list *, unsigned ea); +eattr *ea_walk(struct ea_walk_state *s, uint id, uint max); int ea_get_int(ea_list *, unsigned ea, int def); void ea_dump(ea_list *); void ea_sort(ea_list *); /* Sort entries in all sub-lists */ diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 938b2b44..c5537208 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -308,6 +308,82 @@ ea_find(ea_list *e, unsigned id) } /** + * ea_walk - walk through extended attributes + * @s: walk state structure + * @id: start of attribute ID interval + * @max: length of attribute ID interval + * + * Given an extended attribute list, ea_walk() walks through the list looking + * for first occurrences of attributes with ID in specified interval from @id to + * (@id + @max - 1), returning pointers to found &eattr structures, storing its + * walk state in @s for subsequent calls. + + * The function ea_walk() is supposed to be called in a loop, with initially + * zeroed walk state structure @s with filled the initial extended attribute + * list, returning one found attribute in each call or %NULL when no other + * attribute exists. The extended attribute list or the arguments should not be + * modified between calls. The maximum value of @max is 128. + */ +eattr * +ea_walk(struct ea_walk_state *s, uint id, uint max) +{ + ea_list *e = s->eattrs; + eattr *a = s->ea; + eattr *a_max; + + max = id + max; + + if (a) + goto step; + + for (; e; e = e->next) + { + if (e->flags & EALF_BISECT) + { + int l, r, m; + + l = 0; + r = e->count - 1; + while (l < r) + { + m = (l+r) / 2; + if (e->attrs[m].id < id) + l = m + 1; + else + r = m; + } + a = e->attrs + l; + } + else + a = e->attrs; + + step: + a_max = e->attrs + e->count; + for (; a < a_max; a++) + if ((a->id >= id) && (a->id < max)) + { + int n = a->id - id; + + if (BIT32_TEST(s->visited, n)) + continue; + + BIT32_SET(s->visited, n); + + if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) + continue; + + s->eattrs = e; + s->ea = a; + return a; + } + else if (e->flags & EALF_BISECT) + break; + } + + return NULL; +} + +/** * ea_get_int - fetch an integer attribute * @e: attribute list * @id: attribute ID |