struct fib_iterator reload_fit; /* Iterator in in_table used during reloading */
u8 reload_active; /* Iterator reload_fit is linked */
+ u8 out_table_int; /* Update of out_table is handled internally by protocol */
struct rtable *out_table; /* Internal table for exported routes */
};
}
}
- if (c->out_table && !rte_update_out(c, net->n.addr, new, old, &old_free, refeed))
+ if (c->out_table && !c->out_table_int &&
+ !rte_update_out(c, net->n.addr, new, old, &old_free, refeed))
return;
/* Use route from export_table as old */
{
attrs = bgp_update_attrs(p, c, new, attrs, bgp_linpool2);
+ if (c->c.out_table && c->c.out_table_int)
+ {
+ rte *old_free = NULL;
+ rte *new1 = NULL;
+
+ /* Prepare new1 as final route after bgp_update_attrs() attribute changes */
+ if (attrs)
+ {
+ new1 = rte_cow_rta(new, bgp_linpool2);
+ new1->attrs->eattrs = attrs;
+ }
+
+ /* Update out_table, we use 'new' as 'old' to ensure it is non-NULL */
+ int drop = !rte_update_out(C, n->n.addr, new1, new, &old_free, new == old);
+
+ if (new1 != new)
+ rte_free(new1);
+ if (old_free)
+ rte_free(old_free);
+
+ if (drop)
+ {
+ lp_flush(bgp_linpool2);
+ return;
+ }
+ }
+
/* If attributes are invalid, we fail back to withdraw */
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
path = new->attrs->src->global_id;
}
else
{
+ if (c->c.out_table && c->c.out_table_int)
+ {
+ rte *old_free = NULL;
+
+ if (!rte_update_out(C, n->n.addr, new, old, &old_free, 0))
+ return;
+
+ if (old_free)
+ rte_free(old_free);
+ }
+
buck = bgp_get_withdraw_bucket(c);
path = old->attrs->src->global_id;
}