Example #1
0
const char *
bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
                         char *timebuf, size_t len)
{
  struct bgp_damp_info *bdi;
  time_t t_now, t_diff;
  int penalty;
  
  if (!binfo->extra)
    return NULL;
  
  /* BGP dampening information.  */
  bdi = binfo->extra->damp_info;

  /* If dampening is not enabled or there is no dampening information,
     return immediately.  */
  if (! damp || ! bdi)
    return NULL;

  /* Calculate new penalty.  */
  t_now = bgp_clock ();
  t_diff = t_now - bdi->t_updated;
  penalty = bgp_damp_decay (t_diff, bdi->penalty);

  return  bgp_get_reuse_time (penalty, timebuf, len);
}
Example #2
0
void
bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)  
{
  struct bgp_damp_info *bdi;
  time_t t_now, t_diff;
  char timebuf[BGP_UPTIME_LEN];
  int penalty;

  if (!binfo->extra)
    return;
  
  /* BGP dampening information.  */
  bdi = binfo->extra->damp_info;

  /* If dampening is not enabled or there is no dampening information,
     return immediately.  */
  if (! damp || ! bdi)
    return;

  /* Calculate new penalty.  */
  t_now = bgp_clock ();
  t_diff = t_now - bdi->t_updated;
  penalty = bgp_damp_decay (t_diff, bdi->penalty);

  vty_out (vty, "      Dampinfo: penalty %d, flapped %d times in %s",
           penalty, bdi->flap,
	   peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));

  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
      && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
    vty_out (vty, ", reuse in %s",
	     bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));

  vty_out (vty, "%s", VTY_NEWLINE);
}
Example #3
0
/* Remove dampening information and history route.  */
int 
bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
{
  time_t t_now, t_diff;
  struct bgp_damp_info *bdi;
  
  assert (binfo->extra && binfo->extra->damp_info);
  
  t_now = bgp_clock ();
  bdi = binfo->extra->damp_info;
 
  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
    {
      t_diff = t_now - bdi->suppress_time;

      if (t_diff >= damp->max_suppress_time)
        {
          bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED);
          bgp_reuse_list_delete (bdi);
	  BGP_DAMP_LIST_ADD (damp, bdi);
          bdi->penalty = damp->reuse_limit;
          bdi->suppress_time = 0;
          bdi->t_updated = t_now;
          
          /* Need to announce UPDATE once this binfo is usable again. */
          if (bdi->lastrecord == BGP_RECORD_UPDATE)
            return 1;
          else
            return 0;
        }
    }
  else
    {
      t_diff = t_now - bdi->t_updated;
      bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);

      if (bdi->penalty <= damp->reuse_limit / 2.0)
        {
          /* release the bdi, bdi->binfo. */  
          bgp_damp_info_free (bdi, 1);
          return 0;
        }            
      else
        bdi->t_updated = t_now;
    }       
  return 0;
}
Example #4
0
static int
bgp_routeadv_timer (struct thread *thread)
{
  struct peer *peer;

  peer = THREAD_ARG (thread);
  peer->t_routeadv = NULL;

  if (BGP_DEBUG (fsm, FSM))
    zlog (peer->log, LOG_DEBUG,
	  "%s [FSM] Timer (routeadv timer expire)",
	  peer->host);

  peer->synctime = bgp_clock ();

  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);

  BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
		peer->v_routeadv);

  return 0;
}
Example #5
0
int
bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, 
		 afi_t afi, safi_t safi)
{
  time_t t_now;
  struct bgp_damp_info *bdi;
  int status;

  if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
    return BGP_DAMP_USED;

  t_now = bgp_clock ();
  bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);

  bdi->lastrecord = BGP_RECORD_UPDATE;
  bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);

  if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
      && (bdi->penalty < damp->suppress_value))
    status = BGP_DAMP_USED;
  else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
	   && (bdi->penalty < damp->reuse_limit) )
    {
      bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED);
      bgp_reuse_list_delete (bdi);
      BGP_DAMP_LIST_ADD (damp, bdi);
      bdi->suppress_time = 0;
      status = BGP_DAMP_USED;
    }
  else
    status = BGP_DAMP_SUPPRESSED;  

  if (bdi->penalty > damp->reuse_limit / 2.0)
    bdi->t_updated = t_now;
  else
    bgp_damp_info_free (bdi, 0);
	
  return status;
}
Example #6
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;
}
Example #7
0
/* Handler of reuse timer event.  Each route in the current reuse-list
   is evaluated.  RFC2439 Section 4.8.7.  */
