/* A route becomes unreachable (RFC2439 Section 4.8.2). */ int bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, safi_t safi, int attr_change) { time_t t_now; struct bgp_damp_info *bdi = NULL; double last_penalty = 0; t_now = bgp_clock (); /* Processing Unreachable Messages. */ if (binfo->extra) bdi = binfo->extra->damp_info; if (bdi == NULL) { /* If there is no previous stability history. */ /* RFC2439 said: 1. allocate a damping structure. 2. set figure-of-merit = 1. 3. withdraw the route. */ bdi = XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info)); bdi->binfo = binfo; bdi->rn = rn; bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY); bdi->flap = 1; bdi->start_time = t_now; bdi->suppress_time = 0; bdi->index = -1; bdi->afi = afi; bdi->safi = safi; (bgp_info_extra_get (binfo))->damp_info = bdi; BGP_DAMP_LIST_ADD (damp, bdi); } else { last_penalty = bdi->penalty; /* 1. Set t-diff = t-now - t-updated. */ bdi->penalty = (bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty) + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY)); if (bdi->penalty > damp->ceiling) bdi->penalty = damp->ceiling; bdi->flap++; } assert ((rn == bdi->rn) && (binfo == bdi->binfo)); bdi->lastrecord = BGP_RECORD_WITHDRAW; bdi->t_updated = t_now; /* Make this route as historical status. */ bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY); /* Remove the route from a reuse list if it is on one. */ if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)) { /* If decay rate isn't equal to 0, reinsert brn. */ if (bdi->penalty != last_penalty) { bgp_reuse_list_delete (bdi); bgp_reuse_list_add (bdi); } return BGP_DAMP_SUPPRESSED; } /* If not suppressed before, do annonunce this withdraw and insert into reuse_list. */ if (bdi->penalty >= damp->suppress_value) { bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED); bdi->suppress_time = t_now; BGP_DAMP_LIST_DEL (damp, bdi); bgp_reuse_list_add (bdi); } return BGP_DAMP_USED; }
static void bgp_scan (afi_t afi, safi_t safi) { struct bgp_node *rn; struct bgp *bgp; struct bgp_info *bi; struct bgp_info *next; struct peer *peer; struct listnode *node, *nnode; int valid; int current; int changed; int metricchanged; /* Change cache. */ if (bgp_nexthop_cache_table[afi] == cache1_table[afi]) bgp_nexthop_cache_table[afi] = cache2_table[afi]; else bgp_nexthop_cache_table[afi] = cache1_table[afi]; /* Get default bgp. */ bgp = bgp_get_default (); if (bgp == NULL) return; /* Maximum prefix check */ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { if (peer->status != Established) continue; if (peer->afc[afi][SAFI_UNICAST]) bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1); if (peer->afc[afi][SAFI_MULTICAST]) bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1); if (peer->afc[afi][SAFI_MPLS_VPN]) bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1); } for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next (rn)) { for (bi = rn->info; bi; bi = next) { next = bi->next; if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL) { changed = 0; metricchanged = 0; if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1) valid = bgp_nexthop_onlink (afi, bi->attr); else valid = bgp_nexthop_lookup (afi, bi->peer, bi, &changed, &metricchanged); current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0; if (changed) SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED); else UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED); if (valid != current) { if (CHECK_FLAG (bi->flags, BGP_INFO_VALID)) { bgp_aggregate_decrement (bgp, &rn->p, bi, afi, SAFI_UNICAST); bgp_info_unset_flag (rn, bi, BGP_INFO_VALID); } else { bgp_info_set_flag (rn, bi, BGP_INFO_VALID); bgp_aggregate_increment (bgp, &rn->p, bi, afi, SAFI_UNICAST); } } if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST], BGP_CONFIG_DAMPENING) && bi->extra && bi->extra->damp_info ) if (bgp_damp_scan (bi, afi, SAFI_UNICAST)) bgp_aggregate_increment (bgp, &rn->p, bi, afi, SAFI_UNICAST); } } bgp_process (bgp, rn, afi, SAFI_UNICAST); } /* Flash old cache. */ if (bgp_nexthop_cache_table[afi] == cache1_table[afi]) bgp_nexthop_cache_reset (cache2_table[afi]); else bgp_nexthop_cache_reset (cache1_table[afi]); if (BGP_DEBUG (events, EVENTS)) { if (afi == AFI_IP) zlog_debug ("scanning IPv4 Unicast routing tables"); else if (afi == AFI_IP6) zlog_debug ("scanning IPv6 Unicast routing tables"); } /* Reevaluate default-originate route-maps and announce/withdraw * default route if neccesary. */ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { if (peer->status == Established && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) && peer->default_rmap[afi][safi].name) bgp_default_originate (peer, afi, safi, 0); } }