c->channel = cf->channel;
c->proto = p;
c->table = cf->table->table;
+ rt_lock_table(c->table);
c->in_filter = cf->in_filter;
c->out_filter = cf->out_filter;
CD(c, "Removed", c->name);
+ rt_unlock_table(c->table);
rem_node(&c->n);
mb_free(c);
}
static void
channel_do_start(struct channel *c)
{
- rt_lock_table(c->table);
add_tail(&c->table->channels, &c->table_node);
c->proto->active_channels++;
ASSERT(!c->feed_active && !c->reload_active);
rem_node(&c->table_node);
- rt_unlock_table(c->table);
c->proto->active_channels--;
if ((c->stats.imp_routes + c->stats.filt_routes) != 0)
*
* CS_DOWN - The initial and the final state of a channel. There is no route
* exchange between the protocol and the table. Channel is not counted as
- * active. Channel keeps a ptr to the table, but do not lock the table and is
+ * active. Channel keeps a ptr to the table, keeps the table locked, but is
* not linked in the table. Generally, new closed channels are created in
* protocols' init() hooks. The protocol is expected to explicitly activate its
* channels (by calling channel_init() or channel_open()).
* channel. The channel is still initialized, but no route exchange is allowed.
* Instead, the associated table is running flush loop to remove routes imported
* through the channel. After that, the channel changes state to CS_DOWN and
- * is detached from the table (the table is unlocked and the channel is unlinked
- * from it). Unlike other states, the CS_FLUSHING state is not explicitly
+ * is detached from the table (the channel is unlinked from it, but keeps the
+ * table locked). Unlike other states, the CS_FLUSHING state is not explicitly
* entered or left by the protocol. A protocol may request to close a channel
* (by calling channel_close()), which causes the channel to change state to
* CS_FLUSHING and later to CS_DOWN. Also note that channels are closed
cli_msg(-1006, " BGP Next hop: %I %I", c->next_hop_addr, c->link_addr);
}
- if (c->igp_table_ip4)
- cli_msg(-1006, " IGP IPv4 table: %s", c->igp_table_ip4->name);
+ /* After channel is deconfigured, these pointers are no longer valid */
+ if (!p->p.reconfiguring || (c->c.channel_state != CS_DOWN))
+ {
+ if (c->igp_table_ip4)
+ cli_msg(-1006, " IGP IPv4 table: %s", c->igp_table_ip4->name);
- if (c->igp_table_ip6)
- cli_msg(-1006, " IGP IPv6 table: %s", c->igp_table_ip6->name);
+ if (c->igp_table_ip6)
+ cli_msg(-1006, " IGP IPv6 table: %s", c->igp_table_ip6->name);
- if (c->base_table)
- cli_msg(-1006, " Base table: %s", c->base_table->name);
+ if (c->base_table)
+ cli_msg(-1006, " Base table: %s", c->base_table->name);
+ }
}
}
}