static int
bgp_reuse_timer (struct thread *t)
{
  struct bgp_damp_info *bdi;
  struct bgp_damp_info *next;
  time_t t_now, t_diff;
    
  damp->t_reuse = NULL;
  damp->t_reuse =
    thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);

  t_now = bgp_clock ();

  /* 1.  save a pointer to the current zeroth queue head and zero the
     list head entry.  */
  bdi = damp->reuse_list[damp->reuse_offset];
  damp->reuse_list[damp->reuse_offset] = NULL;

  /* 2.  set offset = modulo reuse-list-size ( offset + 1 ), thereby
     rotating the circular queue of list-heads.  */
  damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;

  /* 3. if ( the saved list head pointer is non-empty ) */
  for (; bdi; bdi = next)
    {
      struct bgp *bgp = bdi->binfo->peer->bgp;
      
      next = bdi->next;

      /* Set t-diff = t-now - t-updated.  */
      t_diff = t_now - bdi->t_updated;

      /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
      bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);   

      /* Set t-updated = t-now.  */
      bdi->t_updated = t_now;

      /* if (figure-of-merit < reuse).  */
      if (bdi->penalty < damp->reuse_limit)
	{
	  /* Reuse the route.  */
	  bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED);
	  bdi->suppress_time = 0;

	  if (bdi->lastrecord == BGP_RECORD_UPDATE)
	    {
	      bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY);
	      bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
				       bdi->afi, bdi->safi);   
	      bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
	    }

	  if (bdi->penalty <= damp->reuse_limit / 2.0)
	    bgp_damp_info_free (bdi, 1);
	  else
	    BGP_DAMP_LIST_ADD (damp, bdi);
	}
      else
	/* Re-insert into another list (See RFC2439 Section 4.8.6).  */
	bgp_reuse_list_add (bdi);
    }

  return 0;
}
Example #8
0
/* Runs under child process. */
static unsigned int
bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
{
  struct stream *obuf;
  struct bgp_info *info;
  struct bgp_node *rn;
  struct bgp *bgp;
  struct bgp_table *table;

  bgp = bgp_get_default ();
  if (!bgp)
    return seq;

  if (bgp_dump_routes.fp == NULL)
    return seq;

  /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
     so this should only be done on the first call to bgp_dump_routes_func.
     ( this function will be called once for ipv4 and once for ipv6 ) */
  if(first_run)
    bgp_dump_routes_index_table(bgp);

  obuf = bgp_dump_obuf;
  stream_reset(obuf);

  /* Walk down each BGP route. */
  table = bgp->rib[afi][SAFI_UNICAST];

  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
    {
      if(!rn->info)
        continue;

      stream_reset(obuf);

      /* MRT header */
      if (afi == AFI_IP)
	bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST,
			 BGP_DUMP_ROUTES);
      else if (afi == AFI_IP6)
	bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST,
			 BGP_DUMP_ROUTES);

      /* Sequence number */
      stream_putl(obuf, seq);

      /* Prefix length */
      stream_putc (obuf, rn->p.prefixlen);

      /* Prefix */
      if (afi == AFI_IP)
        {
          /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
          stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
        }
      else if (afi == AFI_IP6)
        {
          /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
          stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
        }

      /* Save where we are now, so we can overwride the entry count later */
      int sizep = stream_get_endp(obuf);

      /* Entry count */
      uint16_t entry_count = 0;

      /* Entry count, note that this is overwritten later */
      stream_putw(obuf, 0);

      for (info = rn->info; info; info = info->next)
        {
          entry_count++;

          /* Peer index */
          stream_putw(obuf, info->peer->table_dump_index);

          /* Originated */
#ifdef HAVE_CLOCK_MONOTONIC
          stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime));
