Exemplo n.º 1
0
Arquivo: node.c Projeto: kr/cubby
int
node_is_active(node n)
{
    return node_is_local(n) || peer_active(n->peer);
}
Exemplo n.º 2
0
/* Hook function called after bgp event is occered.  And vty's
   neighbor command invoke this function after making neighbor
   structure. */
void
bgp_timer_set (struct peer *peer)
{
  int jitter = 0;

  switch (peer->status)
    {
    case Idle:
      /* First entry point of peer's finite state machine.  In Idle
	 status start timer is on unless peer is shutdown or peer is
	 inactive.  All other timer must be turned off */
      if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer))
	{
	  BGP_TIMER_OFF (peer->t_start);
	}
      else
	{
	  jitter = bgp_start_jitter (peer->v_start);
	  BGP_TIMER_ON (peer->t_start, bgp_start_timer,
			peer->v_start + jitter);
	}
      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);
      break;

    case Connect:
      /* After start timer is expired, the peer moves to Connnect
         status.  Make sure start timer is off and connect timer is
         on. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_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);
      break;

    case Active:
      /* Active is waiting connection from remote peer.  And if
         connect timer is expired, change status to Connect. */
      BGP_TIMER_OFF (peer->t_start);
      /* If peer is passive mode, do not set connect timer. */
      if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
	  || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
	{
	  BGP_TIMER_OFF (peer->t_connect);
	}
      else
	{
	  BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_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);
      break;

    case OpenSent:
      /* OpenSent status. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_OFF (peer->t_connect);
      if (peer->v_holdtime != 0)
	{
	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, 
			peer->v_holdtime);
	}
      else
	{
	  BGP_TIMER_OFF (peer->t_holdtime);
	}
      BGP_TIMER_OFF (peer->t_keepalive);
      BGP_TIMER_OFF (peer->t_asorig);
      BGP_TIMER_OFF (peer->t_routeadv);
      break;

    case OpenConfirm:
      /* OpenConfirm status. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_OFF (peer->t_connect);

      /* If the negotiated Hold Time value is zero, then the Hold Time
         timer and KeepAlive timers are not started. */
      if (peer->v_holdtime == 0)
	{
	  BGP_TIMER_OFF (peer->t_holdtime);
	  BGP_TIMER_OFF (peer->t_keepalive);
	}
      else
	{
	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
			peer->v_holdtime);
	  BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, 
			peer->v_keepalive);
	}
      BGP_TIMER_OFF (peer->t_asorig);
      BGP_TIMER_OFF (peer->t_routeadv);
      break;

    case Established:
      /* In Established status start and connect timer is turned
         off. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_OFF (peer->t_connect);

      /* Same as OpenConfirm, if holdtime is zero then both holdtime
         and keepalive must be turned off. */
      if (peer->v_holdtime == 0)
	{
	  BGP_TIMER_OFF (peer->t_holdtime);
	  BGP_TIMER_OFF (peer->t_keepalive);
	}
      else
	{
	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
			peer->v_holdtime);
	  BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
			peer->v_keepalive);
	}
      BGP_TIMER_OFF (peer->t_asorig);
      break;
    case Deleted:
      BGP_TIMER_OFF (peer->t_gr_restart);
      BGP_TIMER_OFF (peer->t_gr_stale);
      BGP_TIMER_OFF (peer->t_pmax_restart);
    case Clearing:
      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);
    }
}
Exemplo n.º 3
0
/* Accept bgp connection. */
static int bgp_accept(struct thread *thread)
{
	int bgp_sock;
	int accept_sock;
	union sockunion su;
	struct bgp_listener *listener = THREAD_ARG(thread);
	struct peer *peer;
	struct peer *peer1;
	char buf[SU_ADDRSTRLEN];
	struct bgp *bgp = NULL;

	sockunion_init(&su);

	/* Register accept thread. */
	accept_sock = THREAD_FD(thread);
	if (accept_sock < 0) {
		flog_err_sys(EC_LIB_SOCKET, "accept_sock is nevative value %d",
			     accept_sock);
		return -1;
	}
	listener->thread = NULL;

	thread_add_read(bm->master, bgp_accept, listener, accept_sock,
			&listener->thread);

	/* Accept client connection. */
	bgp_sock = sockunion_accept(accept_sock, &su);
	if (bgp_sock < 0) {
		flog_err_sys(EC_LIB_SOCKET,
			     "[Error] BGP socket accept failed (%s)",
			     safe_strerror(errno));
		return -1;
	}
	set_nonblocking(bgp_sock);

	/* Obtain BGP instance this connection is meant for.
	 * - if it is a VRF netns sock, then BGP is in listener structure
	 * - otherwise, the bgp instance need to be demultiplexed
	 */
	if (listener->bgp)
		bgp = listener->bgp;
	else if (bgp_get_instance_for_inc_conn(bgp_sock, &bgp)) {
		if (bgp_debug_neighbor_events(NULL))
			zlog_debug(
				"[Event] Could not get instance for incoming conn from %s",
				inet_sutop(&su, buf));
		close(bgp_sock);
		return -1;
	}

	/* Set socket send buffer size */
	setsockopt_so_sendbuf(bgp_sock, BGP_SOCKET_SNDBUF_SIZE);

	/* Check remote IP address */
	peer1 = peer_lookup(bgp, &su);

	if (!peer1) {
		peer1 = peer_lookup_dynamic_neighbor(bgp, &su);
		if (peer1) {
			/* Dynamic neighbor has been created, let it proceed */
			peer1->fd = bgp_sock;
			bgp_fsm_change_status(peer1, Active);
			BGP_TIMER_OFF(
				peer1->t_start); /* created in peer_create() */

			if (peer_active(peer1))
				BGP_EVENT_ADD(peer1, TCP_connection_open);

			return 0;
		}
	}

	if (!peer1) {
		if (bgp_debug_neighbor_events(NULL)) {
			zlog_debug(
				"[Event] %s connection rejected - not configured"
				" and not valid for dynamic",
				inet_sutop(&su, buf));
		}
		close(bgp_sock);
		return -1;
	}

	if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) {
		if (bgp_debug_neighbor_events(peer1))
			zlog_debug(
				"[Event] connection from %s rejected due to admin shutdown",
				inet_sutop(&su, buf));
		close(bgp_sock);
		return -1;
	}

	/*
	 * Do not accept incoming connections in Clearing state. This can result
	 * in incorect state transitions - e.g., the connection goes back to
	 * Established and then the Clearing_Completed event is generated. Also,
	 * block incoming connection in Deleted state.
	 */
	if (peer1->status == Clearing || peer1->status == Deleted) {
		if (bgp_debug_neighbor_events(peer1))
			zlog_debug(
				"[Event] Closing incoming conn for %s (%p) state %d",
				peer1->host, peer1, peer1->status);
		close(bgp_sock);
		return -1;
	}

	/* Check that at least one AF is activated for the peer. */
	if (!peer_active(peer1)) {
		if (bgp_debug_neighbor_events(peer1))
			zlog_debug(
				"%s - incoming conn rejected - no AF activated for peer",
				peer1->host);
		close(bgp_sock);
		return -1;
	}

	if (bgp_debug_neighbor_events(peer1))
		zlog_debug("[Event] BGP connection from host %s fd %d",
			   inet_sutop(&su, buf), bgp_sock);

	if (peer1->doppelganger) {
		/* We have an existing connection. Kill the existing one and run
		   with this one.
		*/
		if (bgp_debug_neighbor_events(peer1))
			zlog_debug(
				"[Event] New active connection from peer %s, Killing"
				" previous active connection",
				peer1->host);
		peer_delete(peer1->doppelganger);
	}

	if (bgp_set_socket_ttl(peer1, bgp_sock) < 0)
		if (bgp_debug_neighbor_events(peer1))
			zlog_debug(
				"[Event] Unable to set min/max TTL on peer %s, Continuing",
				peer1->host);

	peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as,
			   peer1->as, peer1->as_type, 0, 0, NULL);
	hash_release(peer->bgp->peerhash, peer);
	hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);

	peer_xfer_config(peer, peer1);
	UNSET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);

	peer->doppelganger = peer1;
	peer1->doppelganger = peer;
	peer->fd = bgp_sock;
	vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
	bgp_fsm_change_status(peer, Active);
	BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */

	SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);

	/* Make dummy peer until read Open packet. */
	if (peer1->status == Established
	    && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) {
		/* If we have an existing established connection with graceful
		 * restart
		 * capability announced with one or more address families, then
		 * drop
		 * existing established connection and move state to connect.
		 */
		peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
		SET_FLAG(peer1->sflags, PEER_STATUS_NSF_WAIT);
		bgp_event_update(peer1, TCP_connection_closed);
	}

	if (peer_active(peer)) {
		BGP_EVENT_ADD(peer, TCP_connection_open);
	}

	return 0;
}
Exemplo n.º 4
0
/* Hook function called after bgp event is occered.  And vty's
   neighbor command invoke this function after making neighbor
   structure. */
