* bgp_fsm.c, bgp_open.c, bgp_packet.c, bgp_route.[ch], bgp_vty.c,

bgpd.[ch]: Add BGP_INFO_STALE flag and end-of-rib support. "bgp
	  graceful-restart" commands added. Show numbers of individual
	  messages in "show ip bgp neighbor" command. Final pieces of graceful
	  restart.

	[merge from GNU Zebra]
This commit is contained in:
hasso 2005-02-02 14:40:33 +00:00
parent c9502438e8
commit 93406d87e6
9 changed files with 544 additions and 82 deletions

View File

@ -1,3 +1,11 @@
2005-02-02 Akihiro Mizutani <mizutani@net-chef.net
* bgp_fsm.c, bgp_open.c, bgp_packet.c, bgp_route.[ch], bgp_vty.c,
bgpd.[ch]: Add BGP_INFO_STALE flag and end-of-rib support. "bgp
graceful-restart" commands added. Show numbers of individual
messages in "show ip bgp neighbor" command. Final pieces of graceful
restart.
2005-02-01 Akihiro Mizutani <mizutani@net-chef.net>
* bgp_open.c, bgp_packet.c, bgp_vty.c, bgpd.[ch]: Remove "no neighbor

View File

@ -118,7 +118,8 @@ bgp_timer_set (struct peer *peer)
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))
if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)
|| CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
{
BGP_TIMER_OFF (peer->t_connect);
}
@ -331,9 +332,62 @@ const char *peer_down_str[] =
"Peer-group delete member",
"Capability changed",
"Passive config change",
"Multihop config change"
"Multihop config change",
"NSF peer closed the session"
};
int
bgp_graceful_restart_timer_expire (struct thread *thread)
{
struct peer *peer;
afi_t afi;
safi_t safi;
peer = THREAD_ARG (thread);
peer->t_gr_restart = NULL;
/* NSF delete stale route */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
BGP_TIMER_OFF (peer->t_gr_stale);
if (BGP_DEBUG (events, EVENTS))
{
zlog_debug ("%s graceful restart timer expired", peer->host);
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
bgp_timer_set (peer);
return 0;
}
int
bgp_graceful_stale_timer_expire (struct thread *thread)
{
struct peer *peer;
afi_t afi;
safi_t safi;
peer = THREAD_ARG (thread);
peer->t_gr_stale = NULL;
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
/* NSF delete stale route */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
return 0;
}
/* Administrative BGP peer stop event. */
int
bgp_stop (struct peer *peer)
@ -353,6 +407,36 @@ bgp_stop (struct peer *peer)
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_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
{
if (BGP_DEBUG (events, EVENTS))
{
zlog_debug ("%s graceful restart timer started for %d sec",
peer->host, peer->v_gr_restart);
zlog_debug ("%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);
/* Reset uptime. */
@ -655,6 +739,7 @@ bgp_establish (struct peer *peer)
struct bgp_notify *notify;
afi_t afi;
safi_t safi;
int nsf_af_count = 0;
/* Reset capability open status flag. */
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
@ -677,6 +762,50 @@ bgp_establish (struct peer *peer)
if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
zlog_info ("%%ADJCHANGE: neighbor %s Up", peer->host);
/* graceful restart */
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
{
if (peer->afc_nego[afi][safi]
&& CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
&& CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
{
if (peer->nsf[afi][safi]
&& ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV))
bgp_clear_stale_route (peer, afi, safi);
peer->nsf[afi][safi] = 1;
nsf_af_count++;
}
else
{
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
peer->nsf[afi][safi] = 0;
}
}
if (nsf_af_count)
SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
else
{
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
if (peer->t_gr_stale)
{
BGP_TIMER_OFF (peer->t_gr_stale);
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
}
if (peer->t_gr_restart)
{
BGP_TIMER_OFF (peer->t_gr_restart);
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s graceful restart timer stopped", peer->host);
}
#ifdef HAVE_SNMP
bgpTrapEstablished (peer);
#endif /* HAVE_SNMP */

View File

@ -401,7 +401,6 @@ bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
struct graceful_restart_af graf;
u_int16_t restart_flag_time;
int restart_bit = 0;
int forwarding_bit = 0;
u_char *restart_pnt;
u_char *restart_end;
@ -418,15 +417,15 @@ bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
restart_flag_time = ntohs(cap.mpc.afi);
if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
restart_bit = 1;
UNSET_FLAG (restart_flag_time, 0xF000);
peer->restart_time_rcv = restart_flag_time;
UNSET_FLAG (restart_flag_time, 0xF000);
peer->v_gr_restart = restart_flag_time;
if (BGP_DEBUG (normal, NORMAL))
{
zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
peer->host, restart_bit ? " " : " not ",
peer->restart_time_rcv);
peer->v_gr_restart);
}
restart_pnt = pnt + 4;
@ -440,7 +439,7 @@ bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
safi = graf.safi;
if (CHECK_FLAG (graf.flag, RESTART_F_BIT))
forwarding_bit = 1;
SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
if (strcmp (afi_safi_print (afi, safi), "Unknown") == 0)
{
@ -458,12 +457,13 @@ bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
{
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s Address family %s is%spreserved", peer->host,
afi_safi_print (afi, safi), forwarding_bit ? " " : " not ");
afi_safi_print (afi, safi),
CHECK_FLAG (peer->af_cap[afi][safi],
PEER_CAP_RESTART_AF_PRESERVE_RCV)
? " " : " not ");
if (forwarding_bit)
SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
}
forwarding_bit = 0;
restart_pnt += 4;
}
}