#else
          stream_putl (obuf, info->uptime);
#endif /* HAVE_CLOCK_MONOTONIC */

          /* Dump attribute. */
          /* Skip prefix & AFI/SAFI for MP_NLRI */
          bgp_dump_routes_attr (obuf, info->attr, &rn->p);
        }

      /* Overwrite the entry count, now that we know the right number */
      stream_putw_at (obuf, sizep, entry_count);

      seq++;

      bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
      fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);

    }

  fflush (bgp_dump_routes.fp);

  return seq;
}
Example #9
0
static int
show_ip_bgp_nexthop_table (struct vty *vty, int detail)
{
  struct bgp_node *rn;
  struct bgp_nexthop_cache *bnc;
  char buf[INET6_ADDRSTRLEN];
  struct nexthop *nexthop;
  time_t tbuf;
  afi_t afi;

  vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    {
      if (!bgp_nexthop_cache_table[afi])
        continue;
      
      for (rn = bgp_table_top (bgp_nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
	{
	  if ((bnc = rn->info) != NULL)
	    {
	      if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
		{
		  vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
			   inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
			   bnc->metric, bnc->path_count, VTY_NEWLINE);
		  if (detail)
		    for (nexthop = bnc->nexthop ; nexthop; nexthop = nexthop->next)
		      switch (nexthop->type)
			{
			case NEXTHOP_TYPE_IPV6:
			  vty_out (vty, "  gate %s%s",
				   inet_ntop (AF_INET6, &nexthop->gate.ipv6,
					      buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
			  break;
			case NEXTHOP_TYPE_IPV6_IFINDEX:
			  vty_out(vty, "  gate %s, if %s%s",
				  inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
					    INET6_ADDRSTRLEN),
				  ifindex2ifname(nexthop->ifindex),
				  VTY_NEWLINE);
			  break;
			case NEXTHOP_TYPE_IPV4:
			  vty_out (vty, "  gate %s%s",
				   inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
					      INET6_ADDRSTRLEN), VTY_NEWLINE);
			  break;
			case NEXTHOP_TYPE_IFINDEX:
			  vty_out (vty, "  if %s%s",
				   ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
			  break;
			case NEXTHOP_TYPE_IPV4_IFINDEX:
			  vty_out (vty, "  gate %s, if %s%s",
				   inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
					     INET6_ADDRSTRLEN),
				   ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
			  break;
			default:
			  vty_out (vty, "  invalid nexthop type %u%s",
				   nexthop->type, VTY_NEWLINE);
			}
		}
	      else
		vty_out (vty, " %s invalid%s",
			 inet_ntop (AF_INET, &rn->p.u.prefix, buf, sizeof (buf)), VTY_NEWLINE);
#ifdef HAVE_CLOCK_MONOTONIC
	      tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
	      vty_out (vty, "  Last update: %s", ctime(&tbuf));
#else
	      vty_out (vty, "  Last update: %s", ctime(&bnc->uptime));
#endif /* HAVE_CLOCK_MONOTONIC */
	      vty_out(vty, "%s", VTY_NEWLINE);
	    }
	}
    }
  return CMD_SUCCESS;
}
Example #10
0
static struct bgp_info *
bgp_dump_route_node_record (int afi, struct bgp_node *rn,
                            struct bgp_info *info, unsigned int seq)
{
  struct stream *obuf;
  size_t sizep;
  size_t endp;

  obuf = bgp_dump_obuf;
  stream_reset (obuf);

  /* MRT header */
  if (afi == AFI_IP)
    bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST,
                     BGP_DUMP_ROUTES);
  else if (afi == AFI_IP6)
    bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST,
                     BGP_DUMP_ROUTES);

  /* Sequence number */
  stream_putl (obuf, seq);

  /* Prefix length */
  stream_putc (obuf, rn->p.prefixlen);

  /* Prefix */
  if (afi == AFI_IP)
    {
      /* We'll dump only the useful bits (those not 0), but have to
       * align on 8 bits */
      stream_write (obuf, (u_char *) &rn->p.u.prefix4, 
                    (rn->p.prefixlen + 7) / 8);
    }
  else if (afi == AFI_IP6)
    {
      /* We'll dump only the useful bits (those not 0), but have to
       * align on 8 bits */
      stream_write (obuf, (u_char *) &rn->p.u.prefix6,
                    (rn->p.prefixlen + 7) / 8);
    }

  /* Save where we are now, so we can overwride the entry count later */
  sizep = stream_get_endp (obuf);

  /* Entry count */
  uint16_t entry_count = 0;

  /* Entry count, note that this is overwritten later */
  stream_putw (obuf, 0);

  endp = stream_get_endp (obuf);
  for (; info; info = info->next)
    {
      size_t cur_endp;

      /* Peer index */
      stream_putw (obuf, info->peer->table_dump_index);

      /* Originated */
#ifdef HAVE_CLOCK_MONOTONIC
      stream_putl (obuf, time (NULL) - (bgp_clock () - info->uptime));
#else
      stream_putl (obuf, info->uptime);
#endif /* HAVE_CLOCK_MONOTONIC */

      /* Dump attribute. */
      /* Skip prefix & AFI/SAFI for MP_NLRI */
      bgp_dump_routes_attr (obuf, info->attr, &rn->p);

      cur_endp = stream_get_endp (obuf);
      if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
          + BGP_DUMP_HEADER_SIZE)
        {
          stream_set_endp (obuf, endp);
          break;
        }

      entry_count++;
      endp = cur_endp;
    }

  /* Overwrite the entry count, now that we know the right number */
  stream_putw_at (obuf, sizep, entry_count);

  bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2);
  fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);

  return info;
}
Example #11
0
/* Status goes to Established.  Send keepalive packet then make first
   update information. */
