From 93406d87e68a0e9cf5ce0240461395cd59c143b6 Mon Sep 17 00:00:00 2001 From: hasso Date: Wed, 2 Feb 2005 14:40:33 +0000 Subject: * 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] --- bgpd/ChangeLog | 8 +++ bgpd/bgp_fsm.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_open.c | 16 +++--- bgpd/bgp_packet.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++------ bgpd/bgp_route.c | 108 +++++++++++++++++++++++++++------------ bgpd/bgp_route.h | 4 +- bgpd/bgp_vty.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++------- bgpd/bgpd.c | 42 ++++++++++++++++ bgpd/bgpd.h | 23 ++++++--- 9 files changed, 544 insertions(+), 82 deletions(-) (limited to 'bgpd') diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog index 67da8ff8..c867b9fd 100644 --- a/bgpd/ChangeLog +++ b/bgpd/ChangeLog @@ -1,3 +1,11 @@ +2005-02-02 Akihiro Mizutani * bgp_open.c, bgp_packet.c, bgp_vty.c, bgpd.[ch]: Remove "no neighbor diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 7327db0c..c8ca4173 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -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 */ diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 8321bcfa..72503836 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -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; } } diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 854b32cd..201ffbbe 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -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; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 2e7f7b31..2453cffc 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index e324ef03..46ae54d1 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -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 *); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index be57c126..8ee47c7e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -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); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1a504767..279c5467 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e14a8ad3..f8a36274 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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 *); -- cgit v1.2.1