summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_debug.c28
-rw-r--r--bgpd/bgp_notification.c17
-rw-r--r--bgpd/bgp_peer.c56
3 files changed, 67 insertions, 34 deletions
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 684e9651..c4cf9cf6 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -262,6 +262,7 @@ bgp_notify_print(struct peer *peer, bgp_notify notification)
bool log_neighbor_changes ;
int length ;
char* alloc ;
+ int subcode ;
/* See if we need to do any of this */
if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
@@ -274,30 +275,37 @@ bgp_notify_print(struct peer *peer, bgp_notify notification)
/* Sort out string forms of code and subcode */
code_str = LOOKUP (bgp_notify_msg, notification->code) ;
- subcode_str = "";
+ subcode = notification->subcode ;
+ subcode_str = "/Unspecific";
switch (notification->code)
{
case BGP_NOTIFY_HEADER_ERR:
- subcode_str = LOOKUP (bgp_notify_head_msg, notification->subcode);
+ if (subcode != 0)
+ subcode_str = LOOKUP (bgp_notify_head_msg, subcode);
break;
case BGP_NOTIFY_OPEN_ERR:
- subcode_str = LOOKUP (bgp_notify_open_msg, notification->subcode);
+ if (subcode != 0)
+ subcode_str = LOOKUP (bgp_notify_open_msg, subcode);
break;
case BGP_NOTIFY_UPDATE_ERR:
- subcode_str = LOOKUP (bgp_notify_update_msg, notification->subcode);
+ if (subcode != 0)
+ subcode_str = LOOKUP (bgp_notify_update_msg, subcode);
break;
case BGP_NOTIFY_HOLD_ERR:
- subcode_str = "";
- break;
case BGP_NOTIFY_FSM_ERR:
- subcode_str = "";
+ if (subcode != 0)
+ subcode_str = "/*unknown*" ;
+ else
+ subcode_str = "";
break;
case BGP_NOTIFY_CEASE:
- subcode_str = LOOKUP (bgp_notify_cease_msg, notification->subcode);
+ if (subcode != 0)
+ subcode_str = LOOKUP (bgp_notify_cease_msg, subcode);
break;
case BGP_NOTIFY_CAPABILITY_ERR:
- subcode_str = LOOKUP (bgp_notify_capability_msg, notification->subcode);
+ if (subcode != 0)
+ subcode_str = LOOKUP (bgp_notify_capability_msg, subcode);
break;
}
@@ -338,7 +346,7 @@ bgp_notify_print(struct peer *peer, bgp_notify notification)
notification->code, notification->subcode,
code_str, subcode_str, length, hex_form) ;
- /* Release the */
+ /* Release the space allocated to the hex form of the data, if any */
if (alloc != NULL)
XFREE(MTYPE_TMP, alloc) ;
} ;
diff --git a/bgpd/bgp_notification.c b/bgpd/bgp_notification.c
index 45bf99b7..c0690df9 100644
--- a/bgpd/bgp_notification.c
+++ b/bgpd/bgp_notification.c
@@ -203,19 +203,25 @@ bgp_notify_take(bgp_notify* p_notification)
extern void
bgp_notify_set(bgp_notify* p_dst, bgp_notify src)
{
- bgp_notify_free(*p_dst) ;
- *p_dst = src ;
+ if (*p_dst != src) /* empty operation if already set ! */
+ {
+ bgp_notify_free(*p_dst) ;
+ *p_dst = src ;
+ } ;
} ;
/*------------------------------------------------------------------------------
* Set pointer to notification to a *copy* of the source.
*
- * Frees any existing notification at the destination.
+ * Frees any existing notification at the destination unless points at src !
*/
extern void
bgp_notify_set_dup(bgp_notify* p_dst, bgp_notify src)
{
- bgp_notify_set(p_dst, bgp_notify_dup(src)) ;
+ if (*p_dst != src)
+ bgp_notify_free(*p_dst) ; /* avoid freeing what we're duplicating */
+
+ *p_dst = bgp_notify_dup(src) ;
} ;
/*------------------------------------------------------------------------------
@@ -228,8 +234,7 @@ bgp_notify_set_dup(bgp_notify* p_dst, bgp_notify src)
extern void
bgp_notify_set_mov(bgp_notify* p_dst, bgp_notify* p_src)
{
- bgp_notify_free(*p_dst) ;
- *p_dst = *p_src ;
+ bgp_notify_set(p_dst, *p_src) ;
*p_src = NULL ;
} ;
diff --git a/bgpd/bgp_peer.c b/bgpd/bgp_peer.c
index 2062c527..625e1d99 100644
--- a/bgpd/bgp_peer.c
+++ b/bgpd/bgp_peer.c
@@ -177,7 +177,8 @@
/* prototypes */
static void bgp_session_has_established(bgp_session session);
-static void bgp_session_has_stopped(bgp_session session);
+static void bgp_session_has_stopped(bgp_session session,
+ bgp_notify notification) ;
static void bgp_session_has_disabled(bgp_session session);
static void bgp_uptime_reset (struct peer *peer);
static void bgp_peer_stop (struct peer *peer, bool nsf) ;
@@ -216,9 +217,7 @@ bgp_session_do_event(mqueue_block mqb, mqb_flag_t flag)
{
/* Pull stuff into Routing Engine *private* fields in the session */
- session->event = args->event ; /* last event */
- bgp_notify_set(&session->notification, args->notification) ;
- /* if any sent/received */
+ session->event = args->event ; /* last event */
session->err = args->err ; /* errno, if any */
session->ordinal = args->ordinal ; /* primary/secondary connection */
@@ -232,6 +231,8 @@ bgp_session_do_event(mqueue_block mqb, mqb_flag_t flag)
* before the BGP Engine had seen the disable message.
*/
case bgp_session_eEstablished:
+ assert(args->notification == NULL) ;
+
if (session->state == bgp_session_sLimping)
break ;
@@ -241,6 +242,10 @@ bgp_session_do_event(mqueue_block mqb, mqb_flag_t flag)
/* If now Disabled, then the BGP Engine is acknowledging the a
* session disable, and the session is now disabled.
*
+ * If sent a notification with the disable request, then it is
+ * returned iff the notification was actually sent. Don't really
+ * care one way or the other.
+ *
* BEWARE: this may be the last thing that happens to the session
* and/or the related peer -- which may be deleted inside
* bgp_session_has_disabled().
@@ -259,12 +264,13 @@ bgp_session_do_event(mqueue_block mqb, mqb_flag_t flag)
break ;
if (args->stopped)
- bgp_session_has_stopped(session) ;
+ bgp_session_has_stopped(session,
+ bgp_notify_take(&(args->notification))) ;
break ;
} ;
- }
- else
- bgp_notify_free(args->notification) ;
+ } ;
+
+ bgp_notify_free(args->notification) ; /* Discard any notification. */
mqb_free(mqb) ;
}
@@ -410,11 +416,13 @@ bgp_session_has_established(bgp_session session)
* that is to tell it to disable the session, and then wait in sLimping state
* until the BGP Engine completes the disable request and signals that.
*
+ * NB: takes responsibility for the notification.
+ *
* TODO: session stopped because we stopped it or because the other end did ?
* TODO: restore NSF !!
*/
static void
-bgp_session_has_stopped(bgp_session session)
+bgp_session_has_stopped(bgp_session session, bgp_notify notification)
{
peer_down_t why_down ;
@@ -432,17 +440,17 @@ bgp_session_has_stopped(bgp_session session)
peer->v_start = (60 * 2);
} ;
- if (session->notification == NULL)
+ if (notification == NULL)
why_down = PEER_DOWN_CLOSE_SESSION ;
else
{
- if (session->notification->received)
+ if (notification->received)
why_down = PEER_DOWN_NOTIFY_RECEIVED ;
else
- why_down = bgp_peer_map_notification(session->notification) ;
+ why_down = bgp_peer_map_notification(notification) ;
} ;
- bgp_peer_down_notify(peer, why_down, session->notification) ;
+ bgp_peer_down_notify(peer, why_down, notification) ;
} ;
/*------------------------------------------------------------------------------
@@ -1255,6 +1263,16 @@ bgp_peer_down(bgp_peer peer, peer_down_t why_down)
bgp_peer_down_notify(peer, why_down, NULL) ;
} ;
+/*------------------------------------------------------------------------------
+ * Down Peer for the given reason, with the given notification, if any.
+ *
+ * See bgp_peer_down() above.
+ *
+ * If the notification is NULL and need to send a notification, make one up from
+ * the given reason for downing the peer.
+ *
+ * NB: takes responsibility for the notification.
+ */
static void
bgp_peer_down_notify(bgp_peer peer, peer_down_t why_down,
bgp_notify notification)
@@ -1266,12 +1284,14 @@ bgp_peer_down_notify(bgp_peer peer, peer_down_t why_down,
if (notification == NULL)
notification = bgp_peer_map_peer_down(why_down) ;
- bgp_notify_set_dup(&peer->session->notification, notification) ;
+ bgp_notify_set(&peer->session->notification, notification) ;
- bgp_session_disable(peer, notification) ;
- }
- else
- bgp_notify_free(notification) ; /* Discard unused notification */
+ bgp_session_disable(peer, bgp_notify_dup(notification)) ;
+ /* The copy of the notification will be discarded either by
+ * the BGP_Engine, if the notification is not sent, or when
+ * it is returned in the eDisabled message.
+ */
+ } ;
/* Now worry about the state of the peer */