View File

@ -46,6 +46,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_network.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h"
int stream_put_prefix (struct stream *, struct prefix *);
@ -243,7 +244,50 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
return packet;
}
return NULL;
}
struct stream *
bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
{
struct stream *s;
struct stream *packet;
#ifdef DISABLE_BGP_ANNOUNCE
return;
#endif /* DISABLE_BGP_ANNOUNCE */
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
s = stream_new (BGP_MAX_PACKET_SIZE);
/* Make BGP update packet. */
bgp_packet_set_marker (s, BGP_MSG_UPDATE);
/* Unfeasible Routes Length */
stream_putw (s, 0);
if (afi == AFI_IP && safi == SAFI_UNICAST)
{
/* Total Path Attribute Length */
stream_putw (s, 0);
}
else
{
/* Total Path Attribute Length */
stream_putw (s, 6);
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
stream_putc (s, 3);
stream_putw (s, afi);
stream_putc (s, safi);
}
bgp_packet_set_size (s);
packet = bgp_packet_dup (s);
bgp_packet_add (peer, packet);
stream_free (s);
return packet;
}
/* Make BGP withdraw packet. */
@ -504,11 +548,34 @@ bgp_write_packet (struct peer *peer)
if (adv)
{
if (adv->binfo && adv->binfo->uptime < peer->synctime)
s = bgp_update_packet (peer, afi, safi);
{
if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
&& CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
&& ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
&& safi != SAFI_MPLS_VPN)
{
if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED))
s = bgp_update_packet (peer, afi, safi);
}
else
s = bgp_update_packet (peer, afi, safi);
}
if (s)
return s;
}
if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
{
if (peer->afc_nego[afi][safi] && peer->synctime
&& ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
&& safi != SAFI_MPLS_VPN)
{
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
return bgp_update_packet_eor (peer, afi, safi);
}
}
}
return NULL;
@ -1192,13 +1259,24 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
/* Hack part. */
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
{
if (ret == 0 && realpeer->status != Active
&& realpeer->status != OpenSent
&& realpeer->status != OpenConfirm)
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)
{
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s [Event] peer's status is %s close connection",
realpeer->host, LOOKUP (bgp_status_msg, peer->status));
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;
}
@ -1524,8 +1602,14 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (! attribute_len && ! withdraw_len)
{
/* End-of-RIB received */
SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
PEER_STATUS_EOR_RECEIVED);
if (BGP_DEBUG (update, UPDATE_IN))
/* NSF delete stale route */
if (peer->nsf[AFI_IP][SAFI_UNICAST])
bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
if (BGP_DEBUG (normal, NORMAL))
zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
peer->host);
}
@ -1542,14 +1626,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
&& mp_withdraw.safi == SAFI_MULTICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
if (attribute_len == 6 && ! withdraw_len
if (! withdraw_len
&& mp_withdraw.afi == AFI_IP
&& mp_withdraw.safi == SAFI_MULTICAST
&& mp_withdraw.length == 0)
{
/* End-of-RIB received */
SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
PEER_STATUS_EOR_RECEIVED);
if (BGP_DEBUG (update, UPDATE_IN))
/* NSF delete stale route */
if (peer->nsf[AFI_IP][SAFI_MULTICAST])
bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
if (BGP_DEBUG (normal, NORMAL))
zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
peer->host);
}
@ -1566,14 +1656,19 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
&& mp_withdraw.safi == SAFI_UNICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
if (attribute_len == 6 && ! withdraw_len
if (! withdraw_len
&& mp_withdraw.afi == AFI_IP6
&& mp_withdraw.safi == SAFI_UNICAST
&& mp_withdraw.length == 0)
{
/* End-of-RIB received */
SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
if (BGP_DEBUG (update, UPDATE_IN))
/* NSF delete stale route */
if (peer->nsf[AFI_IP6][SAFI_UNICAST])
bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
if (BGP_DEBUG (normal, NORMAL))
zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
peer->host);
}
@ -1590,13 +1685,17 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
&& mp_withdraw.safi == SAFI_MULTICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
if (attribute_len == 6 && ! withdraw_len
if (! withdraw_len
&& mp_withdraw.afi == AFI_IP6
&& mp_withdraw.safi == SAFI_MULTICAST
&& mp_withdraw.length == 0)
{
/* End-of-RIB received */
/* NSF delete stale route */
if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
if (BGP_DEBUG (update, UPDATE_IN))
zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
peer->host);
@ -1614,7 +1713,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
&& mp_withdraw.safi == BGP_SAFI_VPNV4)
bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
if (attribute_len == 6 && ! withdraw_len
if (! withdraw_len
&& mp_withdraw.afi == AFI_IP
&& mp_withdraw.safi == BGP_SAFI_VPNV4
&& mp_withdraw.length == 0)
@ -2080,6 +2179,18 @@ bgp_read_packet (struct peer *peer)
plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
peer->host, safe_strerror (errno));
if (peer->status == Established)
{
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
{
peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
}
else
peer->last_reset = PEER_DOWN_CLOSE_SESSION;
}
BGP_EVENT_ADD (peer, TCP_fatal_error);
return -1;
}
@ -2092,7 +2203,15 @@ bgp_read_packet (struct peer *peer)
peer->host, peer->fd);
if (peer->status == Established)
peer->last_reset = PEER_DOWN_CLOSE_SESSION;
{
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
{
peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
}
else
peer->last_reset = PEER_DOWN_CLOSE_SESSION;
}
BGP_EVENT_ADD (peer, TCP_connection_closed);
return -1;

