]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Update handling of temporary attributes
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 14 Mar 2019 16:22:22 +0000 (17:22 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 14 Mar 2019 16:31:40 +0000 (17:31 +0100)
The temporary atttributes are no longer removed by ea_do_prune(), but
they are undefined by store_tmp_attrs() protocol hooks. This fixes
several bugs where temporary attributes were removed when they should
not or not removed when they should be. The flag EAF_TEMP is no longer
needed and was removed.

Update all protocol make_tmp_attrs() / store_tmp_attrs() hooks to use
helper functions and to handle unset attributes properly.

Also fix some related bugs like improper handling of empty eattr list.

filter/config.Y
nest/protocol.h
nest/route.h
nest/rt-attr.c
nest/rt-show.c
nest/rt-table.c
proto/babel/babel.c
proto/mrt/mrt.c
proto/ospf/ospf.c
proto/rip/rip.c
sysdep/unix/krt.c

index c1e7453102a6aa9a46d8ea5e5cd5abb25d395b16..02de34169f3d46a93fb21cd0bcf6eda6b9d669af 100644 (file)
@@ -1045,7 +1045,7 @@ cmd:
    }
  | UNSET '(' rtadot dynamic_attr ')' ';' {
      $$ = f_new_inst_da(FI_EA_SET, $4);
-     $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
+     $$->aux = EAF_TYPE_UNDEF;
      $$->a1.p = NULL;
    }
  | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a1.p = $2; $$->a2.i = $1; }
index 6c04071b55b739fb6d1d35a05d87d4dd4dd28a4b..56d66ed560fa7e9b65ea9bba42e2d2c7edacdc9d 100644 (file)
@@ -194,8 +194,8 @@ struct proto {
    *      ifa_notify   Notify protocol about interface address changes.
    *      rt_notify    Notify protocol about routing table updates.
    *      neigh_notify Notify protocol about neighbor cache events.
-   *      make_tmp_attrs  Construct ea_list from private attrs stored in rta.
-   *      store_tmp_attrs Store private attrs back to rta. The route MUST NOT be cached.
+   *      make_tmp_attrs  Add attributes to rta from from private attrs stored in rte. The route and rta MUST NOT be cached.
+   *      store_tmp_attrs Store private attrs back to rte and undef added attributes. The route and rta MUST NOT be cached.
    *      preexport  Called as the first step of the route exporting process.
    *                   It can construct a new rte, add private attributes and
    *                   decide whether the route shall be exported: 1=yes, -1=no,
@@ -211,8 +211,8 @@ struct proto {
   void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
   void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old);
   void (*neigh_notify)(struct neighbor *neigh);
-  struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
-  void (*store_tmp_attrs)(struct rte *rt);
+  void (*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
+  void (*store_tmp_attrs)(struct rte *rt, struct linpool *pool);
   int (*preexport)(struct proto *, struct rte **rt, struct linpool *pool);
   void (*reload_routes)(struct channel *);
   void (*feed_begin)(struct channel *, int initial);
@@ -297,18 +297,6 @@ proto_get_router_id(struct proto_config *pc)
   return pc->router_id ? pc->router_id : pc->global->router_id;
 }
 
-static inline void
-rte_make_tmp_attrs(struct rte **rt, struct linpool *pool)
-{
-  struct ea_list *(*mta)(struct rte *rt, struct linpool *pool);
-  mta = (*rt)->attrs->src->proto->make_tmp_attrs;
-  if (!mta) return;
-  *rt = rte_cow_rta(*rt, pool);
-  struct ea_list *ea = mta(*rt, pool);
-  ea->next = (*rt)->attrs->eattrs;
-  (*rt)->attrs->eattrs = ea;
-}
-
 
 extern pool *proto_pool;
 extern list proto_list;
index 3e835bb1532ed8f986d386ccfdc3ca7f6456071e..15aac8f6128505886c2059e929885d778d3884cf 100644 (file)
@@ -308,8 +308,10 @@ void rte_free(rte *);
 rte *rte_do_cow(rte *);
 static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; }
 rte *rte_cow_rta(rte *r, linpool *lp);
-void rte_make_tmp_attr(struct rte *r, struct ea_list *e, uint id, uint type, u32 val);
-uint rte_store_tmp_attr(struct rte *r, uint id);
+void rte_init_tmp_attrs(struct rte *r, linpool *lp, uint max);
+void rte_make_tmp_attr(struct rte *r, uint id, uint type, uintptr_t val);
+void rte_make_tmp_attrs(struct rte **r, struct linpool *pool, struct rta **old_attrs);
+uintptr_t rte_store_tmp_attr(struct rte *r, uint id);
 void rt_dump(rtable *);
 void rt_dump_all(void);
 int rt_feed_channel(struct channel *c);
@@ -512,7 +514,6 @@ const char *ea_custom_name(uint ea);
 #define EAF_VAR_LENGTH 0x02            /* Attribute length is variable (part of type spec) */
 #define EAF_ORIGINATED 0x20            /* The attribute has originated locally */
 #define EAF_FRESH 0x40                 /* An uncached attribute (e.g. modified in export filter) */
-#define EAF_TEMP 0x80                  /* A temporary attribute (the one stored in the tmp attr list) */
 
 typedef struct adata {
   uint length;                         /* Length of data */
@@ -542,6 +543,7 @@ typedef struct ea_list {
 #define EALF_SORTED 1                  /* Attributes are sorted by code */
 #define EALF_BISECT 2                  /* Use interval bisection for searching */
 #define EALF_CACHED 4                  /* Attributes belonging to cached rta */
+#define EALF_TEMP 8                    /* Temporary ea_list added by make_tmp_attrs hooks */
 
 struct rte_src *rt_find_source(struct proto *p, u32 id);
 struct rte_src *rt_get_source(struct proto *p, u32 id);
@@ -574,6 +576,8 @@ void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **na
     ea = t; \
   } \
   ea_sort(ea); \
+  if (ea->count == 0) \
+    ea = NULL; \
 } while(0) \
 
 static inline eattr *
index 3e4578b02884e5b5e907a460358d2b793f2f34ea..cc362cab03cd486d2f4c28277b0464a53257540c 100644 (file)
@@ -571,8 +571,8 @@ ea_do_sort(ea_list *e)
 }
 
 /**
- * In place discard duplicates, undefs and temporary attributes in sorted
- * ea_list. We use stable sort for this reason.
+ * In place discard duplicates and undefs in sorted ea_list. We use stable sort
+ * for this reason.
  **/
 static inline void
 ea_do_prune(ea_list *e)
@@ -596,10 +596,6 @@ ea_do_prune(ea_list *e)
       if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
        continue;
 
-      /* Drop temporary attributes */
-      if (s0->type & EAF_TEMP)
-       continue;
-
       /* Copy the newest version to destination */
       *d = *s0;
 
@@ -979,8 +975,6 @@ ea_dump(ea_list *e)
        {
          eattr *a = &e->attrs[i];
          debug(" %02x:%02x.%02x", EA_PROTO(a->id), EA_ID(a->id), a->flags);
-         if (a->type & EAF_TEMP)
-           debug("T");
          debug("=%c", "?iO?I?P???S?????" [a->type & EAF_TYPE_MASK]);
          if (a->type & EAF_ORIGINATED)
            debug("o");
index c7bcdf2f6c98546cfd8705817389920513ff81ac..002a6039c961d23b233d37aac66b135136966b4a 100644 (file)
@@ -45,10 +45,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
   else
     from[0] = 0;
 
-  get_route_info = a->src->proto->proto->get_route_info;
   /* Need to normalize the extended attributes */
-  if ((get_route_info || d->verbose) && !rta_is_cached(a))
+  if (d->verbose && !rta_is_cached(a) && a->eattrs)
     ea_normalize(a->eattrs);
+
+  get_route_info = a->src->proto->proto->get_route_info;
   if (get_route_info)
     get_route_info(e, info);
   else
@@ -114,7 +115,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
        continue;
 
       ee = e;
-      rte_make_tmp_attrs(&e, c->show_pool);
+      rte_make_tmp_attrs(&e, c->show_pool, NULL);
 
       /* Export channel is down, do not try to export routes to it */
       if (ec && (ec->export_state == ES_DOWN))
index 7990fca3c01799937a3da7f220a7568d20f3918e..0b796228920405e4ca57f77dd19c0763ec4c9acf 100644 (file)
@@ -326,29 +326,90 @@ rte_cow_rta(rte *r, linpool *lp)
 }
 
 
