BGP_TIMER_OFF(peer->t_routeadv);
peer->synctime = bgp_clock();
- thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets,
- peer, 0,
- &peer->t_generate_updgrp_packets);
+ /* If suppress fib pending is enabled, route is advertised to
+ * peers when the status is received from the FIB. The delay
+ * is added to update group packet generate which will allow
+ * more routes to be sent in the update message
+ */
+ BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
+ bgp_generate_updgrp_packets);
return;
}
thread_cancel_event(bm->master, (P)); \
} while (0)
+#define BGP_UPDATE_GROUP_TIMER_ON(T, F) \
+ do { \
+ if (BGP_SUPPRESS_FIB_ENABLED(peer->bgp) && \
+ PEER_ROUTE_ADV_DELAY(peer)) \
+ thread_add_timer_msec(bm->master, (F), peer, \
+ (BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME * 1000),\
+ T); \
+ else \
+ thread_add_timer_msec(bm->master, (F), peer, \
+ 0, T); \
+ } while (0) \
+
#define BGP_MSEC_JITTER 10
/* Status codes for bgp_event_update() */
fatal = true;
}
+ /* If suppress fib pending is enabled, route is advertised to peers when
+ * the status is received from the FIB. The delay is added
+ * to update group packet generate which will allow more routes to be
+ * sent in the update message
+ */
if (reschedule) {
thread_add_write(fpt->master, bgp_process_writes, peer,
peer->fd, &peer->t_write);
} else if (!fatal) {
- BGP_TIMER_ON(peer->t_generate_updgrp_packets,
- bgp_generate_updgrp_packets, 0);
+ BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
+ bgp_generate_updgrp_packets);
}
return 0;
struct attr attr;
afi_t afi;
safi_t safi;
+ struct bgp *bgp;
+ bool advertise;
p = bgp_dest_get_prefix(dest);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
+ bgp = SUBGRP_INST(subgrp);
onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
: NULL);
memset(&attr, 0, sizeof(struct attr));
/* It's initialized in bgp_announce_check() */
- /* Announcement to the subgroup. If the route is filtered withdraw it.
+ /* Announcement to the subgroup. If the route is filtered withdraw it.
+ * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
+ * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
+ * route
*/
+ advertise = bgp_check_advertise(bgp, dest);
+
if (selected) {
if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
- false))
- bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
- else
+ false)) {
+ /* Route is selected, if the route is already installed
+ * in FIB, then it is advertised
+ */
+ if (advertise)
+ bgp_adj_out_set_subgroup(dest, subgrp, &attr,
+ selected);
+ } else
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
addpath_tx_id);
}
else
has_valid_label = bgp_is_valid_label(label);
+ /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
+ * condition :
+ * Suppress fib is enabled
+ * BGP_OPT_NO_FIB is not enabled
+ * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
+ * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
+ */
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
+ (sub_type == BGP_ROUTE_NORMAL) &&
+ (!bgp_option_check(BGP_OPT_NO_FIB)) &&
+ (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
if (!soft_reconfig
if (dest_p->prefixlen <= p->prefixlen)
continue;
+ /* If suppress fib is enabled and route not installed
+ * in FIB, skip the route
+ */
+ if (!bgp_check_advertise(bgp, dest))
+ continue;
+
match = 0;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
return;
+ /* If suppress fib is enabled and route not installed
+ * in FIB, do not update the aggregate route
+ */
+ if (!bgp_check_advertise(bgp, pi->net))
+ return;
+
child = bgp_node_get(table, p);
/* Aggregate address configuration check. */
}
}
+static inline bool bgp_check_advertise(struct bgp *bgp, struct bgp_dest *dest)
+{
+ return (!(BGP_SUPPRESS_FIB_ENABLED(bgp) &&
+ CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING) &&
+ (!bgp_option_check(BGP_OPT_NO_FIB))));
+}
+
/* called before bgp_process() */
DECLARE_HOOK(bgp_process,
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
#define BGP_NODE_LABEL_CHANGED (1 << 2)
#define BGP_NODE_REGISTERED_FOR_LABEL (1 << 3)
#define BGP_NODE_SELECT_DEFER (1 << 4)
+#define BGP_NODE_FIB_INSTALL_PENDING (1 << 5)
+#define BGP_NODE_FIB_INSTALLED (1 << 6)
struct bgp_addpath_node_data tx_addpath;
static int subgroup_coalesce_timer(struct thread *thread)
{
struct update_subgroup *subgrp;
+ struct bgp *bgp;
subgrp = THREAD_ARG(thread);
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
subgrp->v_coalesce);
subgrp->t_coalesce = NULL;
subgrp->v_coalesce = 0;
+ bgp = SUBGRP_INST(subgrp);
subgroup_announce_route(subgrp);
* to
* announce, this is the method currently employed to trigger the EOR.
*/
- if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) {
+ if (!bgp_update_delay_active(SUBGRP_INST(subgrp)) &&
+ !(BGP_SUPPRESS_FIB_ENABLED(bgp))) {
struct peer_af *paf;
struct peer *peer;
struct peer *peer;
afi_t afi;
safi_t safi;
+ struct peer *adv_peer;
+ struct peer_af *paf;
+ struct bgp *bgp;
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
+ bgp = SUBGRP_INST(subgrp);
if (DISABLE_BGP_ANNOUNCE)
return;
* mrai timers so the socket writes can happen.
*/
if (!bgp_adv_fifo_count(&subgrp->sync->update)) {
- struct peer_af *paf;
-
SUBGRP_FOREACH_PEER (subgrp, paf) {
+ /* If there are no routes in the withdraw list, set
+ * the flag PEER_STATUS_ADV_DELAY which will allow
+ * more routes to be sent in the update message
+ */
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp)) {
+ adv_peer = PAF_PEER(paf);
+ if (!bgp_adv_fifo_count(
+ &subgrp->sync->withdraw))
+ SET_FLAG(adv_peer->thread_flags,
+ PEER_THREAD_SUBGRP_ADV_DELAY);
+ else
+ UNSET_FLAG(adv_peer->thread_flags,
+ PEER_THREAD_SUBGRP_ADV_DELAY);
+ }
bgp_adjust_routeadv(PAF_PEER(paf));
}
}
afi_t afi;
safi_t safi;
int addpath_capable;
+ struct bgp *bgp;
+ bool advertise;
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
+ bgp = SUBGRP_INST(subgrp);
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
if (safi == SAFI_LABELED_UNICAST)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+ /* Check if the route can be advertised */
+ advertise = bgp_check_advertise(bgp, dest);
+
for (ri = bgp_dest_get_bgp_path_info(dest); ri; ri = ri->next)
if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)
ri))) {
if (subgroup_announce_check(dest, ri, subgrp,
dest_p, &attr,
- false))
- bgp_adj_out_set_subgroup(dest, subgrp,
- &attr, ri);
- else {
+ false)) {
+ /* Check if route can be advertised */
+ if (advertise)
+ bgp_adj_out_set_subgroup(dest,
+ subgrp,
+ &attr,
+ ri);
+ } else {
/* If default originate is enabled for
* the peer, do not send explicit
* withdraw. This will prevent deletion
struct updwalk_context ctx;
ctx.pi = pi;
ctx.dest = dest;
+
+ /* If suppress fib is enabled, the route will be advertised when
+ * FIB status is received
+ */
+ if (!bgp_check_advertise(bgp, dest))
+ return;
+
update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);
}
return 0;
}
+/* Process route notification messages from RIB */
+static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct prefix p;
+ enum zapi_route_notify_owner note;
+ uint32_t table_id;
+ char buf[PREFIX_STRLEN];
+ afi_t afi;
+ safi_t safi;
+ struct bgp_dest *dest;
+ struct bgp *bgp;
+ struct bgp_path_info *pi, *new_select;
+
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e,
+ &afi, &safi)) {
+ zlog_err("%s : error in msg decode", __PRETTY_FUNCTION__);
+ return -1;
+ }
+
+ /* Get the bgp instance */
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp) {
+ flog_err(EC_BGP_INVALID_BGP_INSTANCE,
+ "%s : bgp instance not found vrf %d",
+ __PRETTY_FUNCTION__, vrf_id);
+ return -1;
+ }
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ prefix2str(&p, buf, sizeof(buf));
+
+ /* Find the bgp route node */
+ dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p,
+ &bgp->vrf_prd);
+ if (!dest)
+ return -1;
+
+ bgp_dest_unlock_node(dest);
+
+ switch (note) {
+ case ZAPI_ROUTE_INSTALLED:
+ new_select = NULL;
+ /* Clear the flags so that route can be processed */
+ if (CHECK_FLAG(dest->flags,
+ BGP_NODE_FIB_INSTALL_PENDING)) {
+ UNSET_FLAG(dest->flags,
+ BGP_NODE_FIB_INSTALL_PENDING);
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("route %s : INSTALLED", buf);
+ /* Find the best route */
+ for (pi = dest->info; pi; pi = pi->next) {
+ /* Process aggregate route */
+ bgp_aggregate_increment(bgp, &p, pi,
+ afi, safi);
+ if (CHECK_FLAG(pi->flags,
+ BGP_PATH_SELECTED))
+ new_select = pi;
+ }
+ /* Advertise the route */
+ if (new_select)
+ group_announce_route(bgp, afi, safi,
+ dest, new_select);
+ else {
+ flog_err(EC_BGP_INVALID_ROUTE,
+ "selected route %s not found",
+ buf);
+ return -1;
+ }
+ }
+ break;
+ case ZAPI_ROUTE_REMOVED:
+ /* Route deleted from dataplane, reset the installed flag
+ * so that route can be reinstalled when client sends
+ * route add later
+ */
+ UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
+ break;
+ case ZAPI_ROUTE_FAIL_INSTALL:
+ /* Error will be logged by zebra module */
+ break;
+ case ZAPI_ROUTE_BETTER_ADMIN_WON:
+ /* No action required */
+ break;
+ case ZAPI_ROUTE_REMOVE_FAIL:
+ zlog_warn("%s: Route %s failure to remove",
+ __func__, buf);
+ break;
+ }
+ return 0;
+}
+
/* this function is used to forge ip rule,
* - either for iptable/ipset using fwmark id
* - or for sample ip rule cmd
zclient->ipset_notify_owner = ipset_notify_owner;
zclient->ipset_entry_notify_owner = ipset_entry_notify_owner;
zclient->iptable_notify_owner = iptable_notify_owner;
+ zclient->route_notify_owner = bgp_zebra_route_notify_owner;
zclient->instance = instance;
}
#define PEER_THREAD_WRITES_ON (1U << 0)
#define PEER_THREAD_READS_ON (1U << 1)
#define PEER_THREAD_KEEPALIVES_ON (1U << 2)
+#define PEER_THREAD_SUBGRP_ADV_DELAY (1U << 3)
+
/* workqueues */
struct work_queue *clear_node_queue;
|| CHECK_FLAG((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW) \
|| CHECK_FLAG((P)->bgp->flags, BGP_FLAG_SHUTDOWN))
-#define PEER_ROUTE_ADV_DELAY(peer) \
- CHECK_FLAG(peer->thread_flags, PEER_THREAD_SUBGRP_ADV_DELAY)
+#define PEER_ROUTE_ADV_DELAY(peer) \
+ (CHECK_FLAG(peer->thread_flags, PEER_THREAD_SUBGRP_ADV_DELAY))
#define PEER_PASSWORD_MINLEN (1)
#define PEER_PASSWORD_MAXLEN (80)