View File

@ -1393,7 +1393,8 @@ bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY) &&
rn->table->type == BGP_TABLE_MAIN)
{
peer->pcount[afi][safi]--;
if (! CHECK_FLAG (ri->flags, BGP_INFO_STALE))
peer->pcount[afi][safi]--;
bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
}
@ -1780,6 +1781,13 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
peer->host,
inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
p->prefixlen);
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
{
UNSET_FLAG (ri->flags, BGP_INFO_STALE);
peer->pcount[afi][safi]++;
}
}
bgp_unlock_node (rn);
@ -1794,6 +1802,13 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
p->prefixlen);
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
{
UNSET_FLAG (ri->flags, BGP_INFO_STALE);
peer->pcount[afi][safi]++;
}
/* The attribute is changed. */
SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
@ -2255,7 +2270,18 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == peer)
{
bgp_rib_remove (rn, ri, peer, afi, safi);
/* graceful restart STALE flag set. */
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)
&& peer->nsf[afi][safi]
&& ! CHECK_FLAG (ri->flags, BGP_INFO_STALE)
&& ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
&& ! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
{
SET_FLAG (ri->flags, BGP_INFO_STALE);
peer->pcount[afi][safi]--;
}
else
bgp_rib_remove (rn, ri, peer, afi, safi);
break;
}
for (ain = rn->adj_in; ain; ain = ain->next)
@ -2327,6 +2353,27 @@ bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi)
break;
}
}
void
bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp_node *rn;
struct bgp_info *ri;
struct bgp_table *table;
table = peer->bgp->rib[afi][safi];
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
{
for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == peer)
{
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
bgp_rib_remove (rn, ri, peer, afi, safi);
break;
}
}
}
/* Delete all kernel routes. */
void
@ -4725,7 +4772,9 @@ route_vty_out (struct vty *vty, struct prefix *p,
struct attr *attr;
/* Route status display. */
if (binfo->suppress)
if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
vty_out (vty, "S");
else if (binfo->suppress)
vty_out (vty, "s");
else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, "*");
@ -5106,26 +5155,19 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
aspath_print_vty (vty, attr->aspath);
}
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)
|| CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)
|| CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
|| CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)
|| CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
{
vty_out (vty, ",");
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))
vty_out (vty, " (aggregated by %d %s)", attr->aggregator_as,
inet_ntoa (attr->aggregator_addr));
if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
vty_out (vty, " (Received from a RR-client)");
if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
vty_out (vty, " (Received from a RS-client)");
if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, " (history entry)");
else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
vty_out (vty, " (suppressed due to dampening)");
}
if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
vty_out (vty, ", (stale)");
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
vty_out (vty, ", (aggregated by %d %s)", attr->aggregator_as,
inet_ntoa (attr->aggregator_addr));
if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
vty_out (vty, ", (Received from a RR-client)");
if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
vty_out (vty, ", (Received from a RS-client)");
if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, ", (history entry)");
else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
vty_out (vty, ", (suppressed due to dampening)");
vty_out (vty, "%s", VTY_NEWLINE);
/* Line2 display Next-hop, Neighbor, Router-id */
@ -5251,6 +5293,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
vty_out (vty, "%s", VTY_NEWLINE);
}
#define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,%s r RIB-failure, S Stale%s"
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s"
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path%s"
#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path%s"
#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path%s"
@ -5449,9 +5493,9 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router
if (header)
{
vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (*router_id), VTY_NEWLINE);
vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (*router_id), VTY_NEWLINE);
vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
if (type == bgp_show_type_dampend_paths
|| type == bgp_show_type_damp_neighbor)
vty_out (vty, BGP_SHOW_DAMP_HEADER, VTY_NEWLINE);
@ -8114,8 +8158,8 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
PEER_STATUS_DEFAULT_ORIGINATE))
{
vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, "Originating default network 0.0.0.0%s%s",
VTY_NEWLINE, VTY_NEWLINE);
@ -8131,8 +8175,8 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
if (header1)
{
vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
header1 = 0;
}
if (header2)
@ -8155,8 +8199,8 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
if (header1)
{
vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
header1 = 0;
}
if (header2)