static int
bgp_establish (struct peer *peer)
{
  struct bgp_notify *notify;
  afi_t afi;
  safi_t safi;
  int nsf_af_count = 0;

  /* Reset capability open status flag. */
  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
    SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);

  /* Clear last notification data. */
  notify = &peer->notify;
  if (notify->data)
    XFREE (MTYPE_TMP, notify->data);
  memset (notify, 0, sizeof (struct bgp_notify));

  /* Clear start timer value to default. */
  peer->v_start = BGP_INIT_START_TIMER;

  /* Increment established count. */
  peer->established++;
  bgp_fsm_change_status (peer, Established);

  /* bgp log-neighbor-changes of neighbor Up */
  if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
    zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);

  /* graceful restart */
  UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
      {
	if (peer->afc_nego[afi][safi]
	    && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
	    && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
	  {
	    if (peer->nsf[afi][safi]
		&& ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
	      bgp_clear_stale_route (peer, afi, safi);

	    peer->nsf[afi][safi] = 1;
	    nsf_af_count++;
	  }
	else
	  {
	    if (peer->nsf[afi][safi])
	      bgp_clear_stale_route (peer, afi, safi);
	    peer->nsf[afi][safi] = 0;
	  }
      }

  if (nsf_af_count)
    SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
  else
    {
      UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
      if (peer->t_gr_stale)
	{
	  BGP_TIMER_OFF (peer->t_gr_stale);
	  if (BGP_DEBUG (events, EVENTS))
	    zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
	}
    }

  if (peer->t_gr_restart)
    {
      BGP_TIMER_OFF (peer->t_gr_restart);
      if (BGP_DEBUG (events, EVENTS))
	zlog_debug ("%s graceful restart timer stopped", peer->host);
    }

#ifdef HAVE_SNMP
  bgpTrapEstablished (peer);
#endif /* HAVE_SNMP */

  /* Reset uptime, send keepalive, send current table. */
  peer->uptime = bgp_clock ();

  /* Send route-refresh when ORF is enabled */
  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
	{
	  if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
	    bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
				    REFRESH_IMMEDIATE, 0);
	  else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
	    bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
				    REFRESH_IMMEDIATE, 0);
	}

  if (peer->v_keepalive)
    bgp_keepalive_send (peer);

  /* First update is deferred until ORF or ROUTE-REFRESH is received */
  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
	if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
	    || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
	  SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);

  bgp_announce_route_all (peer);

  BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);

  return 0;
}
Example #12
0
/* May be called multiple times for the same peer */
int
bgp_stop (struct peer *peer)
{
  afi_t afi;
  safi_t safi;
  char orf_name[BUFSIZ];

  /* Can't do this in Clearing; events are used for state transitions */
  if (peer->status != Clearing)
    {
      /* Delete all existing events of the peer */
      BGP_EVENT_FLUSH (peer);
    }

  /* Increment Dropped count. */
  if (peer->status == Established)
    {
      peer->dropped++;

      /* bgp log-neighbor-changes of neighbor Down */
      if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
	zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
                   peer_down_str [(int) peer->last_reset]);

      /* graceful restart */
      if (peer->t_gr_stale)
	{
	  BGP_TIMER_OFF (peer->t_gr_stale);
	  if (BGP_DEBUG (events, EVENTS))
	    zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
	}
      if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
	{
	  if (BGP_DEBUG (events, EVENTS))
	    {
	      zlog_debug ("%s graceful restart timer started for %d sec",
			  peer->host, peer->v_gr_restart);
	      zlog_debug ("%s graceful restart stalepath timer started for %d sec",
			  peer->host, peer->bgp->stalepath_time);
	    }
	  BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
			peer->v_gr_restart);
	  BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
			peer->bgp->stalepath_time);
	}
      else
	{
	  UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);

	  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
	    for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
	      peer->nsf[afi][safi] = 0;
	}

      /* set last reset time */
      peer->resettime = peer->uptime = bgp_clock ();