-/* Note that rte_make_tmp_attr() requires free eattr in ea_list */
+/**
+ * rte_init_tmp_attrs - initialize temporary ea_list for route
+ * @r: route entry to be modified
+ * @lp: linpool from which to allocate attributes
+ * @max: maximum number of added temporary attribus
+ *
+ * This function is supposed to be called from make_tmp_attrs() and
+ * store_tmp_attrs() hooks before rte_make_tmp_attr() / rte_store_tmp_attr()
+ * functions. It allocates &ea_list with length for @max items for temporary
+ * attributes and puts it on top of eattrs stack.
+ */
 void
-rte_make_tmp_attr(rte *r, ea_list *e, uint id, uint type, u32 val)
+rte_init_tmp_attrs(rte *r, linpool *lp, uint max)
+{
+  struct ea_list *e = lp_alloc(lp, sizeof(struct ea_list) + max * sizeof(eattr));
+
+  e->next = r->attrs->eattrs;
+  e->flags = EALF_SORTED | EALF_TEMP;
+  e->count = 0;
+
+  r->attrs->eattrs = e;
+}
+
+/**
+ * rte_make_tmp_attr - make temporary eattr from private route fields
+ * @r: route entry to be modified
+ * @id: attribute ID
+ * @type: attribute type
+ * @val: attribute value (u32 or adata ptr)
+ *
+ * This function is supposed to be called from make_tmp_attrs() hook for
+ * each temporary attribute, after temporary &ea_list was initialized by
+ * rte_init_tmp_attrs(). It checks whether temporary attribute is supposed to
+ * be defined (based on route pflags) and if so then it fills &eattr field in
+ * preallocated temporary &ea_list on top of route @r eattrs stack.
+ *
+ * Note that it may require free &eattr in temporary &ea_list, so it must not be
+ * called more times than @max argument of rte_init_tmp_attrs().
+ */
+void
+rte_make_tmp_attr(rte *r, uint id, uint type, uintptr_t val)
 {
   if (r->pflags & EA_ID_FLAG(id))
   {
+    ea_list *e = r->attrs->eattrs;
     eattr *a = &e->attrs[e->count++];
     a->id = id;
-    a->type = type | EAF_TEMP;
+    a->type = type;
     a->flags = 0;
-    a->u.data = val;
+
+    if (type & EAF_EMBEDDED)
+      a->u.data = (u32) val;
+    else
+      a->u.ptr = (struct adata *) val;
   }
 }
 
-/* Note that rte has to be writable */
-uint
+/**
+ * rte_store_tmp_attr - store temporary eattr to private route fields
+ * @r: route entry to be modified
+ * @id: attribute ID
+ *
+ * This function is supposed to be called from store_tmp_attrs() hook for
+ * each temporary attribute, after temporary &ea_list was initialized by
+ * rte_init_tmp_attrs(). It checks whether temporary attribute is defined in
+ * route @r eattrs stack, updates route pflags accordingly, undefines it by
+ * filling &eattr field in preallocated temporary &ea_list on top of the eattrs
+ * stack, and returns the value. Caller is supposed to store it in the
+ * appropriate private field.
+ *
+ * Note that it may require free &eattr in temporary &ea_list, so it must not be
+ * called more times than @max argument of rte_init_tmp_attrs()
+ */
+uintptr_t
 rte_store_tmp_attr(rte *r, uint id)
 {
-  eattr *a;
-  if (a = ea_find(r->attrs->eattrs, id))
+  ea_list *e = r->attrs->eattrs;
+  eattr *a = ea_find(e->next, id);
+
+  if (a)
   {
+    e->attrs[e->count++] = (struct eattr) { .id = id, .type = EAF_TYPE_UNDEF };
     r->pflags |= EA_ID_FLAG(id);
-    return a->u.data;
+    return (a->type & EAF_EMBEDDED) ? a->u.data : (uintptr_t) a->u.ptr;
   }
   else
   {
@@ -357,6 +418,82 @@ rte_store_tmp_attr(rte *r, uint id)
   }
 }
 
