summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c796
1 files changed, 445 insertions, 351 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 740b0f1c..3fd584c5 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -103,8 +103,8 @@ bgp_packet_delete (struct peer *peer)
}
/* Check file descriptor whether connect is established. */
-static void
-bgp_connect_check (struct peer *peer)
+int
+bgp_connect_check (struct peer *peer, int change_state)
{
int status;
socklen_t slen;
@@ -121,22 +121,25 @@ bgp_connect_check (struct peer *peer)
/* If getsockopt is fail, this is fatal error. */
if (ret < 0)
{
- zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
+ zlog_info ("can't get sockopt for nonblocking connect");
BGP_EVENT_ADD (peer, TCP_fatal_error);
- return;
+ return -1;
}
/* When status is 0 then TCP connection is established. */
if (status == 0)
{
BGP_EVENT_ADD (peer, TCP_connection_open);
+ return 1;
}
else
{
- if (BGP_DEBUG (events, EVENTS))
- plog_debug (peer->log, "%s [Event] Connect failed (%s)",
- peer->host, safe_strerror (errno));
- BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [Event] Connect failed (%s)",
+ peer->host, safe_strerror (errno));
+ if (change_state)
+ BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+ return 0;
}
}
@@ -153,8 +156,13 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
struct bgp_info *binfo = NULL;
bgp_size_t total_attr_len = 0;
unsigned long attrlen_pos = 0;
+ int space_remaining = 0;
+ int space_needed = 0;
size_t mpattrlen_pos = 0;
size_t mpattr_pos = 0;
+ int num_pfx_adv = 0;
+ char send_attr_str[BUFSIZ];
+ int send_attr_printed = 0;
s = peer->work;
stream_reset (s);
@@ -171,9 +179,12 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
if (adv->binfo)
binfo = adv->binfo;
+ space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
+ BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
+
/* When remaining space can't include NLRI and it's length. */
- if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
- (BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(afi,safi,&rn->p)))
+ if (space_remaining < space_needed)
break;
/* If packet is empty, set attribute. */
@@ -217,6 +228,29 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
&rn->p : NULL),
afi, safi,
from, prd, tag);
+ space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
+ BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);;
+
+ /* If the attributes alone do not leave any room for NLRI then
+ * return */
+ if (space_remaining < space_needed)
+ {
+ zlog_err ("%s cannot send UPDATE, the attributes do not leave "
+ "room for NLRI", peer->host);
+ /* Flush the FIFO update queue */
+ while (adv)
+ adv = bgp_advertise_clean (peer, adv->adj, afi, safi);
+ return NULL;
+ }
+
+ if (BGP_DEBUG (update, UPDATE_OUT) ||
+ BGP_DEBUG (update, UPDATE_PREFIX))
+ {
+ memset (send_attr_str, 0, BUFSIZ);
+ send_attr_printed = 0;
+ bgp_dump_attr (peer, adv->baa->attr, send_attr_str, BUFSIZ);
+ }
}
if (afi == AFI_IP && safi == SAFI_UNICAST)
@@ -237,14 +271,21 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
adv->baa->attr);
bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
}
- if (BGP_DEBUG (update, UPDATE_OUT))
+ num_pfx_adv++;
+
+ if (bgp_debug_update(peer, &rn->p, 0))
{
+ if (!send_attr_printed)
+ {
+ zlog_debug ("%s send UPDATE w/ attr: %s", peer->host, send_attr_str);
+ send_attr_printed = 1;
+ }
char buf[INET6_BUFSIZ];
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
- peer->host,
- inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
- rn->p.prefixlen);
+ zlog_debug ("%s send UPDATE %s/%d",
+ peer->host,
+ inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
+ rn->p.prefixlen);
}
/* Synchnorize attribute. */
@@ -274,8 +315,11 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
else
packet = stream_dup (s);
bgp_packet_set_size (packet);
+ if (BGP_DEBUG (update, UPDATE_OUT))
+ zlog_debug("%s form UPDATE (adv) total len %zd numPfx %d",
+ peer->host,
+ (stream_get_endp (s) - stream_get_getp (s)), num_pfx_adv);
bgp_packet_add (peer, packet);
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
stream_reset (s);
stream_reset (snlri);
return packet;
@@ -291,7 +335,7 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
if (DISABLE_BGP_ANNOUNCE)
return NULL;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -347,6 +391,9 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
size_t attrlen_pos = 0;
size_t mplen_pos = 0;
u_char first_time = 1;
+ int space_remaining = 0;
+ int space_needed = 0;
+ int num_pfx_wd = 0;
s = peer->work;
stream_reset (s);
@@ -357,8 +404,12 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
adj = adv->adj;
rn = adv->rn;
- if (STREAM_REMAIN (s)
- < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
+ space_remaining = STREAM_REMAIN (s) -
+ BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN +
+ bgp_packet_mpattr_prefix_size (afi, safi, &rn->p));
+
+ if (space_remaining < space_needed)
break;
if (stream_empty (s))
@@ -390,15 +441,16 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
}
+ num_pfx_wd++;
- if (BGP_DEBUG (update, UPDATE_OUT))
+ if (bgp_debug_update(peer, &rn->p, 0))
{
char buf[INET6_BUFSIZ];
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
- peer->host,
- inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
- rn->p.prefixlen);
+ zlog_debug ("%s send UPDATE %s/%d -- unreachable",
+ peer->host,
+ inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
+ rn->p.prefixlen);
}
peer->scount[afi][safi]--;
@@ -426,6 +478,10 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
stream_putw_at (s, attrlen_pos, total_attr_len);
}
bgp_packet_set_size (s);
+ if (BGP_DEBUG (update, UPDATE_OUT))
+ zlog_debug("%s form UPDATE (wd) total len %zd numPfx %d",
+ peer->host,
+ (stream_get_endp (s) - stream_get_getp (s)), num_pfx_wd);
packet = stream_dup (s);
bgp_packet_add (peer, packet);
stream_reset (s);
@@ -453,16 +509,16 @@ bgp_default_update_send (struct peer *peer, struct attr *attr,
str2prefix ("::/0", &p);
/* Logging the attribute. */
- if (BGP_DEBUG (update, UPDATE_OUT))
+ if (bgp_debug_update(peer, &p, 0))
{
char attrstr[BUFSIZ];
char buf[INET6_BUFSIZ];
attrstr[0] = '\0';
bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
- peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
- p.prefixlen, attrstr);
+ zlog_debug ("%s send UPDATE %s/%d %s",
+ peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
+ p.prefixlen, attrstr);
}
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -521,13 +577,13 @@ bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
total_attr_len = 0;
- if (BGP_DEBUG (update, UPDATE_OUT))
+ if (bgp_debug_update(peer, &p, 0))
{
char buf[INET6_BUFSIZ];
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
- peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
- p.prefixlen);
+ zlog_debug ("%s send UPDATE %s/%d -- unreachable",
+ peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
+ p.prefixlen);
}
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -589,6 +645,12 @@ bgp_write_packet (struct peer *peer)
if (s)
return s;
+ /* The code beyond this part deals with update packets, check if updates
+ are on hold as part of the update-delay post processing stages. */
+ if (peer->bgp && (peer->bgp->main_peers_update_hold ||
+ peer->bgp->rsclient_peers_update_hold))
+ return NULL;
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
@@ -607,7 +669,7 @@ bgp_write_packet (struct peer *peer)
adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
if (adv)
{
- if (adv->binfo && adv->binfo->uptime < peer->synctime)
+ if (adv->binfo && adv->binfo->uptime <= peer->synctime)
{
if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
&& CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
@@ -645,28 +707,82 @@ bgp_write_packet (struct peer *peer)
return NULL;
}
-/* Is there partially written packet or updates we can send right
- now. */
-static int
-bgp_write_proceed (struct peer *peer)
+/* Are there prefixes queued for being withdrawn? */
+int
+bgp_peer_wd_fifo_exists (struct peer *peer)
{
afi_t afi;
safi_t safi;
- struct bgp_advertise *adv;
-
- if (stream_fifo_head (peer->obuf))
- return 1;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
return 1;
+ return 0;
+}
+
+/* Are there prefixes queued for being advertised?
+ * Are they recent?
+ */
+int
+bgp_peer_adv_fifo_exists (struct peer *peer, int chk_recent)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp_advertise *adv;
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
- if (adv->binfo->uptime < peer->synctime)
- return 1;
+ {
+ if (!chk_recent)
+ return 1;
+ if (adv->binfo->uptime < peer->synctime)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Schedule updates for the peer, if needed.
+ */
+void
+bgp_peer_schedule_updates(struct peer *peer)
+{
+ /* If withdraw FIFO exists, immediately schedule write */
+ if (bgp_peer_wd_fifo_exists(peer) && !peer->t_write)
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s scheduling write thread", peer->host);
+ BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ }
+
+ /* If update FIFO exists, fire MRAI timer */
+ if (bgp_peer_adv_fifo_exists(peer, 0) && !peer->radv_adjusted)
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s scheduling MRAI timer", peer->host);
+ bgp_adjust_routeadv(peer);
+ }
+}
+
+/* Is there partially written packet or updates we can send right
+ now. */
+static int
+bgp_write_proceed (struct peer *peer)
+{
+ /* If queued packet exists, we should try to write it */
+ if (stream_fifo_head (peer->obuf))
+ return 1;
+
+ /* If there are prefixes to be withdrawn or to be advertised (and
+ * queued before last MRAI timer expiry), schedule write
+ */
+ if (bgp_peer_wd_fifo_exists(peer)
+ || bgp_peer_adv_fifo_exists(peer, 1))
+ return 1;
return 0;
}
@@ -680,6 +796,7 @@ bgp_write (struct thread *thread)
struct stream *s;
int num;
unsigned int count = 0;
+ unsigned int oc = 0;
/* Yes first of all get peer pointer. */
peer = THREAD_ARG (thread);
@@ -688,7 +805,7 @@ bgp_write (struct thread *thread)
/* For non-blocking IO check. */
if (peer->status == Connect)
{
- bgp_connect_check (peer);
+ bgp_connect_check (peer, 1);
return 0;
}
@@ -698,6 +815,8 @@ bgp_write (struct thread *thread)
sockopt_cork (peer->fd, 1);
+ oc = peer->update_out;
+
/* Nonblocking write until TCP output buffer is full. */
do
{
@@ -765,13 +884,17 @@ bgp_write (struct thread *thread)
/* OK we send packet so delete it. */
bgp_packet_delete (peer);
}
- while (++count < BGP_WRITE_PACKET_MAX &&
+ while (++count < peer->bgp->wpkt_quanta &&
(s = bgp_write_packet (peer)) != NULL);
-
+
if (bgp_write_proceed (peer))
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
done:
+ /* Update the last write if some updates were written. */
+ if (peer->update_out > oc)
+ peer->last_write = bgp_clock ();
+
sockopt_cork (peer->fd, 0);
return 0;
}
@@ -826,6 +949,8 @@ bgp_write_notify (struct peer *peer)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
+ /* Handle Graceful Restart case where the state changes to
+ Connect instead of Idle */
BGP_EVENT_ADD (peer, BGP_Stop);
return 0;
@@ -836,7 +961,6 @@ void
bgp_keepalive_send (struct peer *peer)
{
struct stream *s;
- int length;
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -844,16 +968,13 @@ bgp_keepalive_send (struct peer *peer)
bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
/* Set packet size. */
- length = bgp_packet_set_size (s);
+ (void)bgp_packet_set_size (s);
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
- if (BGP_DEBUG (keepalive, KEEPALIVE))
+ if (bgp_debug_keepalive(peer))
zlog_debug ("%s sending KEEPALIVE", peer->host);
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_KEEPALIVE, length);
/* Add packet to the peer. */
bgp_packet_add (peer, s);
@@ -866,7 +987,6 @@ void
bgp_open_send (struct peer *peer)
{
struct stream *s;
- int length;
u_int16_t send_holdtime;
as_t local_as;
@@ -897,17 +1017,13 @@ bgp_open_send (struct peer *peer)
bgp_open_capability (s, peer);
/* Set BGP packet length. */
- length = bgp_packet_set_size (s);
+ (void)bgp_packet_set_size (s);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
peer->host, BGP_VERSION_4, local_as,
send_holdtime, inet_ntoa (peer->local_id));
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_OPEN, length);
-
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
@@ -984,33 +1100,16 @@ bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
}
}
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_NOTIFY, length);
-
/* peer reset cause */
if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
{
if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
- {
peer->last_reset = PEER_DOWN_USER_RESET;
- zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
- }
else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
- {
peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
- zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
- }
else
- {
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
- zlog_info ("Notification sent to neighbor %s: type %u/%u",
- peer->host, code, sub_code);
- }
}
- else
- zlog_info ("Notification sent to neighbor %s: configuration change",
- peer->host);
/* Call immediately. */
BGP_WRITE_OFF (peer->t_write);
@@ -1031,7 +1130,6 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
u_char orf_type, u_char when_to_refresh, int remove)
{
struct stream *s;
- int length;
struct bgp_filter *filter;
int orf_refresh = 0;
@@ -1074,7 +1172,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
{
UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
@@ -1086,7 +1184,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
ORF_COMMON_PART_DENY);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
@@ -1099,16 +1197,13 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
}
/* Set packet size. */
- length = bgp_packet_set_size (s);
+ (void)bgp_packet_set_size (s);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
if (! orf_refresh)
zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi);
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
- BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
}
/* Add packet to the peer. */
@@ -1123,7 +1218,6 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
int capability_code, int action)
{
struct stream *s;
- int length;
/* Adjust safi code. */
if (safi == SAFI_MPLS_VPN)
@@ -1144,23 +1238,18 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
stream_putc (s, 0);
stream_putc (s, safi);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
peer->host, action == CAPABILITY_ACTION_SET ?
"Advertising" : "Removing", afi, safi);
}
/* Set packet size. */
- length = bgp_packet_set_size (s);
-
+ (void)bgp_packet_set_size (s);
/* Add packet to the peer. */
bgp_packet_add (peer, s);
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_CAPABILITY, length);
-
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
}
@@ -1169,13 +1258,7 @@ static int
bgp_collision_detect (struct peer *new, struct in_addr remote_id)
{
struct peer *peer;
- struct listnode *node, *nnode;
- struct bgp *bgp;
- bgp = bgp_get_default ();
- if (! bgp)
- return 0;
-
/* Upon receipt of an OPEN message, the local system must examine
all of its connections that are in the OpenConfirm state. A BGP
speaker may also examine connections in an OpenSent state if it
@@ -1185,31 +1268,42 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
OPEN message, then the local system performs the following
collision resolution procedure: */
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if ((peer = new->doppelganger) != NULL)
{
- /* Under OpenConfirm status, local peer structure already hold
- remote router ID. */
-
- if (peer != new
- && (peer->status == OpenConfirm || peer->status == OpenSent)
- && sockunion_same (&peer->su, &new->su))
+ /* Do not accept the new connection in Established or Clearing states.
+ * Note that a peer GR is handled by closing the existing connection
+ * upon receipt of new one.
+ */
+ if (peer->status == Established || peer->status == Clearing)
+ {
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return (-1);
+ }
+ else if ((peer->status == OpenConfirm) || (peer->status == OpenSent))
{
/* 1. The BGP Identifier of the local system is compared to
the BGP Identifier of the remote system (as specified in
the OPEN message). */
if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
- {
- /* 2. If the value of the local BGP Identifier is less
- than the remote one, the local system closes BGP
- connection that already exists (the one that is
- already in the OpenConfirm state), and accepts BGP
- connection initiated by the remote system. */
-
- if (peer->fd >= 0)
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
- return 1;
- }
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ {
+ /* 2. If the value of the local BGP Identifier is less
+ than the remote one, the local system closes BGP
+ connection that already exists (the one that is
+ already in the OpenConfirm state), and accepts BGP
+ connection initiated by the remote system. */
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return 1;
+ }
+ else
+ {
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return -1;
+ }
else
{
/* 3. Otherwise, the local system closes newly created
@@ -1217,11 +1311,18 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
received OPEN message), and continues to use the
existing one (the one that is already in the
OpenConfirm state). */
-
- if (new->fd >= 0)
- bgp_notify_send (new, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
- return -1;
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ {
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return 1;
+ }
+ else
+ {
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return -1;
+ }
}
}
}
@@ -1238,24 +1339,23 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
u_int16_t send_holdtime;
as_t remote_as;
as_t as4 = 0;
- struct peer *realpeer;
struct in_addr remote_id;
int mp_capability;
u_int8_t notify_data_remote_as[2];
u_int8_t notify_data_remote_id[4];
+ u_int16_t *holdtime_ptr;
- realpeer = NULL;
-
/* Parse open packet. */
version = stream_getc (peer->ibuf);
memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
remote_as = stream_getw (peer->ibuf);
+ holdtime_ptr = (u_int16_t *)stream_pnt (peer->ibuf);
holdtime = stream_getw (peer->ibuf);
memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
/* Receive OPEN message log */
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
" holdtime %d, id %s",
peer->host, version, remote_as, holdtime,
@@ -1294,8 +1394,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_BAD_PEER_AS);
+ bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_BAD_PEER_AS);
return -1;
}
@@ -1325,154 +1425,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
}
}
- /* Lookup peer from Open packet. */
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- int as = 0;
-
- realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
-
- if (! realpeer)
- {
- /* Peer's source IP address is check in bgp_accept(), so this
- must be AS number mismatch or remote-id configuration
- mismatch. */
- if (as)
- {
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s bad OPEN, wrong router identifier %s",
- peer->host, inet_ntoa (remote_id));
- bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
- notify_data_remote_id, 4);
- }
- else
- {
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
- peer->host, remote_as, peer->as);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_BAD_PEER_AS,
- notify_data_remote_as, 2);
- }
- return -1;
- }
- }
-
- /* When collision is detected and this peer is closed. Retrun
- immidiately. */
- ret = bgp_collision_detect (peer, remote_id);
- if (ret < 0)
- return ret;
-
- /* Hack part. */
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- if (realpeer->status == Established
- && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
- {
- realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
- SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
- }
- else if (ret == 0 && realpeer->status != Active
- && realpeer->status != OpenSent
- && realpeer->status != OpenConfirm
- && realpeer->status != Connect)
- {
- /* XXX: This is an awful problem..
- *
- * According to the RFC we should just let this connection (of the
- * accepted 'peer') continue on to Established if the other
- * connection (the 'realpeer' one) is in state Connect, and deal
- * with the more larval FSM as/when it gets far enough to receive
- * an Open. We don't do that though, we instead close the (more
- * developed) accepted connection.
- *
- * This means there's a race, which if hit, can loop:
- *
- * FSM for A FSM for B
- * realpeer accept-peer realpeer accept-peer
- *
- * Connect Connect
- * Active
- * OpenSent OpenSent
- * <arrive here,
- * Notify, delete>
- * Idle Active
- * OpenSent OpenSent
- * <arrive here,
- * Notify, delete>
- * Idle
- * <wait> <wait>
- * Connect Connect
- *
- *
- * If both sides are Quagga, they're almost certain to wait for
- * the same amount of time of course (which doesn't preclude other
- * implementations also waiting for same time). The race is
- * exacerbated by high-latency (in bgpd and/or the network).
- *
- * The reason we do this is because our FSM is tied to our peer
- * structure, which carries our configuration information, etc.
- * I.e. we can't let the accepted-peer FSM continue on as it is,
- * cause it's not associated with any actual peer configuration -
- * it's just a dummy.
- *
- * It's possible we could hack-fix this by just bgp_stop'ing the
- * realpeer and continueing on with the 'transfer FSM' below.
- * Ideally, we need to seperate FSMs from struct peer.
- *
- * Setting one side to passive avoids the race, as a workaround.
- */
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s peer status is %s close connection",
- realpeer->host, LOOKUP (bgp_status_msg,
- realpeer->status));
- bgp_notify_send (peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONNECT_REJECT);
-
- return -1;
- }
-
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
- peer->host,
- LOOKUP (bgp_status_msg, realpeer->status));
-
- bgp_stop (realpeer);
-
- /* Transfer file descriptor. */
- realpeer->fd = peer->fd;
- peer->fd = -1;
-
- /* Transfer input buffer. */
- stream_free (realpeer->ibuf);
- realpeer->ibuf = peer->ibuf;
- realpeer->packet_size = peer->packet_size;
- peer->ibuf = NULL;
-
- /* Transfer status. */
- realpeer->status = peer->status;
- bgp_stop (peer);
-
- /* peer pointer change. Open packet send to neighbor. */
- peer = realpeer;
- bgp_open_send (peer);
- if (peer->fd < 0)
- {
- zlog_err ("bgp_open_receive peer's fd is negative value %d",
- peer->fd);
- return -1;
- }
- BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
- }
-
/* remote router-id check. */
if (remote_id.s_addr == 0
|| IPV4_CLASS_DE (ntohl (remote_id.s_addr))
|| ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s bad OPEN, wrong router identifier %s",
peer->host, inet_ntoa (remote_id));
bgp_notify_send_with_data (peer,
@@ -1490,7 +1448,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
u_int16_t maxver = htons(BGP_VERSION_4);
/* XXX this reply may not be correct if version < 4 XXX */
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
peer->host, version, BGP_VERSION_4);
/* Data must be in network byte order here */
@@ -1504,7 +1462,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
/* Check neighbor as number. */
if (remote_as != peer->as)
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
peer->host, remote_as, peer->as);
bgp_notify_send_with_data (peer,
@@ -1522,9 +1480,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (holdtime < 3 && holdtime != 0)
{
- bgp_notify_send (peer,
- BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_UNACEP_HOLDTIME,
+ (u_int8_t *)holdtime_ptr, 2);
return -1;
}
@@ -1559,7 +1518,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
}
else
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
peer->host);
}
@@ -1578,11 +1537,28 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
}
+ /* When collision is detected and this peer is closed. Retrun
+ immidiately. */
+ ret = bgp_collision_detect (peer, remote_id);
+ if (ret < 0)
+ return ret;
+
/* Get sockname. */
- bgp_getsockname (peer);
+ if ((ret = bgp_getsockname (peer)) < 0)
+ {
+ zlog_err("%s: bgp_getsockname() failed for peer: %s", __FUNCTION__,
+ peer->host);
+ return (ret);
+ }
peer->rtt = sockopt_tcp_rtt (peer->fd);
- BGP_EVENT_ADD (peer, Receive_OPEN_message);
+ if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0)
+ {
+ zlog_err("%s: BGP event update failed for peer: %s", __FUNCTION__,
+ peer->host);
+ /* DD: bgp send notify and reset state */
+ return (ret);
+ }
peer->packet_size = 0;
if (peer->ibuf)
@@ -1609,6 +1585,117 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
return -1;
}
+/* Called when there is a change in the EOR(implicit or explicit) status of a peer.
+ Ends the update-delay if all expected peers are done with EORs. */
+void
+bgp_check_update_delay(struct bgp *bgp)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer = NULL;
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Checking update delay, T: %d R: %d I:%d E: %d", bgp->established,
+ bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors);
+
+ if (bgp->established <=
+ bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors)
+ {
+ /* This is an extra sanity check to make sure we wait for all the
+ eligible configured peers. This check is performed if establish wait
+ timer is on, or establish wait option is not given with the
+ update-delay command */
+ if (bgp->t_establish_wait ||
+ (bgp->v_establish_wait == bgp->v_update_delay))
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
+ && !CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
+ && !peer->update_delay_over)
+ {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug (" Peer %s pending, continuing read-only mode",
+ peer->host);
+ return;
+ }
+ }
+
+ zlog_info ("Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d",
+ bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors);
+ bgp_update_delay_end(bgp);
+ }
+}
+
+/* Called if peer is known to have restarted. The restart-state bit in
+ Graceful-Restart capability is used for that */
+void
+bgp_update_restarted_peers (struct peer *peer)
+{
+ if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
+ if (peer->update_delay_over) return; /* This peer has already been considered */
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Peer %s: Checking restarted", peer->host);
+
+ if (peer->status == Established)
+ {
+ peer->update_delay_over = 1;
+ peer->bgp->restarted_peers++;
+ bgp_check_update_delay(peer->bgp);
+ }
+}
+
+/* Called as peer receives a keep-alive. Determines if this occurence can be
+ taken as an implicit EOR for this peer.
+ NOTE: The very first keep-alive after the Established state of a peer is
+ considered implicit EOR for the update-delay purposes */
+void
+bgp_update_implicit_eors (struct peer *peer)
+{
+ if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
+ if (peer->update_delay_over) return; /* This peer has already been considered */
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Peer %s: Checking implicit EORs", peer->host);
+
+ if (peer->status == Established)
+ {
+ peer->update_delay_over = 1;
+ peer->bgp->implicit_eors++;
+ bgp_check_update_delay(peer->bgp);
+ }
+}
+
+/* Should be called only when there is a change in the EOR_RECEIVED status
+ for any afi/safi on a peer */
+static void
+bgp_update_explicit_eors (struct peer *peer)
+{
+ afi_t afi;
+ safi_t safi;
+
+ if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
+ if (peer->update_delay_over) return; /* This peer has already been considered */
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Peer %s: Checking explicit EORs", peer->host);
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ if (peer->afc_nego[afi][safi] &&
+ !CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED))
+ {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug (" afi %d safi %d didnt receive EOR", afi, safi);
+ return;
+ }
+ }
+
+ peer->update_delay_over = 1;
+ peer->bgp->explicit_eors++;
+ bgp_check_update_delay(peer->bgp);
+}
+
/* Parse BGP Update packet and make attribute object. */
static int
bgp_update_receive (struct peer *peer, bgp_size_t size)
@@ -1646,6 +1733,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
memset (&extra, 0, sizeof (struct attr_extra));
memset (&nlris, 0, sizeof nlris);
attr.extra = &extra;
+ memset (peer->rcvd_attr_str, 0, BUFSIZ);
+ peer->rcvd_attr_printed = 0;
s = peer->ibuf;
end = stream_pnt (s) + size;
@@ -1686,8 +1775,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
nlris[NLRI_WITHDRAW].nlri = stream_pnt (s);
nlris[NLRI_WITHDRAW].length = withdraw_len;
- if (BGP_DEBUG (packet, PACKET_RECV))
- zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
+ zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
stream_forward_getp (s, withdraw_len);
}
@@ -1744,24 +1832,21 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
}
/* Logging the attribute. */
- if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
- || BGP_DEBUG (update, UPDATE_IN))
+ if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW ||
+ BGP_DEBUG (update, UPDATE_IN) ||
+ BGP_DEBUG (update, UPDATE_PREFIX))
{
- char attrstr[BUFSIZ];
- attrstr[0] = '\0';
-
- ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
- int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
- ? LOG_ERR : LOG_DEBUG;
+ ret = bgp_dump_attr (peer, &attr, peer->rcvd_attr_str, BUFSIZ);
if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
- zlog (peer->log, LOG_ERR,
- "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
- peer->host);
+ zlog_err ("%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
+ peer->host);
- if (ret)
- zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
- peer->host, attrstr);
+ if (ret && bgp_debug_update(peer, NULL, 1))
+ {
+ zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str);
+ peer->rcvd_attr_printed = 1;
+ }
}
/* Network Layer Reachability Information. */
@@ -1796,8 +1881,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
*/
if (!bgp_afi_safi_valid_indices (nlris[i].afi, &nlris[i].safi))
{
- plog_info (peer->log,
- "%s [Info] UPDATE with unsupported AFI/SAFI %u/%u",
+ zlog_info ("%s [Info] UPDATE with unsupported AFI/SAFI %u/%u",
peer->host, nlris[i].afi, nlris[i].safi);
continue;
}
@@ -1806,8 +1890,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
Address Family and Subsequent Address Family. */
if (!peer->afc[nlris[i].afi][nlris[i].safi])
{
- plog_info (peer->log,
- "%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u",
+ zlog_info ("%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u",
peer->host, nlris[i].afi, nlris[i].safi);
continue;
}
@@ -1829,8 +1912,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (nlri_ret < 0)
{
- plog_err (peer->log,
- "%s [Error] Error parsing NLRI", peer->host);
+ zlog_err ("%s [Error] Error parsing NLRI", peer->host);
if (peer->status == Established)
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
i <= NLRI_WITHDRAW
@@ -1877,14 +1959,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* End-of-RIB received */
SET_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED);
+ if (!CHECK_FLAG (peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED))
+ {
+ SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
+ PEER_STATUS_EOR_RECEIVED);
+ bgp_update_explicit_eors(peer);
+ }
/* NSF delete stale route */
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
- if (BGP_DEBUG (normal, NORMAL))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for %s from %s",
- peer->host, afi_safi_print (afi, safi));
+ zlog_debug ("rcvd End-of-RIB for %s from %s",
+ peer->host, afi_safi_print (afi, safi));
}
}
@@ -1991,7 +2079,7 @@ bgp_notify_receive (struct peer *peer, bgp_size_t size)
static void
bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
{
- if (BGP_DEBUG (keepalive, KEEPALIVE))
+ if (bgp_debug_keepalive(peer))
zlog_debug ("%s KEEPALIVE rcvd", peer->host);
BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
@@ -2008,7 +2096,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* If peer does not have the capability, send notification. */
if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
{
- plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
+ zlog_err ("%s [Error] BGP route refresh is not enabled",
peer->host);
bgp_notify_send (peer,
BGP_NOTIFY_HEADER_ERR,
@@ -2019,8 +2107,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* Status must be Established. */
if (peer->status != Established)
{
- plog_err (peer->log,
- "%s [Error] Route refresh packet received under status %s",
+ zlog_err ("%s [Error] Route refresh packet received under status %s",
peer->host, LOOKUP (bgp_status_msg, peer->status));
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
return;
@@ -2034,7 +2121,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
stream_getc (s);
safi = stream_getc (s);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_update(peer, NULL, 0))
zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi);
@@ -2043,11 +2130,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|| (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
&& safi != SAFI_MPLS_LABELED_VPN))
{
- if (BGP_DEBUG (normal, NORMAL))
- {
- zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
- peer->host, afi, safi);
- }
+ zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
+ peer->host, afi, safi);
return;
}
@@ -2092,7 +2176,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
char name[BUFSIZ];
int ret;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
peer->host, orf_type, orf_len);
@@ -2119,7 +2203,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* after ++: p_pnt <= p_end */
if (common & ORF_COMMON_PART_REMOVE_ALL)
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
prefix_bgp_orf_remove_all (afi, name);
break;
@@ -2158,7 +2242,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
memcpy (&orfp.p.u.prefix, p_pnt, psize);
p_pnt += psize;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
char buf[INET6_BUFSIZ];
@@ -2179,9 +2263,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
if (!ok || (ok && ret != CMD_SUCCESS))
{
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s Received misformatted prefixlist ORF."
- " Remove All pfxlist", peer->host);
+ zlog_info ("%s Received misformatted prefixlist ORF."
+ " Remove All pfxlist", peer->host);
prefix_bgp_orf_remove_all (afi, name);
break;
}
@@ -2191,7 +2274,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
}
stream_forward_getp (s, orf_len);
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
if (when_to_refresh == REFRESH_DEFER)
@@ -2240,7 +2323,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
return -1;
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
peer->host, action, hdr->code, hdr->length);
@@ -2267,14 +2350,14 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
if (!bgp_afi_safi_valid_indices (afi, &safi))
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
"(%u/%u)", peer->host, afi, safi);
continue;
}
/* Address family check. */
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
peer->host,
action == CAPABILITY_ACTION_SET
@@ -2323,13 +2406,13 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
/* Fetch pointer. */
pnt = stream_pnt (peer->ibuf);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcv CAPABILITY", peer->host);
/* If peer does not have the capability, send notification. */
if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
{
- plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
+ zlog_err ("%s [Error] BGP dynamic capability is not enabled",
peer->host);
bgp_notify_send (peer,
BGP_NOTIFY_HEADER_ERR,
@@ -2340,8 +2423,8 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
/* Status must be Established. */
if (peer->status != Established)
{
- plog_err (peer->log,
- "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
+ zlog_err ("%s [Error] Dynamic capability packet received under status %s",
+ peer->host, LOOKUP (bgp_status_msg, peer->status));
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
return -1;
}
@@ -2373,8 +2456,8 @@ bgp_read_packet (struct peer *peer)
if (nbytes == -2)
return -1;
- plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
- peer->host, safe_strerror (errno));
+ zlog_err ("%s [Error] bgp_read_packet error: %s",
+ peer->host, safe_strerror (errno));
if (peer->status == Established)
{
@@ -2394,9 +2477,9 @@ bgp_read_packet (struct peer *peer)
/* When read byte is zero : clear bgp peer and return */
if (nbytes == 0)
{
- if (BGP_DEBUG (events, EVENTS))
- plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
- peer->host, peer->fd);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [Event] BGP connection closed fd %d",
+ peer->host, peer->fd);
if (peer->status == Established)
{
@@ -2451,15 +2534,19 @@ bgp_read (struct thread *thread)
struct peer *peer;
bgp_size_t size;
char notify_data_length[2];
+ u_int32_t notify_out;
/* Yes first of all get peer pointer. */
peer = THREAD_ARG (thread);
peer->t_read = NULL;
+ /* Note notify_out so we can check later to see if we sent another one */
+ notify_out = peer->notify_out;
+
/* For non-blocking IO check. */
if (peer->status == Connect)
{
- bgp_connect_check (peer);
+ bgp_connect_check (peer, 1);
goto done;
}
else
@@ -2490,10 +2577,6 @@ bgp_read (struct thread *thread)
size = stream_getw (peer->ibuf);
type = stream_getc (peer->ibuf);
- if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
- zlog_debug ("%s rcv message type %d, length (excl. header) %d",
- peer->host, type, size - BGP_HEADER_SIZE);
-
/* Marker check */
if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
&& ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
@@ -2511,10 +2594,9 @@ bgp_read (struct thread *thread)
&& type != BGP_MSG_ROUTE_REFRESH_OLD
&& type != BGP_MSG_CAPABILITY)
{
- if (BGP_DEBUG (normal, NORMAL))
- plog_debug (peer->log,
- "%s unknown message type 0x%02x",
- peer->host, type);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s unknown message type 0x%02x",
+ peer->host, type);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESTYPE,
@@ -2532,12 +2614,11 @@ bgp_read (struct thread *thread)
|| (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
|| (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
{
- if (BGP_DEBUG (normal, NORMAL))
- plog_debug (peer->log,
- "%s bad message length - %d for %s",
- peer->host, size,
- type == 128 ? "ROUTE-REFRESH" :
- bgp_type_str[(int) type]);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s bad message length - %d for %s",
+ peer->host, size,
+ type == 128 ? "ROUTE-REFRESH" :
+ bgp_type_str[(int) type]);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESLEN,
@@ -2591,17 +2672,30 @@ bgp_read (struct thread *thread)
break;
}
+ /* If reading this packet caused us to send a NOTIFICATION then store a copy
+ * of the packet for troubleshooting purposes
+ */
+ if (notify_out < peer->notify_out)
+ {
+ memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size);
+ peer->last_reset_cause_size = peer->packet_size;
+ notify_out = peer->notify_out;
+ }
+
/* Clear input buffer. */
peer->packet_size = 0;
if (peer->ibuf)
stream_reset (peer->ibuf);
done:
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ /* If reading this packet caused us to send a NOTIFICATION then store a copy
+ * of the packet for troubleshooting purposes
+ */
+ if (notify_out < peer->notify_out)
{
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
- peer_delete (peer);
+ memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size);
+ peer->last_reset_cause_size = peer->packet_size;
}
+
return 0;
}