#ifdef HAVE_SNMP
      bgpTrapBackwardTransition (peer);
#endif /* HAVE_SNMP */

      /* Reset peer synctime */
      peer->synctime = 0;
    }

  /* Stop read and write threads when exists. */
  BGP_READ_OFF (peer->t_read);
  BGP_WRITE_OFF (peer->t_write);

  /* Stop all timers. */
  BGP_TIMER_OFF (peer->t_start);
  BGP_TIMER_OFF (peer->t_connect);
  BGP_TIMER_OFF (peer->t_holdtime);
  BGP_TIMER_OFF (peer->t_keepalive);
  BGP_TIMER_OFF (peer->t_asorig);
  BGP_TIMER_OFF (peer->t_routeadv);

  /* Stream reset. */
  peer->packet_size = 0;

  /* Clear input and output buffer.  */
  if (peer->ibuf)
    stream_reset (peer->ibuf);
  if (peer->work)
    stream_reset (peer->work);
  if (peer->obuf)
    stream_fifo_clean (peer->obuf);

  /* Close of file descriptor. */
  if (peer->fd >= 0)
    {
      close (peer->fd);
      peer->fd = -1;
    }

  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      {
        /* Reset all negotiated variables */
        peer->afc_nego[afi][safi] = 0;
        peer->afc_adv[afi][safi] = 0;
        peer->afc_recv[afi][safi] = 0;

	/* peer address family capability flags*/
	peer->af_cap[afi][safi] = 0;

	/* peer address family status flags*/
	peer->af_sflags[afi][safi] = 0;

	/* Received ORF prefix-filter */
	peer->orf_plist[afi][safi] = NULL;

        /* ORF received prefix-filter pnt */
        sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
        prefix_bgp_orf_remove_all (orf_name);
      }

  /* Reset keepalive and holdtime */
  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
    {
      peer->v_keepalive = peer->keepalive;
      peer->v_holdtime = peer->holdtime;
    }
  else
    {
      peer->v_keepalive = peer->bgp->default_keepalive;
      peer->v_holdtime = peer->bgp->default_holdtime;
    }

  peer->update_time = 0;

  /* Until we are sure that there is no problem about prefix count
     this should be commented out.*/
#if 0
  /* Reset prefix count */
  peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
  peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
  peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
  peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
#endif /* 0 */

  return 0;
}