+/**
+ * rte_make_tmp_attrs - prepare route by adding all relevant temporary route attributes
+ * @r: route entry to be modified (may be replaced if COW)
+ * @lp: linpool from which to allocate attributes
+ * @old_attrs: temporary ref to old &rta (may be NULL)
+ *
+ * This function expands privately stored protocol-dependent route attributes
+ * to a uniform &eattr / &ea_list representation. It is essentially a wrapper
+ * around protocol make_tmp_attrs() hook, which does some additional work like
+ * ensuring that route @r is writable.
+ *
+ * The route @r may be read-only (with %REF_COW flag), in that case rw copy is
+ * obtained by rte_cow() and @r is replaced. If @rte is originally rw, it may be
+ * directly modified (and it is never copied).
+ *
+ * If the @old_attrs ptr is supplied, the function obtains another reference of
+ * old cached &rta, that is necessary in some cases (see rte_cow_rta() for
+ * details). It is freed by rte_store_tmp_attrs(), or manually by rta_free().
+ *
+ * Generally, if caller ensures that @r is read-only (e.g. in route export) then
+ * it may ignore @old_attrs (and set it to NULL), but must handle replacement of
+ * @r. If caller ensures that @r is writable (e.g. in route import) then it may
+ * ignore replacement of @r, but it must handle @old_attrs.
+ */
+void
+rte_make_tmp_attrs(rte **r, linpool *lp, rta **old_attrs)
+{
+  void (*make_tmp_attrs)(rte *r, linpool *lp);
+  make_tmp_attrs = (*r)->attrs->src->proto->make_tmp_attrs;
+
+  if (!make_tmp_attrs)
+    return;
+
+  /* We may need to keep ref to old attributes, will be freed in rte_store_tmp_attrs() */
+  if (old_attrs)
+    *old_attrs = rta_is_cached((*r)->attrs) ? rta_clone((*r)->attrs) : NULL;
+
+  *r = rte_cow_rta(*r, lp);
+  make_tmp_attrs(*r, lp);
+}
+
+/**
+ * rte_store_tmp_attrs - store temporary route attributes back to private route fields
+ * @r: route entry to be modified
+ * @lp: linpool from which to allocate attributes
+ * @old_attrs: temporary ref to old &rta
+ *
+ * This function stores temporary route attributes that were expanded by
+ * rte_make_tmp_attrs() back to private route fields and also undefines them.
+ * It is essentially a wrapper around protocol store_tmp_attrs() hook, which
+ * does some additional work like shortcut if there is no change and cleanup
+ * of @old_attrs reference obtained by rte_make_tmp_attrs().
+ */
+static void
+rte_store_tmp_attrs(rte *r, linpool *lp, rta *old_attrs)
+{
+  void (*store_tmp_attrs)(rte *rt, linpool *lp);
+  store_tmp_attrs = r->attrs->src->proto->store_tmp_attrs;
+
+  if (!store_tmp_attrs)
+    return;
+
+  ASSERT(!rta_is_cached(r->attrs));
+
+  /* If there is no new ea_list, we just skip the temporary ea_list */
+  ea_list *ea = r->attrs->eattrs;
+  if (ea && (ea->flags & EALF_TEMP))
+    r->attrs->eattrs = ea->next;
+  else
+    store_tmp_attrs(r, lp);
+
+  /* Free ref we got in rte_make_tmp_attrs(), have to do rta_lookup() first */
+  r->attrs = rta_lookup(r->attrs);
+  rta_free(old_attrs);
+}
+
 
 static int                             /* Actually better or at least as good as */
 rte_better(rte *new, rte *old)
