/* Execute event process. */
int
bgp_event (struct thread *thread)
{
  int ret = 0;
  int event;
  int next;
  struct peer *peer;

  peer = THREAD_ARG (thread);
  event = THREAD_VAL (thread);

  /* Logging this event. */
  next = FSM [peer->status -1][event - 1].next_state;

  if (BGP_DEBUG (fsm, FSM) && peer->status != next)
    plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host, 
	       bgp_event_str[event],
	       LOOKUP (bgp_status_msg, peer->status),
	       LOOKUP (bgp_status_msg, next));

  /* Call function. */
  if (FSM [peer->status -1][event - 1].func)
    ret = (*(FSM [peer->status - 1][event - 1].func))(peer);

  /* When function do not want proceed next job return -1. */
  if (ret >= 0)
    {
      /* If status is changed. */
      if (next != peer->status)
        {
          /* Transition into Clearing must /always/ clear all routes.. */
          if (next == Clearing)
            bgp_clear_route_all (peer);
          
          bgp_fsm_change_status (peer, next);
        }
      
      /* Make sure timer is set. */
      bgp_timer_set (peer);
    }
  
  return ret;
}
示例#2
0
/* Called after event occured, this function change status and reset
   read/write and timer thread. */
void
bgp_fsm_change_status (struct peer *peer, int status)
{
  bgp_dump_state (peer, peer->status, status);

  /* Transition into Clearing or Deleted must /always/ clear all routes.. 
   * (and must do so before actually changing into Deleted..
   */
  if (status >= Clearing)
    bgp_clear_route_all (peer);
  
  /* Preserve old status and change into new status. */
  peer->ostatus = peer->status;
  peer->status = status;
  
  if (BGP_DEBUG (normal, NORMAL))
    zlog_debug ("%s went from %s to %s",
		peer->host,
		LOOKUP (bgp_status_msg, peer->ostatus),
		LOOKUP (bgp_status_msg, peer->status));
}
示例#3
0
/* Called after event occured, this function change status and reset
   read/write and timer thread. */
void
bgp_fsm_change_status (struct peer *peer, int status)
{
  bgp_dump_state (peer, peer->status, status);

  /* Transition into Clearing or Deleted must /always/ clear all routes.. 
   * (and must do so before actually changing into Deleted..
   */
  if (status >= Clearing)
    {
      bgp_clear_route_all (peer);

      /* If no route was queued for the clear-node processing, generate the
       * completion event here. This is needed because if there are no routes
       * to trigger the background clear-node thread, the event won't get
       * generated and the peer would be stuck in Clearing. Note that this
       * event is for the peer and helps the peer transition out of Clearing
       * state; it should not be generated per (AFI,SAFI). The event is
       * directly posted here without calling clear_node_complete() as we
       * shouldn't do an extra unlock. This event will get processed after
       * the state change that happens below, so peer will be in Clearing
       * (or Deleted).
       */
      if (!work_queue_is_scheduled (peer->clear_node_queue))
        BGP_EVENT_ADD (peer, Clearing_Completed);
    }
  
  /* Preserve old status and change into new status. */
  peer->ostatus = peer->status;
  peer->status = status;
  
  if (BGP_DEBUG (normal, NORMAL))
    zlog_debug ("%s went from %s to %s",
		peer->host,
		LOOKUP (bgp_status_msg, peer->ostatus),
		LOOKUP (bgp_status_msg, peer->status));
}
示例#4
0
文件: bgp_fsm.c 项目: AllardJ/Tomato
/* Administrative BGP peer stop event. */
int
bgp_stop (struct peer *peer)
{
  afi_t afi;
  safi_t safi;
  char orf_name[BUFSIZ];

  if (CHECK_FLAG (peer->sflags, PEER_STATUS_CREATE_INIT))
    return 0;

  /* Increment Dropped count. */
  if (peer->status == Established)
    {
      bgp_fsm_change_status (peer, Idle);
      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_info ("%s graceful restart stalepath timer stopped", peer->host);
	}
      if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
	{
	  if (BGP_DEBUG (events, EVENTS))
	    {
	      zlog_info ("%s graceful restart timer started for %d sec",
			 peer->host, peer->v_gr_restart);
	      zlog_info ("%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_UNICAST_MULTICAST ; safi++)
	      peer->nsf[afi][safi] = 0;
	}

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

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

      /* Reset uptime. */
      bgp_uptime_reset (peer);

      /* Need of clear of peer. */
      bgp_clear_route_all (peer);

      /* Reset peer synctime */
      for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
	for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
	  peer->synctime[afi][safi] = 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);
  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      BGP_TIMER_OFF (peer->t_routeadv[afi][safi]);

  /* Delete all existing events of the peer. */
  BGP_EVENT_DELETE (peer);

  /* 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);
  stream_fifo_clean (peer->obuf);

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

  /* Connection information. */
  if (peer->su_local)
    {
      XFREE (MTYPE_SOCKUNION, peer->su_local);
      peer->su_local = NULL;
    }

  if (peer->su_remote)
    {
      XFREE (MTYPE_SOCKUNION, peer->su_remote);
      peer->su_remote = NULL;
    }

  /* Clear remote router-id. */
  peer->remote_id.s_addr = 0;

  /* Clear peer capability flag. */
  peer->cap = 0;

  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;
}
示例#5
0
/* Administrative BGP peer stop event. */
int
bgp_stop (struct peer *peer)
{
  int established = 0;
  afi_t afi;
  safi_t safi;
  char orf_name[BUFSIZ];

  /* Increment Dropped count. */
  if (peer->status == Established)
    {
      established = 1;
      peer->dropped++;
      bgp_fsm_change_status (peer, Idle);
#ifdef HAVE_SNMP
      bgpTrapBackwardTransition (peer);
#endif /* HAVE_SNMP */
    }

  /* Reset uptime. */
  bgp_uptime_reset (peer);

  /* Need of clear of peer. */
  if (established)
    bgp_clear_route_all (peer);

  /* 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);

  /* Delete all existing events of the peer. */
  BGP_EVENT_DELETE (peer);

  /* 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);
  stream_fifo_clean (peer->obuf);

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

  /* Connection information. */
  if (peer->su_local)
    {
      XFREE (MTYPE_SOCKUNION, peer->su_local);
      peer->su_local = NULL;
    }

  if (peer->su_remote)
    {
      XFREE (MTYPE_SOCKUNION, peer->su_remote);
      peer->su_remote = NULL;
    }

  /* Clear remote router-id. */
  peer->remote_id.s_addr = 0;

  /* Reset all negotiated variables */
  peer->afc_nego[AFI_IP][SAFI_UNICAST] = 0;
  peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 0;
  peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 0;
  peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 0;
  peer->afc_adv[AFI_IP][SAFI_UNICAST] = 0;
  peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 0;
  peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 0;
  peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 0;
  peer->afc_recv[AFI_IP][SAFI_UNICAST] = 0;
  peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 0;
  peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 0;
  peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 0;

  /* Reset route refresh flag. */
  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
  UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
  UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);

  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      {
	/* 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);
      }

  UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);
  UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);
  UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);
  UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);

  /* 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;
}