View File

@ -36,7 +36,7 @@ struct bgp_info
#define BGP_ROUTE_REDISTRIBUTE 3
/* BGP information status. */
u_char flags;
u_int16_t flags;
#define BGP_INFO_IGP_CHANGED (1 << 0)
#define BGP_INFO_DAMPED (1 << 1)
#define BGP_INFO_HISTORY (1 << 2)
@ -45,6 +45,7 @@ struct bgp_info
#define BGP_INFO_ATTR_CHANGED (1 << 5)
#define BGP_INFO_DMED_CHECK (1 << 6)
#define BGP_INFO_DMED_SELECTED (1 << 7)
#define BGP_INFO_STALE (1 << 8)
/* Peer structure. */
struct peer *peer;
@ -134,6 +135,7 @@ void bgp_check_local_routes_rsclient (struct peer *rsclient, afi_t afi, safi_t s
void bgp_clear_route (struct peer *, afi_t, safi_t);
void bgp_clear_route_all (struct peer *);
void bgp_clear_adj_in (struct peer *, afi_t, safi_t);
void bgp_clear_stale_route (struct peer *, afi_t, safi_t);
int bgp_nlri_sanity_check (struct peer *, int, u_char *, bgp_size_t);
int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);

View File

@ -806,6 +806,53 @@ DEFUN (no_bgp_graceful_restart,
return CMD_SUCCESS;
}
DEFUN (bgp_graceful_restart_stalepath_time,
bgp_graceful_restart_stalepath_time_cmd,
"bgp graceful-restart stalepath-time <1-3600>",
"BGP specific commands\n"
"Graceful restart capability parameters\n"
"Set the max time to hold onto restarting peer's stale paths\n"
"Delay value (seconds)\n")
{
struct bgp *bgp;
u_int32_t stalepath;
bgp = vty->index;
if (! bgp)
return CMD_WARNING;
VTY_GET_INTEGER_RANGE ("stalepath-time", stalepath, argv[0], 1, 3600);
bgp->stalepath_time = stalepath;
return CMD_SUCCESS;
}
DEFUN (no_bgp_graceful_restart_stalepath_time,
no_bgp_graceful_restart_stalepath_time_cmd,
"no bgp graceful-restart stalepath-time",
NO_STR
"BGP specific commands\n"
"Graceful restart capability parameters\n"
"Set the max time to hold onto restarting peer's stale paths\n")
{
struct bgp *bgp;
bgp = vty->index;
if (! bgp)
return CMD_WARNING;
bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
return CMD_SUCCESS;
}
ALIAS (no_bgp_graceful_restart_stalepath_time,
no_bgp_graceful_restart_stalepath_time_val_cmd,
"no bgp graceful-restart stalepath-time <1-3600>",
NO_STR
"BGP specific commands\n"
"Graceful restart capability parameters\n"
"Set the max time to hold onto restarting peer's stale paths\n"
"Delay value (seconds)\n")
/* "bgp fast-external-failover" configuration. */
DEFUN (bgp_fast_external_failover,
bgp_fast_external_failover_cmd,
@ -6950,6 +6997,13 @@ bgp_show_peer (struct vty *vty, struct peer *p)
if (p->status == Established)
vty_out (vty, ", up for %8s",
peer_uptime (p->uptime, timebuf, BGP_UPTIME_LEN));
else if (p->status == Active)
{
if (CHECK_FLAG (p->flags, PEER_FLAG_PASSIVE))
vty_out (vty, " (passive)");
else if (CHECK_FLAG (p->sflags, PEER_STATUS_NSF_WAIT))
vty_out (vty, " (NSF passive)");
}
vty_out (vty, "%s", VTY_NEWLINE);
/* read timer */
@ -6964,7 +7018,7 @@ bgp_show_peer (struct vty *vty, struct peer *p)
vty_out (vty, ", keepalive interval is %d seconds%s",
p->keepalive, VTY_NEWLINE);
}
/* Capability. */
if (p->status == Established)
{
@ -7046,17 +7100,19 @@ bgp_show_peer (struct vty *vty, struct peer *p)
int restart_af_count = 0;
vty_out (vty, " Remote Restart timer is %d seconds%s",
p->restart_time_rcv, VTY_NEWLINE);
vty_out (vty, " Address families preserved by peer:%s ", VTY_NEWLINE);
p->v_gr_restart, VTY_NEWLINE);
vty_out (vty, " Address families by peer:%s ", VTY_NEWLINE);
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV))
{
vty_out (vty, "%s%s", restart_af_count ? ", " : "",
afi_safi_print (afi, safi));
vty_out (vty, "%s%s(%s)", restart_af_count ? ", " : "",
afi_safi_print (afi, safi),
CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV) ?
"preserved" : "not preserved");
restart_af_count++;
}
}
if (! restart_af_count)
vty_out (vty, "none");
vty_out (vty, "%s", VTY_NEWLINE);
@ -7065,15 +7121,67 @@ bgp_show_peer (struct vty *vty, struct peer *p)
}
}
/* graceful restart information */
if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)
|| p->t_gr_restart
|| p->t_gr_stale)
{
int eor_send_af_count = 0;
int eor_receive_af_count = 0;
vty_out (vty, " Graceful restart informations:%s", VTY_NEWLINE);
if (p->status == Established)
{
vty_out (vty, " End-of-RIB send: ");
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_EOR_SEND))
{
vty_out (vty, "%s%s", eor_send_af_count ? ", " : "",
afi_safi_print (afi, safi));
eor_send_af_count++;
}
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, " End-of-RIB received: ");
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED))
{
vty_out (vty, "%s%s", eor_receive_af_count ? ", " : "",
afi_safi_print (afi, safi));
eor_receive_af_count++;
}
vty_out (vty, "%s", VTY_NEWLINE);
}
if (p->t_gr_restart)
{
vty_out (vty, " The remaining time of restart timer is %ld%s",
thread_timer_remain_second (p->t_gr_restart), VTY_NEWLINE);
}
if (p->t_gr_stale)
{
vty_out (vty, " The remaining time of stalepath timer is %ld%s",
thread_timer_remain_second (p->t_gr_stale), VTY_NEWLINE);
}
}
/* Packet counts. */
vty_out(vty, " Received %d messages, %d notifications, %d in queue%s",
p->open_in + p->update_in + p->keepalive_in + p->refresh_in
+ p->dynamic_cap_in, p->notify_in, 0, VTY_NEWLINE);
vty_out(vty, " Sent %d messages, %d notifications, %ld in queue%s",
p->open_out + p->update_out + p->keepalive_out + p->refresh_out
+ p->dynamic_cap_out, p->notify_out, p->obuf->count, VTY_NEWLINE);
vty_out(vty, " Route refresh request: received %d, sent %d%s",
p->refresh_in, p->refresh_out, VTY_NEWLINE);
vty_out (vty, " Message statistics:%s", VTY_NEWLINE);
vty_out (vty, " Inq depth is 0%s", VTY_NEWLINE);
vty_out (vty, " Outq depth is %ld%s", p->obuf->count, VTY_NEWLINE);
vty_out (vty, " Sent Rcvd%s", VTY_NEWLINE);
vty_out (vty, " Opens: %10d %10d%s", p->open_out, p->open_in, VTY_NEWLINE);
vty_out (vty, " Notifications: %10d %10d%s", p->notify_out, p->notify_in, VTY_NEWLINE);
vty_out (vty, " Updates: %10d %10d%s", p->update_out, p->update_in, VTY_NEWLINE);
vty_out (vty, " Keepalives: %10d %10d%s", p->keepalive_out, p->keepalive_in, VTY_NEWLINE);
vty_out (vty, " Route Refresh: %10d %10d%s", p->refresh_out, p->refresh_in, VTY_NEWLINE);
vty_out (vty, " Capability: %10d %10d%s", p->dynamic_cap_out, p->dynamic_cap_in, VTY_NEWLINE);
vty_out (vty, " Total: %10d %10d%s", p->open_out + p->notify_out +
p->update_out + p->keepalive_out + p->refresh_out + p->dynamic_cap_out,
p->open_in + p->notify_in + p->update_in + p->keepalive_in + p->refresh_in +
p->dynamic_cap_in, VTY_NEWLINE);
/* advertisement-interval */
vty_out (vty, " Minimum time between advertisement runs is %d seconds%s",
@ -7136,11 +7244,9 @@ bgp_show_peer (struct vty *vty, struct peer *p)
/* Local address. */
if (p->su_local)
{
vty_out (vty, "Local host: %s, Local port: %d%s%s",
vty_out (vty, "Local host: %s, Local port: %d%s",
sockunion2str (p->su_local, buf1, SU_ADDRSTRLEN),
ntohs (p->su_local->sin.sin_port),
CHECK_FLAG (p->flags, PEER_FLAG_PASSIVE) ?
", passive-mode" : "",
VTY_NEWLINE);
}
@ -8480,11 +8586,12 @@ bgp_vty_init ()
install_element (BGP_NODE, &bgp_deterministic_med_cmd);
install_element (BGP_NODE, &no_bgp_deterministic_med_cmd);
#if 0
/* "bgp graceful-restart" commands */
install_element (BGP_NODE, &bgp_graceful_restart_cmd);
install_element (BGP_NODE, &no_bgp_graceful_restart_cmd);
#endif /* 0 */
install_element (BGP_NODE, &bgp_graceful_restart_stalepath_time_cmd);
install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_cmd);
install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_val_cmd);
/* "bgp fast-external-failover" commands */
install_element (BGP_NODE, &bgp_fast_external_failover_cmd);