@@ -456,7 +593,7 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
       goto accept;
     }
 
-  rte_make_tmp_attrs(&rt, pool);
+  rte_make_tmp_attrs(&rt, pool, NULL);
 
   v = filter && ((filter == FILTER_REJECT) ||
                 (f_run(filter, &rt, pool,
@@ -1436,26 +1573,27 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
          /* new is a private copy, i could modify it */
          new->flags |= REF_FILTERED;
        }
-      else
+      else if (filter)
        {
-         rte_make_tmp_attrs(&new, rte_update_pool);
-         if (filter && (filter != FILTER_REJECT))
-           {
-             ea_list *oldea = new->attrs->eattrs;
-             int fr = f_run(filter, &new, rte_update_pool, 0);
-             if (fr > F_ACCEPT)
-               {
-                 stats->imp_updates_filtered++;
-                 rte_trace_in(D_FILTERS, p, new, "filtered out");
+         rta *old_attrs;
+         rte_make_tmp_attrs(&new, rte_update_pool, &old_attrs);
 
-                 if (! c->in_keep_filtered)
-                   goto drop;
+         int fr = f_run(filter, &new, rte_update_pool, 0);
+         if (fr > F_ACCEPT)
+         {
+           stats->imp_updates_filtered++;
+           rte_trace_in(D_FILTERS, p, new, "filtered out");
 
-                 new->flags |= REF_FILTERED;
-               }
-             if (new->attrs->eattrs != oldea && src->proto->store_tmp_attrs)
-               src->proto->store_tmp_attrs(new);
+           if (! c->in_keep_filtered)
+           {
+             rta_free(old_attrs);
+             goto drop;
            }
+
+           new->flags |= REF_FILTERED;
+         }
+
+         rte_store_tmp_attrs(new, rte_update_pool, old_attrs);
        }
       if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
        new->attrs = rta_lookup(new->attrs);
@@ -1552,7 +1690,7 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
   int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0;
   if (v == RIC_PROCESS)
   {
-    rte_make_tmp_attrs(&rt, rte_update_pool);
+    rte_make_tmp_attrs(&rt, rte_update_pool, NULL);
     v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
   }
 
index d321f1d82b0380b33dee4c04e1253019b486c23f..177ff3a3ed9b924a8b0346a8a8c3ff20865b1602 100644 (file)
@@ -645,7 +645,7 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
     rte->u.babel.seqno = r->seqno;
     rte->u.babel.metric = r->metric;
     rte->u.babel.router_id = r->router_id;
-    rte->pflags = 0;
+    rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
 
     e->unreachable = 0;
     rte_update2(c, e->n.addr, rte, p->p.main_source);
@@ -2077,32 +2077,6 @@ babel_kick_timer(struct babel_proto *p)
 }
 
 
-static struct ea_list *
-babel_prepare_attrs(struct linpool *pool, ea_list *next, uint metric, u64 router_id)
-{
-  struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2*sizeof(eattr));
-  struct adata *rid = lp_alloc(pool, sizeof(struct adata) + sizeof(u64));
-  rid->length = sizeof(u64);
-  memcpy(&rid->data, &router_id, sizeof(u64));
-
-  l->next = next;
-  l->flags = EALF_SORTED;
-  l->count = 2;
-
-  l->attrs[0].id = EA_BABEL_METRIC;
-  l->attrs[0].flags = 0;
-  l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
-  l->attrs[0].u.data = metric;
-
-  l->attrs[1].id = EA_BABEL_ROUTER_ID;
-  l->attrs[1].flags = 0;
-  l->attrs[1].type = EAF_TYPE_OPAQUE | EAF_TEMP;
-  l->attrs[1].u.ptr = rid;
-
-  return l;
-}
-
-
 static int
 babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED)
 {
@@ -2115,16 +2089,25 @@ babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED)
   return 0;
 }
 
