summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_peer.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_peer.c')
-rw-r--r--bgpd/bgp_peer.c267
1 files changed, 37 insertions, 230 deletions
diff --git a/bgpd/bgp_peer.c b/bgpd/bgp_peer.c
index 3d686171..9e9f8b06 100644
--- a/bgpd/bgp_peer.c
+++ b/bgpd/bgp_peer.c
@@ -33,9 +33,11 @@
#include "memory.h"
#include "plist.h"
#include "mqueue.h"
+#include "workqueue.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_peer.h"
+#include "bgpd/bgp_peer_index.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_debug.h"
@@ -45,6 +47,7 @@
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_dump.h"
#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_engine.h"
#include "bgpd/bgp_session.h"
@@ -53,6 +56,21 @@
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */
+/* prototypes */
+
+static int
+bgp_session_has_established(bgp_peer peer);
+static int
+bgp_session_has_stopped(bgp_peer peer);
+static void
+bgp_uptime_reset (struct peer *peer);
+static int
+bgp_routeadv_timer (struct thread *thread);
+static int
+bgp_graceful_restart_timer_expire (struct thread *thread);
+static int
+bgp_graceful_stale_timer_expire (struct thread *thread);
+
/*==============================================================================
* This is the high level management of BGP Peers and peering conversations.
*
@@ -78,215 +96,6 @@
*
*/
-
-/*==============================================================================
- * BGP Peer Index
- *
- * When peers are created, they are registered in the bgp_peer_index. When
- * they are destroyed, they are removed. This is done by the Routeing Engine.
- *
- * The peer index is used by the Routeing Engine to lookup peers.
- *
- * The BGP Engine needs to lookup sessions when a listening socket accepts a
- * connection -- first, to decide whether to continue with the connection, and
- * second, to tie the connection to the right session. It uses the peer index
- * to do this.
- *
- * A mutex is used to coordinate access to the index.
- *
- * NB: the bgp_peer points to its bgp_session (if any). The session pointer
- * MUST only be changed while holding the index mutex.
- *
- * See bgp_peer_set_session().
- *
- * NB: to avoid deadlock, MUST NOT do anything using the index while holding
- * any session mutex.
- *
- * But may acquire a session mutex while doing things to the index.
- */
-
-static struct symbol_table bgp_peer_index ;
-static qpt_mutex_t bgp_peer_index_mutex ;
-
-inline static void BGP_PEER_INDEX_LOCK(void)
-{
- qpt_mutex_lock(&bgp_peer_index_mutex) ;
-} ;
-
-inline static void BGP_PEER_INDEX_UNLOCK(void)
-{
- qpt_mutex_unlock(&bgp_peer_index_mutex) ;
-} ;
-
-/*------------------------------------------------------------------------------
- * Initialise the bgp_peer_index.
- *
- * This must be done before any peers are configured !
- */
-void
-bgp_peer_index_init(void* parent)
-{
- symbol_table_init_new(
- &bgp_peer_index,
- parent,
- 10, /* start ready for a few sessions */
- 200, /* allow to be quite dense */
- sockunion_symbol_hash, /* "name" is an IP Address */
- NULL) ; /* no value change call-back */
-}
-
-/*------------------------------------------------------------------------------
- * Initialise the bgp_peer_index_mutex.
- *
- * This must be done before the BGP Engine is started.
- */
-void
-bgp_peer_index_mutex_init(void* parent)
-{
- qpt_mutex_init(&bgp_peer_index_mutex, qpt_mutex_recursive) ;
-}
-
-/*------------------------------------------------------------------------------
- * Lookup a peer -- do nothing if does not exist
- *
- * For use by the Routeing Engine.
- *
- * Returns the bgp_peer -- NULL if not found.
- */
-bgp_peer
-bgp_peer_index_seek(union sockunion* su)
-{
- bgp_peer peer ;
-
- BGP_PEER_INDEX_LOCK() ; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
- peer = symbol_get_value(symbol_seek(&bgp_peer_index, su)) ;
-
- BGP_PEER_INDEX_UNLOCK() ; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- return peer ;
-}
-
-/*------------------------------------------------------------------------------
- * Register a peer in the peer index.
- *
- * For use by the Routeing Engine.
- *
- * NB: it is a FATAL error to register a peer for an address which is already
- * registered.
- */
-void
-bgp_peer_index_register(bgp_peer peer, union sockunion* su)
-{
- BGP_PEER_INDEX_LOCK() ; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
- peer = symbol_set_value(symbol_find(&bgp_peer_index, su), peer) ;
-
- BGP_PEER_INDEX_UNLOCK() ; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- passert(peer == NULL) ;
-}
-
-/*------------------------------------------------------------------------------
- * Unregister a peer in the peer index.
- *
- * returns 1 if successfully unregistered
- * returns 0 if wasn't registered
- * FATAL error if a different peer is registered.
- */
-int
-bgp_peer_index_unregister(bgp_peer peer, union sockunion* su)
-{
- int found = 0;
- int right_peer = 1;
- symbol s = NULL;
-
- BGP_PEER_INDEX_LOCK() ; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
- s = symbol_seek(&bgp_peer_index, su);
- found = (s != NULL);
- if (found)
- {
- right_peer = (peer == symbol_get_value(s));
- if (right_peer)
- symbol_delete(s);
- }
-
- BGP_PEER_INDEX_UNLOCK() ; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- passert(right_peer) ;
- return found;
-}
-
-/*------------------------------------------------------------------------------
- * Lookup a session -- do nothing if does not exist
- *
- * For use by the BGP Engine.
- *
- * Returns the bgp_session, or NULL if not found OR not active
- * Sets *p_found <=> found.
- *
- * NB: the BGP Engine may not access the bgp_session structure if it is not
- * in either of the active states (Enabled or Established).
- *
- * So this function does not return the bgp_session unless it is active.
- *
- * For callers who care, the p_found return indicates whether the session
- * exists, or not.
- */
-extern bgp_session
-bgp_session_index_seek(union sockunion* su, int* p_found)
-{
- bgp_session session ;
- bgp_peer peer ;
-
- BGP_PEER_INDEX_LOCK() ; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
- peer = symbol_get_value(symbol_seek(&bgp_peer_index, su)) ;
- *p_found = (peer != NULL) ;
- if (*p_found && bgp_session_is_active(peer->session))
- /* NULL peer->session is not active */
- session = peer->session ;
- else
- session = NULL ;
-
- BGP_PEER_INDEX_UNLOCK() ; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- return session ;
-}
-
-/*------------------------------------------------------------------------------
- * Set peer's session pointer.
- *
- * For use by the Routeing Engine. Locks the bgp_peer_index mutex so that the
- * BGP Engine is not fooled when it looks up the session.
- *
- * Returns the old session pointer value.
- *
- * NB: it is a FATAL error to change the pointer if the current session is
- * "active".
- *
- */
-
-bgp_session
-bgp_peer_new_session(bgp_peer peer, bgp_session new_session)
-{
- bgp_session old_session ;
-
- BGP_PEER_INDEX_LOCK() ; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
- old_session = peer->session ;
- peer->session = new_session ;
-
- passert(!bgp_session_is_active(old_session)) ;
-
- BGP_PEER_INDEX_UNLOCK() ; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- return old_session ;
-}
-
-
-
/*==============================================================================
* Deal with change in session state -- mqueue_action function.
*
@@ -298,44 +107,46 @@ bgp_peer_new_session(bgp_peer peer, bgp_session new_session)
* Established -> Stopped -- for some reason
*
* -- arg0 = session
- * arg1 = new state
+ * args = bgp_session_event_args
*
*/
void
-bgp_peer_new_session_state(mqueue_block mqb, mqb_flag_t flag)
+bgp_session_do_event(mqueue_block mqb, mqb_flag_t flag)
{
- bgp_session session = mqb_get_arg0(mqb) ;
- bgp_session_state_t state = mqb_get_arg1_i(mqb) ;
- bgp_peer peer = session->peer ;
+
+ struct bgp_session_event_args * args = mqb_get_args(mqb) ;
+ bgp_session session = mqb_get_arg0(mqb) ;
+ bgp_peer peer = session->peer ;
if (flag == mqb_action)
{
- bgp_session_lock(session) ;
+ BGP_SESSION_LOCK(session) ;
- switch(new_state)
+ switch(args->state)
{
/* If now Enabled, then the BGP Engine is attempting to connect */
/* (may be waiting for the Idle Hold Time to expire. */
- case bgp_session_Enabled:
- bgp_session_enable(session, peer);
+ case bgp_session_sEnabled:
+ bgp_session_enable(peer);
break ;
/* If now Established, then the BGP Engine has exchanged BGP Open */
/* messages, and received the KeepAlive that acknowledges our Open. */
- case bgp_session_Established:
+ case bgp_session_sEstablished:
bgp_session_has_established(peer);
break ;
/* If now Stopped, then for some reason the BGP Engine has either */
/* stopped trying to connect, or the session has been stopped. */
- case bgp_session_Stopped:
+ case bgp_session_sStopped:
bgp_session_has_stopped(peer);
break ;
default:
+ break;
}
- bgp_session_unlock(session) ;
+ BGP_SESSION_UNLOCK(session) ;
}
mqb_free(mqb) ;
@@ -350,7 +161,6 @@ bgp_peer_new_session_state(mqueue_block mqb, mqb_flag_t flag)
static int
bgp_session_has_established(bgp_peer peer)
{
- struct bgp_notify *notify;
afi_t afi;
safi_t safi;
int nsf_af_count = 0;
@@ -363,10 +173,7 @@ bgp_session_has_established(bgp_peer peer)
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));
+ bgp_notify_free(&(peer->notify));
/* Clear start timer value to default. */
peer->v_start = BGP_INIT_START_TIMER;
@@ -603,7 +410,8 @@ bgp_peer_timers_stop(bgp_peer peer)
BGP_TIMER_OFF (peer->t_pmax_restart);
} ;
-void
+/* TODO: bgp_timer_set - kill ? */
+static void
bgp_timer_set (struct peer *peer)
{
int jitter = 0;
@@ -891,7 +699,7 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
bgp_timer_set (peer);
/* session */
- peer->session = bgp_session_init_new(NULL);
+ peer->session = bgp_session_init_new(peer->session, peer);
/* register */
bgp_peer_index_register(peer, &peer->su);
@@ -1039,8 +847,7 @@ peer_delete (struct peer *peer)
}
/* unregister */
- if (peer->su)
- bgp_peer_index_unregister(peer, &peer->su);
+ bgp_peer_index_deregister(peer, &peer->su);
peer_unlock (peer); /* initial reference */