View File

@ -1040,6 +1040,34 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
return 0;
}
void
peer_nsf_stop (struct peer *peer)
{
afi_t afi;
safi_t safi;
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
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;
if (peer->t_gr_restart)
{
BGP_TIMER_OFF (peer->t_gr_restart);
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s graceful restart timer stopped", peer->host);
}
if (peer->t_gr_stale)
{
BGP_TIMER_OFF (peer->t_gr_stale);
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
bgp_clear_route_all (peer);
}
/* Delete peer from confguration. */
int
peer_delete (struct peer *peer)
@ -1052,6 +1080,9 @@ peer_delete (struct peer *peer)
bgp = peer->bgp;
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
peer_nsf_stop (peer);
/* If this peer belongs to peer group. Clearn up the
relationship. */
if (peer->group)
@ -1075,6 +1106,8 @@ peer_delete (struct peer *peer)
BGP_TIMER_OFF (peer->t_asorig);
BGP_TIMER_OFF (peer->t_routeadv);
BGP_TIMER_OFF (peer->t_pmax_restart);
BGP_TIMER_OFF (peer->t_gr_restart);
BGP_TIMER_OFF (peer->t_gr_stale);
/* Delete from all peer list. */
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
@ -2148,6 +2181,9 @@ peer_flag_modify_action (struct peer *peer, u_int32_t flag)
{
if (CHECK_FLAG (peer->flags, flag))
{
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
peer_nsf_stop (peer);
UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
if (peer->t_pmax_restart)
{
@ -2157,6 +2193,9 @@ peer_flag_modify_action (struct peer *peer, u_int32_t flag)
peer->host);
}
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
peer_nsf_stop (peer);
if (peer->status == Established)
bgp_notify_send (peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
@ -4703,6 +4742,9 @@ bgp_config_write (struct vty *vty)
vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
/* BGP graceful-restart. */
if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
bgp->stalepath_time, VTY_NEWLINE);
if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);

View File

@ -142,8 +142,8 @@ struct bgp
u_int32_t default_keepalive;
/* BGP graceful restart */
u_int16_t restart_time;
u_int16_t stalepath_time;
u_int32_t restart_time;
u_int32_t stalepath_time;
};
/* BGP peer-group support. */
@ -318,10 +318,8 @@ struct peer
#define PEER_CAP_ORF_PREFIX_RM_RCV (1 << 3) /* receive-mode received */
#define PEER_CAP_ORF_PREFIX_SM_OLD_RCV (1 << 4) /* send-mode received */
#define PEER_CAP_ORF_PREFIX_RM_OLD_RCV (1 << 5) /* receive-mode received */
#define PEER_CAP_RESTART_AF_RCV (1 << 6) /* graceful restart received */
/* Gracefull Restart */
u_int16_t restart_time_rcv;
#define PEER_CAP_RESTART_AF_RCV (1 << 6) /* graceful restart afi/safi received */
#define PEER_CAP_RESTART_AF_PRESERVE_RCV (1 << 7) /* graceful restart afi/safi F-bit received */
/* Global configuration flags. */
u_int32_t flags;
@ -334,6 +332,9 @@ struct peer
#define PEER_FLAG_ENFORCE_MULTIHOP (1 << 6) /* enforce-multihop */
#define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 7) /* local-as no-prepend */
/* NSF mode (graceful restart) */
u_char nsf[AFI_MAX][SAFI_MAX];
/* Per AF configuration flags. */
u_int32_t af_flags[AFI_MAX][SAFI_MAX];
#define PEER_FLAG_SEND_COMMUNITY (1 << 0) /* send-community */
@ -368,6 +369,8 @@ struct peer
#define PEER_STATUS_CAPABILITY_OPEN (1 << 2) /* capability open send */
#define PEER_STATUS_HAVE_ACCEPT (1 << 3) /* accept peer's parent */
#define PEER_STATUS_GROUP (1 << 4) /* peer-group conf */
#define PEER_STATUS_NSF_MODE (1 << 5) /* NSF aware peer */
#define PEER_STATUS_NSF_WAIT (1 << 6) /* wait comeback peer */
/* Peer status af flags (reset in bgp_stop) */
u_int16_t af_sflags[AFI_MAX][SAFI_MAX];
@ -376,6 +379,8 @@ struct peer
#define PEER_STATUS_DEFAULT_ORIGINATE (1 << 2) /* default-originate peer */
#define PEER_STATUS_PREFIX_THRESHOLD (1 << 3) /* exceed prefix-threshold */
#define PEER_STATUS_PREFIX_LIMIT (1 << 4) /* exceed prefix-limit */
#define PEER_STATUS_EOR_SEND (1 << 5) /* end-of-rib send to peer */
#define PEER_STATUS_EOR_RECEIVED (1 << 6) /* end-of-rib received from peer */
/* Default attribute value for the peer. */
@ -398,6 +403,7 @@ struct peer
u_int32_t v_asorig;
u_int32_t v_routeadv;
u_int32_t v_pmax_restart;
u_int32_t v_gr_restart;
/* Threads. */
struct thread *t_read;
@ -409,6 +415,8 @@ struct peer
struct thread *t_asorig;
struct thread *t_routeadv;
struct thread *t_pmax_restart;
struct thread *t_gr_restart;
struct thread *t_gr_stale;
/* Statistics field */
u_int32_t open_in; /* Open message input count */
@ -486,6 +494,7 @@ struct peer
#define PEER_DOWN_CAPABILITY_CHANGE 19 /* neighbor capability command */
#define PEER_DOWN_PASSIVE_CHANGE 20 /* neighbor passive command */
#define PEER_DOWN_MULTIHOP_CHANGE 21 /* neighbor multihop command */
#define PEER_DOWN_NSF_CLOSE_SESSION 22 /* NSF tcp session close */
/* The kind of route-map Flags.*/
u_char rmap_type;
@ -893,3 +902,5 @@ int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
int peer_clear (struct peer *);
int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type);
void peer_nsf_stop (struct peer *);