-static struct ea_list *
+static void
 babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  return babel_prepare_attrs(pool, NULL, rt->u.babel.metric, rt->u.babel.router_id);
+  struct adata *id = lp_alloc_adata(pool, sizeof(u64));
+  memcpy(id->data, &rt->u.babel.router_id, sizeof(u64));
+
+  rte_init_tmp_attrs(rt, pool, 2);
+  rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric);
+  rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id);
 }
 
 static void
-babel_store_tmp_attrs(struct rte *rt)
+babel_store_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  rt->u.babel.metric = ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, 0);
+  rte_init_tmp_attrs(rt, pool, 2);
+  rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC);
+
+  /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */
+  rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID);
 }
 
 /*
index 95014958a60069b6650f739256a6f994d9883201..e4f1acea28c9c3eb04060ace170d1ece3617ba2c 100644 (file)
@@ -496,7 +496,7 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
       continue;
     }
 
-    rte_make_tmp_attrs(&rt, s->linpool);
+    rte_make_tmp_attrs(&rt, s->linpool, NULL);
 
     if (f_run(s->filter, &rt, s->linpool, 0) <= F_ACCEPT)
       mrt_rib_table_entry(s, rt);
index def73cb6f6a970afc2fe656e36056109ee141862..f3eabb47768e0e54d6407b0c3b9fcdb7c6ac184c 100644 (file)
 #include "ospf.h"
 
 static int ospf_preexport(struct proto *P, rte **new, struct linpool *pool);
-static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
-static void ospf_store_tmp_attrs(struct rte *rt);
+static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
+static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool);
 static void ospf_reload_routes(struct channel *C);
 static int ospf_rte_better(struct rte *new, struct rte *old);
 static int ospf_rte_same(struct rte *new, struct rte *old);
@@ -438,26 +438,20 @@ ospf_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
   return 0;
 }
 
-static struct ea_list *
+static void
 ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  struct ea_list *e = lp_alloc(pool, sizeof(struct ea_list) + 4 * sizeof(eattr));
-
-  e->next = NULL;
-  e->flags = EALF_SORTED;
-  e->count = 0;
-
-  rte_make_tmp_attr(rt, e, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1);
-  rte_make_tmp_attr(rt, e, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2);
-  rte_make_tmp_attr(rt, e, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag);
-  rte_make_tmp_attr(rt, e, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id);
-
-  return e;
+  rte_init_tmp_attrs(rt, pool, 4);
+  rte_make_tmp_attr(rt, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1);
+  rte_make_tmp_attr(rt, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2);
+  rte_make_tmp_attr(rt, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag);
+  rte_make_tmp_attr(rt, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id);
 }
 
 static void
-ospf_store_tmp_attrs(struct rte *rt)
+ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
+  rte_init_tmp_attrs(rt, pool, 4);
   rt->u.ospf.metric1 = rte_store_tmp_attr(rt, EA_OSPF_METRIC1);
   rt->u.ospf.metric2 = rte_store_tmp_attr(rt, EA_OSPF_METRIC2);
   rt->u.ospf.tag = rte_store_tmp_attr(rt, EA_OSPF_TAG);
index 612b6f926c314ba74108df0e9ad0d7085aefd693..91c0058850666bcb8f80999709833ad5f7b01664 100644 (file)
@@ -193,8 +193,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
     e->u.rip.from = a0.nh.iface;
     e->u.rip.metric = rt_metric;
     e->u.rip.tag = rt_tag;
-
-    e->pflags = 0;
+    e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG);
 
     rte_update(&p->p, en->n.addr, e);
   }
@@ -997,28 +996,6 @@ rip_trigger_update(struct rip_proto *p)
  *     RIP protocol glue
  */
 