void
bgp_timer_set (struct peer *peer)
{
  afi_t afi;
  safi_t safi;
  int active_delay = 0;

  switch (peer->status)
    {
    case Idle:
      /* First entry point of peer's finite state machine.  In Idle
	 status start timer is on unless peer is shutdown or peer is
	 inactive.  All other timer must be turned off */
      if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
	  || CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)
	  || ! peer_active (peer))
	{
	  BGP_TIMER_OFF (peer->t_start);
	}
      else
	{
	  if (CHECK_FLAG (peer->sflags, PEER_STATUS_CREATE_INIT))
	    {
	      BGP_TIMER_ON (peer->t_start, bgp_start_timer, BGP_PEER_FIRST_CREATE_TIMER);
	    }
	  else
	    {
	      BGP_TIMER_ON (peer->t_start, bgp_start_timer, peer->v_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]);
      break;

    case Connect:
      /* After start timer is expired, the peer moves to Connnect
         status.  Make sure start timer is off and connect timer is
         on. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_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]);
      break;

    case Active:
      /* Active is waiting connection from remote peer.  And if
         connect timer is expired, change status to Connect. */
      BGP_TIMER_OFF (peer->t_start);
      /* If peer is passive mode, do not set connect timer. */
      if (CHECK_FLAG (peer->flags, PEER_FLAG_CONNECT_MODE_PASSIVE))
	{
	  if (BGP_DEBUG (normal, NORMAL))
	    zlog_info ("%s active open failed - TCP session must be opened passively", peer->host);
	  BGP_TIMER_OFF (peer->t_connect);
	}
      else
	{
	  if (peer->ostatus == Idle
	      && ! CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
	    {
	      active_delay = peer->v_active_delay;
	      active_delay += bgp_active_delay_jitter (BGP_ACTIVE_DELAY_TIMER);

	      if (BGP_DEBUG (normal, NORMAL))
		zlog_info ("%s open active, delay %d sec", peer->host, active_delay);
	      BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, active_delay);
	    }
	  else
	    {
	      BGP_TIMER_ON (peer->t_connect, bgp_connect_timer,
			    peer->v_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]);
      break;

    case OpenSent:
      /* OpenSent status. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_OFF (peer->t_connect);
      if (peer->v_holdtime != 0)
	{
	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, 
			peer->v_holdtime);
	}
      else
	{
	  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]);
      break;

    case OpenConfirm:
      /* OpenConfirm status. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_OFF (peer->t_connect);

      /* If the negotiated Hold Time value is zero, then the Hold Time
         timer and KeepAlive timers are not started. */
      if (peer->v_holdtime == 0)
	{
	  BGP_TIMER_OFF (peer->t_holdtime);
	  BGP_TIMER_OFF (peer->t_keepalive);
	}
      else
	{
	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
			peer->v_holdtime);
	  BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, 
			peer->v_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]);
      break;

    case Established:
      /* In Established status start and connect timer is turned
         off. */
      BGP_TIMER_OFF (peer->t_start);
      BGP_TIMER_OFF (peer->t_connect);

      /* Same as OpenConfirm, if holdtime is zero then both holdtime
         and keepalive must be turned off. */
      if (peer->v_holdtime == 0)
	{
	  BGP_TIMER_OFF (peer->t_holdtime);
	  BGP_TIMER_OFF (peer->t_keepalive);
	}
      else
	{
	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
			peer->v_holdtime);
	  BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
			peer->v_keepalive);
	}
      BGP_TIMER_OFF (peer->t_asorig);
      break;
    }
}