mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-18 17:18:42 +00:00
BGP: The bucket/prefix hashes are now a resource to allow for proper cleanup
This commit is contained in:
parent
0072d11f34
commit
97476e002d
@ -1522,8 +1522,8 @@ bgp_finish_attrs(struct bgp_parse_state *s, ea_list **to)
|
|||||||
|
|
||||||
HASH_DEFINE_REHASH_FN(RBH, struct bgp_bucket)
|
HASH_DEFINE_REHASH_FN(RBH, struct bgp_bucket)
|
||||||
|
|
||||||
void
|
static void
|
||||||
bgp_init_bucket_table(struct bgp_channel *c)
|
bgp_init_bucket_table(struct bgp_pending_tx *c)
|
||||||
{
|
{
|
||||||
HASH_INIT(c->bucket_hash, c->pool, 8);
|
HASH_INIT(c->bucket_hash, c->pool, 8);
|
||||||
|
|
||||||
@ -1531,24 +1531,8 @@ bgp_init_bucket_table(struct bgp_channel *c)
|
|||||||
c->withdraw_bucket = NULL;
|
c->withdraw_bucket = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
bgp_free_bucket_table(struct bgp_channel *c)
|
|
||||||
{
|
|
||||||
HASH_FREE(c->bucket_hash);
|
|
||||||
|
|
||||||
struct bgp_bucket *b;
|
|
||||||
WALK_LIST_FIRST(b, c->bucket_queue)
|
|
||||||
{
|
|
||||||
rem_node(&b->send_node);
|
|
||||||
mb_free(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
mb_free(c->withdraw_bucket);
|
|
||||||
c->withdraw_bucket = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bgp_bucket *
|
static struct bgp_bucket *
|
||||||
bgp_get_bucket(struct bgp_channel *c, ea_list *new)
|
bgp_get_bucket(struct bgp_pending_tx *c, ea_list *new)
|
||||||
{
|
{
|
||||||
/* Hash and lookup */
|
/* Hash and lookup */
|
||||||
u32 hash = ea_hash(new);
|
u32 hash = ea_hash(new);
|
||||||
@ -1577,7 +1561,7 @@ bgp_get_bucket(struct bgp_channel *c, ea_list *new)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct bgp_bucket *
|
static struct bgp_bucket *
|
||||||
bgp_get_withdraw_bucket(struct bgp_channel *c)
|
bgp_get_withdraw_bucket(struct bgp_pending_tx *c)
|
||||||
{
|
{
|
||||||
if (!c->withdraw_bucket)
|
if (!c->withdraw_bucket)
|
||||||
{
|
{
|
||||||
@ -1589,15 +1573,17 @@ bgp_get_withdraw_bucket(struct bgp_channel *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_free_bucket_xx(struct bgp_channel *c, struct bgp_bucket *b)
|
bgp_free_bucket(struct bgp_pending_tx *c, struct bgp_bucket *b)
|
||||||
{
|
{
|
||||||
HASH_REMOVE2(c->bucket_hash, RBH, c->pool, b);
|
HASH_REMOVE2(c->bucket_hash, RBH, c->pool, b);
|
||||||
mb_free(b);
|
mb_free(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_done_bucket(struct bgp_channel *c, struct bgp_bucket *b)
|
bgp_done_bucket(struct bgp_channel *bc, struct bgp_bucket *b)
|
||||||
{
|
{
|
||||||
|
struct bgp_pending_tx *c = bc->ptx;
|
||||||
|
|
||||||
/* Won't free the withdraw bucket */
|
/* Won't free the withdraw bucket */
|
||||||
if (b == c->withdraw_bucket)
|
if (b == c->withdraw_bucket)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1608,21 +1594,23 @@ bgp_done_bucket(struct bgp_channel *c, struct bgp_bucket *b)
|
|||||||
if (b->px_uc || !EMPTY_LIST(b->prefixes))
|
if (b->px_uc || !EMPTY_LIST(b->prefixes))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bgp_free_bucket_xx(c, b);
|
bgp_free_bucket(c, b);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_defer_bucket(struct bgp_channel *c, struct bgp_bucket *b)
|
bgp_defer_bucket(struct bgp_channel *bc, struct bgp_bucket *b)
|
||||||
{
|
{
|
||||||
|
struct bgp_pending_tx *c = bc->ptx;
|
||||||
rem_node(&b->send_node);
|
rem_node(&b->send_node);
|
||||||
add_tail(&c->bucket_queue, &b->send_node);
|
add_tail(&c->bucket_queue, &b->send_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_withdraw_bucket(struct bgp_channel *c, struct bgp_bucket *b)
|
bgp_withdraw_bucket(struct bgp_channel *bc, struct bgp_bucket *b)
|
||||||
{
|
{
|
||||||
struct bgp_proto *p = (void *) c->c.proto;
|
struct bgp_proto *p = (void *) bc->c.proto;
|
||||||
|
struct bgp_pending_tx *c = bc->ptx;
|
||||||
struct bgp_bucket *wb = bgp_get_withdraw_bucket(c);
|
struct bgp_bucket *wb = bgp_get_withdraw_bucket(c);
|
||||||
|
|
||||||
log(L_ERR "%s: Attribute list too long", p->p.name);
|
log(L_ERR "%s: Attribute list too long", p->p.name);
|
||||||
@ -1643,7 +1631,7 @@ bgp_withdraw_bucket(struct bgp_channel *c, struct bgp_bucket *b)
|
|||||||
|
|
||||||
#define PXH_KEY(px) px->net, px->path_id, px->hash
|
#define PXH_KEY(px) px->net, px->path_id, px->hash
|
||||||
#define PXH_NEXT(px) px->next
|
#define PXH_NEXT(px) px->next
|
||||||
#define PXH_EQ(n1,i1,h1,n2,i2,h2) h1 == h2 && (c->add_path_tx ? (i1 == i2) : 1) && net_equal(n1, n2)
|
#define PXH_EQ(n1,i1,h1,n2,i2,h2) h1 == h2 && (add_path_tx ? (i1 == i2) : 1) && net_equal(n1, n2)
|
||||||
#define PXH_FN(n,i,h) h
|
#define PXH_FN(n,i,h) h
|
||||||
|
|
||||||
#define PXH_REHASH bgp_pxh_rehash
|
#define PXH_REHASH bgp_pxh_rehash
|
||||||
@ -1652,28 +1640,20 @@ bgp_withdraw_bucket(struct bgp_channel *c, struct bgp_bucket *b)
|
|||||||
|
|
||||||
HASH_DEFINE_REHASH_FN(PXH, struct bgp_prefix)
|
HASH_DEFINE_REHASH_FN(PXH, struct bgp_prefix)
|
||||||
|
|
||||||
void
|
static void
|
||||||
bgp_init_prefix_table(struct bgp_channel *c)
|
bgp_init_prefix_table(struct bgp_channel *bc)
|
||||||
{
|
{
|
||||||
|
struct bgp_pending_tx *c = bc->ptx;
|
||||||
HASH_INIT(c->prefix_hash, c->pool, 8);
|
HASH_INIT(c->prefix_hash, c->pool, 8);
|
||||||
|
|
||||||
uint alen = net_addr_length[c->c.net_type];
|
uint alen = net_addr_length[bc->c.net_type];
|
||||||
c->prefix_slab = alen ? sl_new(c->pool, sizeof(struct bgp_prefix) + alen) : NULL;
|
c->prefix_slab = alen ? sl_new(c->pool, sizeof(struct bgp_prefix) + alen) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
bgp_free_prefix_table(struct bgp_channel *c)
|
|
||||||
{
|
|
||||||
HASH_FREE(c->prefix_hash);
|
|
||||||
|
|
||||||
rfree(c->prefix_slab);
|
|
||||||
c->prefix_slab = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bgp_prefix *
|
static struct bgp_prefix *
|
||||||
bgp_get_prefix(struct bgp_channel *c, const net_addr *net, u32 path_id)
|
bgp_get_prefix(struct bgp_pending_tx *c, const net_addr *net, u32 path_id, int add_path_tx)
|
||||||
{
|
{
|
||||||
u32 path_id_hash = c->add_path_tx ? path_id : 0;
|
u32 path_id_hash = add_path_tx ? path_id : 0;
|
||||||
/* We must use a different hash function than the rtable */
|
/* We must use a different hash function than the rtable */
|
||||||
u32 hash = u32_hash(net_hash(net) ^ u32_hash(path_id_hash));
|
u32 hash = u32_hash(net_hash(net) ^ u32_hash(path_id_hash));
|
||||||
struct bgp_prefix *px = HASH_FIND(c->prefix_hash, PXH, net, path_id_hash, hash);
|
struct bgp_prefix *px = HASH_FIND(c->prefix_hash, PXH, net, path_id_hash, hash);
|
||||||
@ -1696,15 +1676,16 @@ bgp_get_prefix(struct bgp_channel *c, const net_addr *net, u32 path_id)
|
|||||||
return px;
|
return px;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px);
|
static void bgp_free_prefix(struct bgp_pending_tx *c, struct bgp_prefix *px);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
bgp_update_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket *b)
|
bgp_update_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket *b)
|
||||||
{
|
{
|
||||||
|
#define IS_WITHDRAW_BUCKET(b) ((b) == c->ptx->withdraw_bucket)
|
||||||
#define BPX_TRACE(what) do { \
|
#define BPX_TRACE(what) do { \
|
||||||
if (c->c.debug & D_ROUTES) log(L_TRACE "%s.%s < %s %N %uG %s", \
|
if (c->c.debug & D_ROUTES) log(L_TRACE "%s.%s < %s %N %uG %s", \
|
||||||
c->c.proto->name, c->c.name, what, \
|
c->c.proto->name, c->c.name, what, \
|
||||||
px->net, px->path_id, (b == c->withdraw_bucket) ? "withdraw" : "update"); } while (0)
|
px->net, px->path_id, IS_WITHDRAW_BUCKET(b) ? "withdraw" : "update"); } while (0)
|
||||||
px->lastmod = current_time();
|
px->lastmod = current_time();
|
||||||
|
|
||||||
/* Already queued for the same bucket */
|
/* Already queued for the same bucket */
|
||||||
@ -1722,7 +1703,7 @@ bgp_update_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucke
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The new bucket is the same as we sent before */
|
/* The new bucket is the same as we sent before */
|
||||||
if ((px->last == b) || c->c.out_table && !px->last && (b == c->withdraw_bucket))
|
if ((px->last == b) || c->c.out_table && !px->last && IS_WITHDRAW_BUCKET(b))
|
||||||
{
|
{
|
||||||
if (px->cur)
|
if (px->cur)
|
||||||
BPX_TRACE("reverted");
|
BPX_TRACE("reverted");
|
||||||
@ -1731,15 +1712,15 @@ bgp_update_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucke
|
|||||||
|
|
||||||
/* Well, we haven't sent anything yet */
|
/* Well, we haven't sent anything yet */
|
||||||
if (!px->last)
|
if (!px->last)
|
||||||
bgp_free_prefix(c, px);
|
bgp_free_prefix(c->ptx, px);
|
||||||
|
|
||||||
px->cur = NULL;
|
px->cur = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enqueue the bucket if it has been empty */
|
/* Enqueue the bucket if it has been empty */
|
||||||
if ((b != c->withdraw_bucket) && EMPTY_LIST(b->prefixes))
|
if (!IS_WITHDRAW_BUCKET(b) && EMPTY_LIST(b->prefixes))
|
||||||
add_tail(&c->bucket_queue, &b->send_node);
|
add_tail(&c->ptx->bucket_queue, &b->send_node);
|
||||||
|
|
||||||
/* Enqueue to the new bucket and indicate the change */
|
/* Enqueue to the new bucket and indicate the change */
|
||||||
add_tail(&b->prefixes, &px->buck_node_xx);
|
add_tail(&b->prefixes, &px->buck_node_xx);
|
||||||
@ -1752,7 +1733,7 @@ bgp_update_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucke
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px)
|
bgp_free_prefix(struct bgp_pending_tx *c, struct bgp_prefix *px)
|
||||||
{
|
{
|
||||||
HASH_REMOVE2(c->prefix_hash, PXH, c->pool, px);
|
HASH_REMOVE2(c->prefix_hash, PXH, c->pool, px);
|
||||||
|
|
||||||
@ -1780,7 +1761,7 @@ bgp_done_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket
|
|||||||
px->last->px_uc--;
|
px->last->px_uc--;
|
||||||
|
|
||||||
/* Ref the current sent version */
|
/* Ref the current sent version */
|
||||||
if (buck != c->withdraw_bucket)
|
if (!IS_WITHDRAW_BUCKET(buck))
|
||||||
{
|
{
|
||||||
px->last = buck;
|
px->last = buck;
|
||||||
px->last->px_uc++;
|
px->last->px_uc++;
|
||||||
@ -1790,7 +1771,47 @@ bgp_done_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket
|
|||||||
/* Prefixes belonging to the withdraw bucket are freed always */
|
/* Prefixes belonging to the withdraw bucket are freed always */
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp_free_prefix(c, px);
|
bgp_free_prefix(c->ptx, px);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bgp_pending_tx_rfree(resource *r)
|
||||||
|
{
|
||||||
|
UNUSED struct bgp_pending_tx *ptx = SKIP_BACK(struct bgp_pending_tx, r, r);
|
||||||
|
|
||||||
|
/* Do nothing for now. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bgp_pending_tx_dump(resource *r UNUSED) { debug("\n"); }
|
||||||
|
|
||||||
|
static struct resclass bgp_pending_tx_class = {
|
||||||
|
.name = "BGP Pending TX",
|
||||||
|
.size = sizeof(struct bgp_pending_tx),
|
||||||
|
.free = bgp_pending_tx_rfree,
|
||||||
|
.dump = bgp_pending_tx_dump,
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
bgp_init_pending_tx(struct bgp_channel *c)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(!c->ptx);
|
||||||
|
|
||||||
|
pool *p = rp_new(c->pool, "BGP Pending TX");
|
||||||
|
c->ptx = ralloc(p, &bgp_pending_tx_class);
|
||||||
|
c->ptx->pool = p;
|
||||||
|
|
||||||
|
bgp_init_bucket_table(c->ptx);
|
||||||
|
bgp_init_prefix_table(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bgp_free_pending_tx(struct bgp_channel *c)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(c->ptx);
|
||||||
|
ASSERT_DIE(c->ptx->pool);
|
||||||
|
|
||||||
|
rfree(c->ptx->pool);
|
||||||
|
c->ptx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1802,7 +1823,8 @@ static void
|
|||||||
bgp_out_table_feed(void *data)
|
bgp_out_table_feed(void *data)
|
||||||
{
|
{
|
||||||
struct rt_export_hook *hook = data;
|
struct rt_export_hook *hook = data;
|
||||||
struct bgp_channel *c = SKIP_BACK(struct bgp_channel, prefix_exporter, hook->table);
|
struct bgp_channel *bc = SKIP_BACK(struct bgp_channel, prefix_exporter, hook->table);
|
||||||
|
struct bgp_pending_tx *c = bc->ptx;
|
||||||
|
|
||||||
int max = 512;
|
int max = 512;
|
||||||
|
|
||||||
@ -1897,8 +1919,8 @@ bgp_out_table_feed(void *data)
|
|||||||
static struct rt_export_hook *
|
static struct rt_export_hook *
|
||||||
bgp_out_table_export_start(struct rt_exporter *re, struct rt_export_request *req UNUSED)
|
bgp_out_table_export_start(struct rt_exporter *re, struct rt_export_request *req UNUSED)
|
||||||
{
|
{
|
||||||
struct bgp_channel *c = SKIP_BACK(struct bgp_channel, prefix_exporter, re);
|
struct bgp_channel *bc = SKIP_BACK(struct bgp_channel, prefix_exporter, re);
|
||||||
pool *p = rp_new(c->c.proto->pool, "Export hook");
|
pool *p = rp_new(bc->c.proto->pool, "Export hook");
|
||||||
struct rt_export_hook *hook = mb_allocz(p, sizeof(struct rt_export_hook));
|
struct rt_export_hook *hook = mb_allocz(p, sizeof(struct rt_export_hook));
|
||||||
hook->pool = p;
|
hook->pool = p;
|
||||||
hook->event = ev_new_init(p, bgp_out_table_feed, hook);
|
hook->event = ev_new_init(p, bgp_out_table_feed, hook);
|
||||||
@ -2132,16 +2154,16 @@ bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, c
|
|||||||
log(L_ERR "%s: Invalid route %N withdrawn", p->p.name, n);
|
log(L_ERR "%s: Invalid route %N withdrawn", p->p.name, n);
|
||||||
|
|
||||||
/* If attributes are invalid, we fail back to withdraw */
|
/* If attributes are invalid, we fail back to withdraw */
|
||||||
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
|
buck = attrs ? bgp_get_bucket(c->ptx, attrs) : bgp_get_withdraw_bucket(c->ptx);
|
||||||
path = new->src->global_id;
|
path = new->src->global_id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buck = bgp_get_withdraw_bucket(c);
|
buck = bgp_get_withdraw_bucket(c->ptx);
|
||||||
path = old->src->global_id;
|
path = old->src->global_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bgp_update_prefix(c, bgp_get_prefix(c, n, path), buck))
|
if (bgp_update_prefix(c, bgp_get_prefix(c->ptx, n, path, c->add_path_tx), buck))
|
||||||
bgp_schedule_packet(p->conn, c, PKT_UPDATE);
|
bgp_schedule_packet(p->conn, c, PKT_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,10 +787,8 @@ bgp_handle_graceful_restart(struct bgp_proto *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reset bucket and prefix tables */
|
/* Reset bucket and prefix tables */
|
||||||
bgp_free_bucket_table(c);
|
bgp_free_pending_tx(c);
|
||||||
bgp_free_prefix_table(c);
|
bgp_init_pending_tx(c);
|
||||||
bgp_init_bucket_table(c);
|
|
||||||
bgp_init_prefix_table(c);
|
|
||||||
c->packets_to_send = 0;
|
c->packets_to_send = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1800,8 +1798,7 @@ bgp_channel_start(struct channel *C)
|
|||||||
if (c->cf->export_table)
|
if (c->cf->export_table)
|
||||||
bgp_setup_out_table(c);
|
bgp_setup_out_table(c);
|
||||||
|
|
||||||
bgp_init_bucket_table(c);
|
bgp_init_pending_tx(c);
|
||||||
bgp_init_prefix_table(c);
|
|
||||||
|
|
||||||
c->stale_timer = tm_new_init(c->pool, bgp_long_lived_stale_timeout, c, 0, 0);
|
c->stale_timer = tm_new_init(c->pool, bgp_long_lived_stale_timeout, c, 0, 0);
|
||||||
|
|
||||||
|
@ -351,14 +351,8 @@ struct bgp_channel {
|
|||||||
|
|
||||||
/* Rest are zeroed when down */
|
/* Rest are zeroed when down */
|
||||||
pool *pool;
|
pool *pool;
|
||||||
HASH(struct bgp_bucket) bucket_hash; /* Hash table of route buckets */
|
struct bgp_pending_tx *ptx; /* Routes waiting to be sent */
|
||||||
struct bgp_bucket *withdraw_bucket; /* Withdrawn routes */
|
struct rt_exporter prefix_exporter; /* Table-like exporter for ptx */
|
||||||
list bucket_queue; /* Queue of buckets to send (struct bgp_bucket) */
|
|
||||||
|
|
||||||
HASH(struct bgp_prefix) prefix_hash; /* Prefixes to be sent */
|
|
||||||
slab *prefix_slab; /* Slab holding prefix nodes */
|
|
||||||
|
|
||||||
struct rt_exporter prefix_exporter; /* Table-like exporter for prefix_hash */
|
|
||||||
|
|
||||||
ip_addr next_hop_addr; /* Local address for NEXT_HOP attribute */
|
ip_addr next_hop_addr; /* Local address for NEXT_HOP attribute */
|
||||||
ip_addr link_addr; /* Link-local version of next_hop_addr */
|
ip_addr link_addr; /* Link-local version of next_hop_addr */
|
||||||
@ -401,6 +395,18 @@ struct bgp_bucket {
|
|||||||
ea_list eattrs[0]; /* Per-bucket extended attributes */
|
ea_list eattrs[0]; /* Per-bucket extended attributes */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bgp_pending_tx {
|
||||||
|
resource r;
|
||||||
|
pool *pool;
|
||||||
|
|
||||||
|
HASH(struct bgp_bucket) bucket_hash; /* Hash table of route buckets */
|
||||||
|
struct bgp_bucket *withdraw_bucket; /* Withdrawn routes */
|
||||||
|
list bucket_queue; /* Queue of buckets to send (struct bgp_bucket) */
|
||||||
|
|
||||||
|
HASH(struct bgp_prefix) prefix_hash; /* Prefixes to be sent */
|
||||||
|
slab *prefix_slab; /* Slab holding prefix nodes */
|
||||||
|
};
|
||||||
|
|
||||||
struct bgp_export_state {
|
struct bgp_export_state {
|
||||||
struct bgp_proto *proto;
|
struct bgp_proto *proto;
|
||||||
struct bgp_channel *channel;
|
struct bgp_channel *channel;
|
||||||
@ -566,13 +572,12 @@ void bgp_finish_attrs(struct bgp_parse_state *s, ea_list **to);
|
|||||||
|
|
||||||
void bgp_setup_out_table(struct bgp_channel *c);
|
void bgp_setup_out_table(struct bgp_channel *c);
|
||||||
|
|
||||||
void bgp_init_bucket_table(struct bgp_channel *c);
|
void bgp_init_pending_tx(struct bgp_channel *c);
|
||||||
void bgp_free_bucket_table(struct bgp_channel *c);
|
void bgp_free_pending_tx(struct bgp_channel *c);
|
||||||
|
|
||||||
void bgp_withdraw_bucket(struct bgp_channel *c, struct bgp_bucket *b);
|
void bgp_withdraw_bucket(struct bgp_channel *c, struct bgp_bucket *b);
|
||||||
int bgp_done_bucket(struct bgp_channel *c, struct bgp_bucket *b);
|
int bgp_done_bucket(struct bgp_channel *c, struct bgp_bucket *b);
|
||||||
|
|
||||||
void bgp_init_prefix_table(struct bgp_channel *c);
|
|
||||||
void bgp_free_prefix_table(struct bgp_channel *c);
|
|
||||||
void bgp_done_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket *buck);
|
void bgp_done_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bucket *buck);
|
||||||
|
|
||||||
int bgp_rte_better(struct rte *, struct rte *);
|
int bgp_rte_better(struct rte *, struct rte *);
|
||||||
|
@ -2167,7 +2167,7 @@ bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
|
|||||||
* var IPv4 Network Layer Reachability Information
|
* var IPv4 Network Layer Reachability Information
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ASSERT_DIE(s->channel->withdraw_bucket != buck);
|
ASSERT_DIE(s->channel->ptx->withdraw_bucket != buck);
|
||||||
|
|
||||||
int lr, la;
|
int lr, la;
|
||||||
|
|
||||||
@ -2190,7 +2190,7 @@ bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
|
|||||||
static byte *
|
static byte *
|
||||||
bgp_create_mp_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
|
bgp_create_mp_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
|
||||||
{
|
{
|
||||||
ASSERT_DIE(s->channel->withdraw_bucket != buck);
|
ASSERT_DIE(s->channel->ptx->withdraw_bucket != buck);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2 B IPv4 Withdrawn Routes Length (zero)
|
* 2 B IPv4 Withdrawn Routes Length (zero)
|
||||||
@ -2330,7 +2330,7 @@ again: ;
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Try unreachable bucket */
|
/* Try unreachable bucket */
|
||||||
if ((buck = c->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
|
if ((buck = c->ptx->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
|
||||||
{
|
{
|
||||||
res = (c->afi == BGP_AF_IPV4) && !c->ext_next_hop ?
|
res = (c->afi == BGP_AF_IPV4) && !c->ext_next_hop ?
|
||||||
bgp_create_ip_unreach(&s, buck, buf, end):
|
bgp_create_ip_unreach(&s, buck, buf, end):
|
||||||
@ -2340,9 +2340,9 @@ again: ;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try reachable buckets */
|
/* Try reachable buckets */
|
||||||
if (!EMPTY_LIST(c->bucket_queue))
|
if (!EMPTY_LIST(c->ptx->bucket_queue))
|
||||||
{
|
{
|
||||||
buck = HEAD(c->bucket_queue);
|
buck = HEAD(c->ptx->bucket_queue);
|
||||||
|
|
||||||
/* Cleanup empty buckets */
|
/* Cleanup empty buckets */
|
||||||
if (bgp_done_bucket(c, buck))
|
if (bgp_done_bucket(c, buck))
|
||||||
|
Loading…
Reference in New Issue
Block a user