Exemplo n.º 1
0
/* 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;
}
Exemplo n.º 2
0
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);
    }
}