bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len);
+ p->p.reload_routes = NULL;
+
struct bgp_channel *c;
BGP_WALK_CHANNELS(p, c)
bgp_free_pending_tx(c);
int active = loc->ready && rem->ready;
c->c.disabled = !active;
- c->c.reloadable = p->route_refresh || ((c->c.in_keep & RIK_PREFILTER) == RIK_PREFILTER);
+ c->c.reloadable = p->route_refresh;
c->index = active ? num++ : 0;
cli_msg(-8006, "%s: not reloading, not up", P->name);
}
+struct bgp_enhanced_refresh_request {
+ struct rt_feeding_request rfr;
+ struct bgp_channel *c;
+};
+
+static void
+bgp_done_route_refresh(struct rt_feeding_request *rfr)
+{
+ SKIP_BACK_DECLARE(struct bgp_enhanced_refresh_request, berr, rfr, rfr);
+ struct bgp_channel *c = berr->c;
+ SKIP_BACK_DECLARE(struct bgp_proto, p, p, c->c.proto);
+
+ /* Schedule EoRR packet */
+ ASSERT_DIE(c->feed_state == BFS_REFRESHING);
+
+ c->feed_state = BFS_REFRESHED;
+ bgp_schedule_packet(p->conn, c, PKT_UPDATE);
+
+ mb_free(berr);
+}
+
+const char *
+bgp_begin_route_refresh(struct bgp_proto *p, struct bgp_channel *c)
+{
+ if (c->tx_keep)
+ return bgp_tx_resend(p, c);
+
+ if (!p->enhanced_refresh) {
+ rt_export_refeed(&c->c.out_req, NULL);
+ return "from table by simple refeed";
+ }
+
+ struct bgp_enhanced_refresh_request *berr = mb_alloc(p->p.pool, sizeof *berr);
+ *berr = (struct bgp_enhanced_refresh_request) {
+ .c = c,
+ .rfr.done = bgp_done_route_refresh,
+ };
+
+ c->feed_state = BFS_REFRESHING;
+ bgp_schedule_packet(p->conn, c, PKT_BEGIN_REFRESH);
+
+ rt_export_refeed(&c->c.out_req, &berr->rfr);
+ return "from table by enhanced route refresh";
+}
+
void
bgp_reload_out(struct proto *P, uintptr_t _ UNUSED, int __ UNUSED)
{
struct bgp_channel *c;
BGP_WALK_CHANNELS(p, c)
if (&c->c != P->mpls_channel)
- if (c->tx_keep)
- {
- bgp_tx_resend(p, c);
- cli_msg(-15, "%s.%s: reloading", P->name, c->c.name);
- }
- else
- {
- rt_export_refeed(&c->c.out_req, NULL);
- cli_msg(-15, "%s.%s: reloading by table refeed", P->name, c->c.name);
- }
+ {
+ const char *info = bgp_begin_route_refresh(p, c);
+ cli_msg(-15, "%s.%s: reloading %s", P->name, c->c.name, info);
+ }
}
else
cli_msg(-8006, "%s: not reloading, not up", P->name);
}
-struct bgp_enhanced_refresh_request {
- struct rt_feeding_request rfr;
- struct bgp_channel *c;
-};
-
-void
-bgp_done_route_refresh(struct rt_feeding_request *rfr)
+static int
+bgp_reload_routes(struct channel *C, struct rt_feeding_request *rfr)
{
- SKIP_BACK_DECLARE(struct bgp_enhanced_refresh_request, berr, rfr, rfr);
- struct bgp_channel *c = berr->c;
- SKIP_BACK_DECLARE(struct bgp_proto, p, p, c->c.proto);
+ /* Can't reload partially */
+ if (rfr && rfr->prefilter.mode)
+ return 0;
- /* Schedule EoRR packet */
- ASSERT_DIE(c->feed_state == BFS_REFRESHING);
+ struct bgp_proto *p = SKIP_BACK(struct bgp_proto, p, C->proto);
- c->feed_state = BFS_REFRESHED;
- bgp_schedule_packet(p->conn, c, PKT_UPDATE);
+ if (p->p.proto_state == PS_UP)
+ {
+ struct bgp_channel *c;
+ BGP_WALK_CHANNELS(p, c)
+ if (&c->c != p->p.mpls_channel)
+ {
+ log("%s.%s: reloading", p->p.name, c->c.name);
+ bgp_schedule_packet(p->conn, c, PKT_ROUTE_REFRESH);
+ }
+ }
+ else
+ log("%s: not reloading, not up", p->p.name);
- mb_free(berr);
+ if (rfr)
+ CALL(rfr->done, rfr);
+
+ return 1;
+}
+
+static void
+bgp_refeed_begin(struct channel *C, struct rt_feeding_request *rfr)
+{
+ struct bgp_channel *c = SKIP_BACK(struct bgp_channel, c, C);
+ struct bgp_proto *p = SKIP_BACK(struct bgp_proto, p, C->proto);
+
+ /* Do not announce partial refeed */
+ if (rfr && rfr->prefilter.mode)
+ return;
+
+ /* Run the enhanced refresh if available */
+ if (p->enhanced_refresh && !c->tx_keep)
+ {
+ c->feed_state = BFS_REFRESHING;
+ bgp_schedule_packet(p->conn, c, PKT_BEGIN_REFRESH);
+ }
}
static void
SKIP_BACK_DECLARE(struct bgp_proto, p, p, c->c.proto);
/* Schedule End-of-RIB packet */
- if (c->feed_state == BFS_LOADING)
+ switch (c->feed_state)
{
- c->feed_state = BFS_LOADED;
- bgp_schedule_packet(p->conn, c, PKT_UPDATE);
+ case BFS_LOADING:
+ c->feed_state = BFS_LOADED;
+ bgp_schedule_packet(p->conn, c, PKT_UPDATE);
+ break;
+
+ case BFS_REFRESHING:
+ c->feed_state = BFS_REFRESHED;
+ bgp_schedule_packet(p->conn, c, PKT_UPDATE);
+ break;
}
}
P->rt_notify = bgp_rt_notify;
P->preexport = bgp_preexport;
P->iface_sub.neigh_notify = bgp_neigh_notify;
+ P->refeed_begin = bgp_refeed_begin;
P->export_fed = bgp_export_fed;
+ P->reload_routes = bgp_reload_routes;
P->sources.class = &bgp_rte_owner_class;
P->sources.rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL;