summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/route.h6
-rw-r--r--nest/rt-attr.c76
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