-static struct ea_list *
-rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag)
-{
-  struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr));
-
-  l->next = next;
-  l->flags = EALF_SORTED;
-  l->count = 2;
-
-  l->attrs[0].id = EA_RIP_METRIC;
-  l->attrs[0].flags = 0;
-  l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
-  l->attrs[0].u.data = metric;
-
-  l->attrs[1].id = EA_RIP_TAG;
-  l->attrs[1].flags = 0;
-  l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP;
-  l->attrs[1].u.data = tag;
-
-  return l;
-}
-
 static void
 rip_reload_routes(struct channel *C)
 {
@@ -1032,17 +1009,20 @@ rip_reload_routes(struct channel *C)
   rip_kick_timer(p);
 }
 
-static struct ea_list *
+static void
 rip_make_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  return rip_prepare_attrs(pool, NULL, rt->u.rip.metric, rt->u.rip.tag);
+  rte_init_tmp_attrs(rt, pool, 2);
+  rte_make_tmp_attr(rt, EA_RIP_METRIC, EAF_TYPE_INT, rt->u.rip.metric);
+  rte_make_tmp_attr(rt, EA_RIP_TAG, EAF_TYPE_INT, rt->u.rip.tag);
 }
 
 static void
-rip_store_tmp_attrs(struct rte *rt)
+rip_store_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  rt->u.rip.metric = ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, 1);
-  rt->u.rip.tag = ea_get_int(rt->attrs->eattrs, EA_RIP_TAG, 0);
+  rte_init_tmp_attrs(rt, pool, 2);
+  rt->u.rip.metric = rte_store_tmp_attr(rt, EA_RIP_METRIC);
+  rt->u.rip.tag = rte_store_tmp_attr(rt, EA_RIP_TAG);
 }
 
 static int
index ded5dfe4526c2d3193d9a5216e9eb61e27328a24..3aee3fe2cc3ea06f7653e41ad815e788083a2617 100644 (file)
@@ -301,7 +301,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
   net *n = e->net;
   rta *aa = rta_clone(e->attrs);
   rte *ee = rte_get_temp(aa);
-  ee->pflags = 0;
+  ee->pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC);
   ee->u.krt = e->u.krt;
   rte_update(&p->p, n->n.addr, ee);
 }
@@ -577,7 +577,7 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
   if (filter == FILTER_REJECT)
     return NULL;
 
-  rte_make_tmp_attrs(&rt, krt_filter_lp);
+  rte_make_tmp_attrs(&rt, krt_filter_lp, NULL);
 
   /* We could run krt_preexport() here, but it is already handled by KRF_INSTALLED */
 
@@ -910,33 +910,20 @@ krt_scan_timer_kick(struct krt_proto *p)
  *     Updates
  */
 
-static struct ea_list *
-krt_make_tmp_attrs(rte *rt, struct linpool *pool)
+static void
+krt_make_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr));
-
-  l->next = NULL;
-  l->flags = EALF_SORTED;
-  l->count = 2;
-
-  l->attrs[0].id = EA_KRT_SOURCE;
-  l->attrs[0].flags = 0;
-  l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP;
-  l->attrs[0].u.data = rt->u.krt.proto;
-
-  l->attrs[1].id = EA_KRT_METRIC;
-  l->attrs[1].flags = 0;
-  l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP;
-  l->attrs[1].u.data = rt->u.krt.metric;
-
-  return l;
+  rte_init_tmp_attrs(rt, pool, 2);
+  rte_make_tmp_attr(rt, EA_KRT_SOURCE, EAF_TYPE_INT, rt->u.krt.proto);
+  rte_make_tmp_attr(rt, EA_KRT_METRIC, EAF_TYPE_INT, rt->u.krt.metric);
 }
 
 static void
-krt_store_tmp_attrs(rte *rt)
+krt_store_tmp_attrs(struct rte *rt, struct linpool *pool)
 {
-  /* EA_KRT_SOURCE is read-only */
-  rt->u.krt.metric = ea_get_int(rt->attrs->eattrs, EA_KRT_METRIC, 0);
+  rte_init_tmp_attrs(rt, pool, 2);
+  rt->u.krt.proto = rte_store_tmp_attr(rt, EA_KRT_SOURCE);
+  rt->u.krt.metric = rte_store_tmp_attr(rt, EA_KRT_METRIC);
 }
 
 static int