return ea_lookup_slow(r, squash_upto, oid);
}
+struct ea_free_deferred {
+ struct deferred_call dc;
+ ea_list *attrs;
+};
+
+void ea_free_deferred(struct deferred_call *dc);
+
+static inline ea_list *ea_free_later(ea_list *r)
+{
+ struct ea_free_deferred efd = {
+ .dc.hook = ea_free_deferred,
+ .attrs = r,
+ };
+
+ defer_call(&efd.dc, sizeof efd);
+ return r;
+}
+
+static inline ea_list *ea_lookup_tmp(ea_list *r, u32 squash_upto, enum ea_stored oid)
+{
+ return ea_free_later(ea_lookup(r, squash_upto, oid));
+}
+
static inline ea_list *ea_strip_to(ea_list *r, u32 strip_to)
{
ASSERT_DIE(strip_to);
ASSERT(c->channel_state == CS_UP);
- ea_list *ea_prefilter = NULL, *ea_postfilter = NULL;
-
/* Storing prefilter routes as an explicit layer */
if (new && (c->in_keep & RIK_PREFILTER))
- ea_prefilter = new->attrs = ea_lookup(new->attrs, 0, EALS_PREIMPORT);
+ new->attrs = ea_lookup_tmp(new->attrs, 0, EALS_PREIMPORT);
#if 0
debug("%s.%s -(prefilter)-> %s: %N ", c->proto->name, c->name, c->table->name, n);
if (new)
{
- ea_postfilter = new->attrs = ea_lookup(new->attrs,
- ea_prefilter ? BIT32_ALL(EALS_PREIMPORT) : 0, EALS_FILTERED);
+ new->attrs = ea_lookup_tmp(new->attrs,
+ (c->in_keep & RIK_PREFILTER) ? BIT32_ALL(EALS_PREIMPORT) : 0, EALS_FILTERED);
if (net_is_flow(n))
rt_flowspec_resolve_rte(new, c);
mpls_unlock_fec(fec);
DBGL( "Unlock FEC %p (rte_update %N)", fec, n);
}
-
- /* Now the route attributes are kept by the in-table cached version
- * and we may drop the local handles */
- ea_free(ea_prefilter);
- ea_free(ea_postfilter);
}
void
return;
}
- /* Prepare cached route attributes */
- if (!s->mpls && (s->cached_ea == NULL))
- a0 = s->cached_ea = ea_lookup(a0, 0, EALS_CUSTOM);
-
rte e0 = {
.attrs = a0,
.src = s->last_src,
/* Update next hop entry in rta */
bgp_apply_mpls_labels(s, to, lnum, labels);
- /* Attributes were changed, invalidate cached entry */
- ea_free(s->cached_ea);
- s->cached_ea = NULL;
-
return;
}
{
while (len)
{
+ ea_list *ea = a;
net_addr_ip4 net;
u32 path_id = 0;
/* Decode MPLS labels */
if (s->mpls)
- bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
+ bgp_decode_mpls_labels(s, &pos, &len, &l, &ea);
if (l > IP4_MAX_PREFIX_LENGTH)
bgp_parse_error(s, 10);
// XXXX validate prefix
- bgp_rte_update(s, (net_addr *) &net, path_id, a);
+ bgp_rte_update(s, (net_addr *) &net, path_id, ea);
}
}
{
while (len)
{
+ ea_list *ea = a;
net_addr_ip6 net;
u32 path_id = 0;
/* Decode MPLS labels */
if (s->mpls)
- bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
+ bgp_decode_mpls_labels(s, &pos, &len, &l, &ea);
if (l > IP6_MAX_PREFIX_LENGTH)
bgp_parse_error(s, 10);
// XXXX validate prefix
- bgp_rte_update(s, (net_addr *) &net, path_id, a);
+ bgp_rte_update(s, (net_addr *) &net, path_id, ea);
}
}
{
while (len)
{
+ ea_list *ea = a;
net_addr_vpn4 net;
u32 path_id = 0;
/* Decode MPLS labels */
if (s->mpls)
- bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
+ bgp_decode_mpls_labels(s, &pos, &len, &l, &ea);
/* Decode route distinguisher */
if (l < 64)
// XXXX validate prefix
- bgp_rte_update(s, (net_addr *) &net, path_id, a);
+ bgp_rte_update(s, (net_addr *) &net, path_id, ea);
}
}
{
while (len)
{
+ ea_list *ea = a;
net_addr_vpn6 net;
u32 path_id = 0;
/* Decode MPLS labels */
if (s->mpls)
- bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
+ bgp_decode_mpls_labels(s, &pos, &len, &l, &ea);
/* Decode route distinguisher */
if (l < 64)
// XXXX validate prefix
- bgp_rte_update(s, (net_addr *) &net, path_id, a);
+ bgp_rte_update(s, (net_addr *) &net, path_id, ea);
}
}
/* Handle withdraw during next hop decoding */
if (s->err_withdraw)
ea = NULL;
+
+ if (ea)
+ ea = ea_lookup_tmp(ea, 0, EALS_CUSTOM);
}
c->desc->decode_nlri(s, nlri, len, ea);
- ea_free(s->cached_ea);
- s->cached_ea = NULL;
-
rt_unlock_source(s->last_src);
}
ea, s.mp_next_hop_data, s.mp_next_hop_len);
done:
- ea_free(s.cached_ea);
lp_restore(tmp_linpool, tmpp);
return;
}