summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/ChangeLog198
-rw-r--r--bgpd/bgp_aspath.c20
-rw-r--r--bgpd/bgp_aspath.h1
-rw-r--r--bgpd/bgp_damp.c19
-rw-r--r--bgpd/bgp_debug.c61
-rw-r--r--bgpd/bgp_debug.h3
-rw-r--r--bgpd/bgp_fsm.c127
-rw-r--r--bgpd/bgp_fsm.h43
-rw-r--r--bgpd/bgp_main.c12
-rw-r--r--bgpd/bgp_nexthop.c4
-rw-r--r--bgpd/bgp_packet.c40
-rw-r--r--bgpd/bgp_route.c901
-rw-r--r--bgpd/bgp_route.h13
-rw-r--r--bgpd/bgp_vty.c2
-rw-r--r--bgpd/bgp_zebra.c142
-rw-r--r--bgpd/bgpd.c110
-rw-r--r--bgpd/bgpd.h15
17 files changed, 1429 insertions, 282 deletions
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 13d6777a..236c0b77 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,201 @@
+2006-12-07 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_fsm.c: Bug #302 fix, diagnosis, suggestions and testing
+ by Juergen Kammer <j.kammer@eurodata.de>. Fix follows from
+ his suggested fix, just made in a slightly different way.
+ (bgp_event) Transitions into Clearing always must call
+ bgp_clear_route_all().
+ (bgp_stop) No need to clear routes here, BGP FSM should do
+ it.
+
+2006-11-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * bgp_debug.h: Declare new bgp_debug_zebra conf and term flags,
+ and define BGP_DEBUG_ZEBRA.
+ * bgp_debug.c: Declare conf_bgp_debug_zebra and term_bgp_debug_zebra.
+ (debug_bgp_zebra, no_debug_bgp_zebra, undebug_bgp_zebra) New
+ functions to enable/disable bgp zebra debugging.
+ (no_debug_bgp_all) Turn off zebra debugging.
+ (show_debugging_bgp) Show whether zebra debugging is on.
+ (bgp_config_write_debug) Add 'debug bgp zebra' if configured.
+ (bgp_debug_init) Add new zebra debugging commands.
+ * bgp_zebra.c: (bgp_router_id_update, bgp_interface_add,
+ bgp_interface_delete, bgp_interface_up, bgp_interface_down,
+ bgp_interface_address_add, bgp_interface_address_delete,
+ zebra_read_ipv4, zebra_read_ipv6, bgp_zebra_announce,
+ bgp_zebra_withdraw, bgp_redistribute_set, bgp_redistribute_unset)
+ If zebra debugging is enabled, log an appropriate debug message.
+
+2006-11-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * bgp_route.c: (bgp_info_restore) New function that undoes
+ the effects of a previous call to bgp_info_delete. This is
+ used when a route is deleted and quickly re-added before the
+ deletion has been processed.
+ (bgp_static_update_rsclient, bgp_static_update_main,
+ bgp_redistribute_add) Check whether a pre-existing route
+ has the BGP_INFO_REMOVED set, and, if so, we need to call
+ bgp_info_restore to resurrect it.
+
+2006-10-27 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_route.c: (bgp_table_stats) oops, u_intXX_t should be
+ uintXX_t
+
+2006-10-19 Paul Jakma <paul.jakma@sun.com>
+
+ * bgpd.c: (peer_new) bgp element of peer absolutely must be
+ filled in, make peer_new() require it as argument and update
+ all callers. Fixes a crash reported by Jan 'yanek' Bortl and
+ Andrew Schorr where bgpd would crash in bgp_pcount_adjust
+ trying to dereference the bgp member of bgp->peer_self,
+ triggered through redistribution.
+ * bgp_route.c: (bgp_pcount_adjust) assert sanity of arguments.
+
+2006-10-15 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_route.c: (bgp_table_stats_walker) NULL deref if table is
+ empty, bgp_table_top may return NULL, Coverity CID#73.
+ * bgp_packet.c: (bgp_update_packet) adv->rn can not be NULL,
+ check is bogus - changed to assert(), CID#64.
+ binfo is checked for NULL, but then dereferenced
+ unconditionally, fix, CID #63.
+ (bgp_withdraw_packet) Assert adv->rn is valid, as with
+ bgp_update_packet().
+
+2006-10-14 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_fsm.h: Remove BGP_EVENT_FLUSH_ADD, dangerous and not
+ needed.
+ * bgp_fsm.c: (bgp_stop) Move BGP_EVENT_FLUSH to the top of the
+ of the function, otherwise it could flush a ClearingCompleted
+ event, bug #302.
+ * bgp_packet.c: Replace all BGP_EVENT_FLUSH_ADD with
+ BGP_EVENT_ADD, fixing bug #302.
+
+2006-09-19 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * bgpd.c: (peer_uptime) Fix printf format/arg mismatch in
+ zlog_warn message (%ld/size_t -> %lu/u_long).
+
+2006-09-14 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_route.c: (bgp_table_stats_walker) Address space announced
+ should only count top-level unaggregateable prefixes, to
+ avoid falling afoul of anti-dodgy-accounting regulations
+ in various jurisdictions.. ;)
+ (bgp_process_queue_init) process queue hold time too high,
+ adds extra memory load. Change to be much lower, until such
+ time as it's made configurable.
+
+2006-09-14 Paul Jakma <paul.jakma@sun.com>
+
+ * (general) fix the peer refcount issue exposed by previous, by
+ just removing refcounting of peer threads, which is mostly
+ senseless as they're references leading from struct peer,
+ which peer_free cancels anyway. No need to muck around..
+ * bgp_fsm.h: Just remove the refcounting from the various
+ TIMER/READ/WRITE/EVENT ON/OFF/ADD macros.
+ * bgp_fsm.c: (bgp_stop) use BGP_EVENT_FLUSH, no refcounts attached
+ to events anymore.
+ (bgp_event) remove peer_unlock, events not refcounted.
+ * bgpd.c: (peer_free) flush events before free.
+
+2006-09-14 Paul Jakma <paul.jakma@sun.com>
+
+ * (general) Fix some niggly issues around 'shutdown' and clearing
+ by adding a Clearing FSM wait-state and a hidden 'Deleted'
+ FSM state, to allow deleted peers to 'cool off' and hit 0
+ references. This introduces a slow memory leak of struct peer,
+ however that's more a testament to the fragility of the
+ reference counting than a bug in this patch, cleanup of
+ reference counting to fix this is to follow.
+ * bgpd.h: Add Clearing, Deleted states and Clearing_Completed
+ and event.
+ * bgp_debug.c: (bgp_status_msg[]) Add strings for Clearing and
+ Deleted.
+ * bgp_fsm.h: Don't allow timer/event threads to set anything
+ for Deleted peers.
+ * bgp_fsm.c: (bgp_timer_set) Add Clearing and Deleted. Deleted
+ needs to stop everything.
+ (bgp_stop) Remove explicit fsm_change_status call, the
+ general framework handles the transition.
+ (bgp_start) Log a warning if a start is attempted on a peer
+ that should stay down, trying to start a peer.
+ (struct .. FSM) Add Clearing_Completed
+ events, has little influence except when in state
+ Clearing to signal wait-state can end.
+ Add Clearing and Deleted states, former is a wait-state,
+ latter is a placeholder state to allow peers to disappear
+ quietly once refcounts settle.
+ (bgp_event) Try reduce verbosity of FSM state-change debug,
+ changes to same state are not interesting (Established->Established)
+ Allow NULL action functions in FSM.
+ * bgp_packet.c: (bgp_write) Use FSM events, rather than trying
+ to twiddle directly with FSM state behind the back of FSM.
+ (bgp_write_notify) ditto.
+ (bgp_read) Remove the vague ACCEPT_PEER peer_unlock, or else
+ this patch crashes, now it leaks instead.
+ * bgp_route.c: (bgp_clear_node_complete) Clearing_Completed
+ event, to end clearing.
+ (bgp_clear_route) See extensive comments.
+ * bgpd.c: (peer_free) should only be called while in Deleted,
+ peer refcounting controls when peer_free is called.
+ bgp_sync_delete should be here, not in peer_delete.
+ (peer_delete) Initiate delete.
+ Transition to Deleted state manually.
+ When removing peer from indices that provide visibility of it,
+ take great care to be idempotent wrt the reference counting
+ of struct peer through those indices.
+ Use bgp_timer_set, rather than replicating.
+ Call to bgp_sync_delete isn't appropriate here, sync can be
+ referenced while shutting down and finishing deletion.
+ (peer_group_bind) Take care to be idempotent wrt list references
+ indexing peers.
+
+2006-09-13 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_aspath.c: (aspath_highest) new, return highest ASN in an
+ aspath.
+ * bgp_route.c: (bgp_peer_count_walker) new, do the walk done
+ in bgp_peer_counts as a thread.
+ (bgp_peer_counts) move walk to previous and call it via
+ thread_execute so this RIB walk shows up in thread stats.
+ (bgp_table_stats) New, gather some statistics for a given
+ RIB.
+ (bgp_table_stats_walker) New, RIB walker thread for former.
+ (bgp_table_stats_vty) Parsing front-end for 'show bgp ...',
+ useful model for future rationalisation of 'show ... bgp'.
+ (bgp_route_init) Add new RIB stats commands.
+
+2006-09-06 Paul Jakma <paul.jakma@sun.com>
+
+ * (general) Squash any and all prefix-count issues by
+ abstracting route flag changes, and maintaining count as and
+ when flags are modified (rather than relying on explicit
+ modifications of count being sprinkled in just the right
+ places throughout the code).
+ * bgp_route.c: (bgp_pcount_{dec,inc}rement) removed.
+ (bgp_pcount_adjust) new, update prefix count as
+ needed for a given route.
+ (bgp_info_{uns,s}et_flag) set/unset a BGP_INFO route status
+ flag, calling previous function when appropriate.
+ (general) Update all set/unsets of flags to use previous.
+ Remove pcount_{dec,inc}rement calls.
+ No need to unset BGP_INFO_VALID in places where
+ bgp_info_delete is called, it does that anyway.
+ * bgp_{damp,nexthop}.c: Update to use bgp_info_{un,}set_flag.
+ * bgp_route.h: Export bgp_info_{un,}set_flag.
+ Add a 'meta' BGP_INFO flag, BGP_INFO_UNUSEABLE.
+ Move BGP_INFO_HOLDDOWN macro to here from bgpd.h
+
+2006-09-03 Paul Jakma <paul.jakma@sun.com>
+
+ * bgp_route.c: Add 'show ... bgp ... <neighbour> prefix-count'
+ commands, to provide detailed counts of prefixes for a peer.
+ Informative, and should help pin down to pfxcnt drift
+ problems.
+
2006-08-27 Paul Jakma <paul.jakma@sun.com>
* bgp_advertise.c: (bgp_sync_delete) fix mtype in XFREE.
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 317e9f8d..327406fa 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -434,6 +434,26 @@ aspath_size (struct aspath *aspath)
return size;
}
+/* Return highest public ASN in path */
+as_t
+aspath_highest (struct aspath *aspath)
+{
+ struct assegment *seg = aspath->segments;
+ as_t highest = 0;
+ unsigned int i;
+
+ while (seg)
+ {
+ for (i = 0; i < seg->length; i++)
+ if (seg->as[i] > highest
+ && (seg->as[i] < BGP_PRIVATE_AS_MIN
+ || seg->as[i] > BGP_PRIVATE_AS_MAX))
+ highest = seg->as[i];
+ seg = seg->next;
+ }
+ return highest;
+}
+
/* Convert aspath structure to string expression. */
static char *
aspath_make_str_count (struct aspath *as)
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index bf23e5d6..5400c57c 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -87,6 +87,7 @@ extern unsigned long aspath_count (void);
extern unsigned int aspath_count_hops (struct aspath *);
extern unsigned int aspath_count_confeds (struct aspath *);
extern unsigned int aspath_size (struct aspath *);
+extern as_t aspath_highest (struct aspath *);
extern void aspath_put (struct stream *, struct aspath *);
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index a2163a4f..8ba39b65 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -148,12 +148,12 @@ bgp_reuse_timer (struct thread *t)
if (bdi->penalty < damp->reuse_limit)
{
/* Reuse the route. */
- UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
+ bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED);
bdi->suppress_time = 0;
if (bdi->lastrecord == BGP_RECORD_UPDATE)
{
- UNSET_FLAG (bdi->binfo->flags, BGP_INFO_HISTORY);
+ bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY);
bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
bdi->afi, bdi->safi);
bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
@@ -223,11 +223,13 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
bdi->flap++;
}
+ assert ((rn == bdi->rn) && (binfo == bdi->binfo));
+
bdi->lastrecord = BGP_RECORD_WITHDRAW;
bdi->t_updated = t_now;
/* Make this route as historical status. */
- SET_FLAG (binfo->flags, BGP_INFO_HISTORY);
+ bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY);
/* Remove the route from a reuse list if it is on one. */
if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
@@ -245,7 +247,7 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
insert into reuse_list. */
if (bdi->penalty >= damp->suppress_value)
{
- SET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
+ bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED);
bdi->suppress_time = t_now;
BGP_DAMP_LIST_DEL (damp, bdi);
bgp_reuse_list_add (bdi);
@@ -267,7 +269,7 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
return BGP_DAMP_USED;
t_now = time (NULL);
- UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY);
+ bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);
bdi->lastrecord = BGP_RECORD_UPDATE;
bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);
@@ -278,7 +280,7 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
&& (bdi->penalty < damp->reuse_limit) )
{
- UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
+ bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED);
bgp_reuse_list_delete (bdi);
BGP_DAMP_LIST_ADD (damp, bdi);
bdi->suppress_time = 0;
@@ -311,7 +313,7 @@ bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
if (t_diff >= damp->max_suppress_time)
{
- UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED);
+ bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED);
bgp_reuse_list_delete (bdi);
BGP_DAMP_LIST_ADD (damp, bdi);
bdi->penalty = damp->reuse_limit;
@@ -358,8 +360,7 @@ bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
else
BGP_DAMP_LIST_DEL (damp, bdi);
- UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED);
- UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY);
+ bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED);
if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
bgp_info_delete (bdi->rn, binfo);
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 1b398ee8..1986b35b 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -43,6 +43,7 @@ unsigned long conf_bgp_debug_filter;
unsigned long conf_bgp_debug_keepalive;
unsigned long conf_bgp_debug_update;
unsigned long conf_bgp_debug_normal;
+unsigned long conf_bgp_debug_zebra;
unsigned long term_bgp_debug_fsm;
unsigned long term_bgp_debug_events;
@@ -51,6 +52,7 @@ unsigned long term_bgp_debug_filter;
unsigned long term_bgp_debug_keepalive;
unsigned long term_bgp_debug_update;
unsigned long term_bgp_debug_normal;
+unsigned long term_bgp_debug_zebra;
/* messages for BGP-4 status */
struct message bgp_status_msg[] =
@@ -62,6 +64,8 @@ struct message bgp_status_msg[] =
{ OpenSent, "OpenSent" },
{ OpenConfirm, "OpenConfirm" },
{ Established, "Established" },
+ { Clearing, "Clearing" },
+ { Deleted, "Deleted" },
};
int bgp_status_msg_max = BGP_STATUS_MAX;
@@ -588,6 +592,49 @@ ALIAS (no_debug_bgp_normal,
UNDEBUG_STR
BGP_STR)
+DEFUN (debug_bgp_zebra,
+ debug_bgp_zebra_cmd,
+ "debug bgp zebra",
+ DEBUG_STR
+ BGP_STR
+ "BGP Zebra messages\n")
+{
+ if (vty->node == CONFIG_NODE)
+ DEBUG_ON (zebra, ZEBRA);
+ else
+ {
+ TERM_DEBUG_ON (zebra, ZEBRA);
+ vty_out (vty, "BGP zebra debugging is on%s", VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_zebra,
+ no_debug_bgp_zebra_cmd,
+ "no debug bgp zebra",
+ NO_STR
+ DEBUG_STR
+ BGP_STR
+ "BGP Zebra messages\n")
+{
+ if (vty->node == CONFIG_NODE)
+ DEBUG_OFF (zebra, ZEBRA);
+ else
+ {
+ TERM_DEBUG_OFF (zebra, ZEBRA);
+ vty_out (vty, "BGP zebra debugging is off%s", VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_zebra,
+ undebug_bgp_zebra_cmd,
+ "undebug bgp zebra",
+ UNDEBUG_STR
+ DEBUG_STR
+ BGP_STR
+ "BGP Zebra messages\n")
+
DEFUN (no_debug_bgp_all,
no_debug_bgp_all_cmd,
"no debug all bgp",
@@ -603,6 +650,7 @@ DEFUN (no_debug_bgp_all,
TERM_DEBUG_OFF (update, UPDATE_OUT);
TERM_DEBUG_OFF (fsm, FSM);
TERM_DEBUG_OFF (filter, FILTER);
+ TERM_DEBUG_OFF (zebra, ZEBRA);
vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE);
return CMD_SUCCESS;
@@ -640,6 +688,8 @@ DEFUN (show_debugging_bgp,
vty_out (vty, " BGP fsm debugging is on%s", VTY_NEWLINE);
if (BGP_DEBUG (filter, FILTER))
vty_out (vty, " BGP filter debugging is on%s", VTY_NEWLINE);
+ if (BGP_DEBUG (zebra, ZEBRA))
+ vty_out (vty, " BGP zebra debugging is on%s", VTY_NEWLINE);
vty_out (vty, "%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -695,6 +745,12 @@ bgp_config_write_debug (struct vty *vty)
write++;
}
+ if (CONF_BGP_DEBUG (zebra, ZEBRA))
+ {
+ vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE);
+ write++;
+ }
+
return write;
}
@@ -726,6 +782,8 @@ bgp_debug_init (void)
install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd);
install_element (ENABLE_NODE, &debug_bgp_normal_cmd);
install_element (CONFIG_NODE, &debug_bgp_normal_cmd);
+ install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
@@ -745,6 +803,9 @@ bgp_debug_init (void)
install_element (ENABLE_NODE, &no_debug_bgp_normal_cmd);
install_element (ENABLE_NODE, &undebug_bgp_normal_cmd);
install_element (CONFIG_NODE, &no_debug_bgp_normal_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd);
+ install_element (ENABLE_NODE, &undebug_bgp_zebra_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd);
install_element (ENABLE_NODE, &no_debug_bgp_all_cmd);
install_element (ENABLE_NODE, &undebug_bgp_all_cmd);
}
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index bc8acf93..eab95d09 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -63,6 +63,7 @@ extern unsigned long conf_bgp_debug_filter;
extern unsigned long conf_bgp_debug_keepalive;
extern unsigned long conf_bgp_debug_update;
extern unsigned long conf_bgp_debug_normal;
+extern unsigned long conf_bgp_debug_zebra;
extern unsigned long term_bgp_debug_fsm;
extern unsigned long term_bgp_debug_events;
@@ -71,6 +72,7 @@ extern unsigned long term_bgp_debug_filter;
extern unsigned long term_bgp_debug_keepalive;
extern unsigned long term_bgp_debug_update;
extern unsigned long term_bgp_debug_normal;
+extern unsigned long term_bgp_debug_zebra;
#define BGP_DEBUG_FSM 0x01
#define BGP_DEBUG_EVENTS 0x01
@@ -80,6 +82,7 @@ extern unsigned long term_bgp_debug_normal;
#define BGP_DEBUG_UPDATE_IN 0x01
#define BGP_DEBUG_UPDATE_OUT 0x02
#define BGP_DEBUG_NORMAL 0x01
+#define BGP_DEBUG_ZEBRA 0x01
#define BGP_DEBUG_PACKET_SEND 0x01
#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 770a7911..d704c297 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -68,6 +68,11 @@ bgp_start_jitter (int time)
return ((rand () % (time + 1)) - (time / 2));
}
+/* Check if suppress start/restart of sessions to peer. */
+#define BGP_PEER_START_SUPPRESSED(P) \
+ (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \
+ || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+
/* Hook function called after bgp event is occered. And vty's
neighbor command invoke this function after making neighbor
structure. */
@@ -82,10 +87,7 @@ bgp_timer_set (struct peer *peer)
/* First entry point of peer's finite state machine. In Idle
status start timer is on unless peer is shutdown or peer is
inactive. All other timer must be turned off */
- if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
- || CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)
- || CHECK_FLAG (peer->sflags, PEER_STATUS_CLEARING)
- || ! peer_active (peer))
+ if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer))
{
BGP_TIMER_OFF (peer->t_start);
}
@@ -197,6 +199,17 @@ bgp_timer_set (struct peer *peer)
}
BGP_TIMER_OFF (peer->t_asorig);
break;
+ case Deleted:
+ BGP_TIMER_OFF (peer->t_gr_restart);
+ BGP_TIMER_OFF (peer->t_gr_stale);
+ BGP_TIMER_OFF (peer->t_pmax_restart);
+ case Clearing:
+ BGP_TIMER_OFF (peer->t_start);
+ BGP_TIMER_OFF (peer->t_connect);
+ BGP_TIMER_OFF (peer->t_holdtime);
+ BGP_TIMER_OFF (peer->t_keepalive);
+ BGP_TIMER_OFF (peer->t_asorig);
+ BGP_TIMER_OFF (peer->t_routeadv);
}
}
@@ -413,14 +426,15 @@ bgp_stop (struct peer *peer)
{
afi_t afi;
safi_t safi;
- unsigned int i;
char orf_name[BUFSIZ];
+ /* Delete all existing events of the peer */
+ BGP_EVENT_FLUSH (peer);
+
/* Increment Dropped count. */
if (peer->status == Established)
{
peer->dropped++;
- bgp_fsm_change_status (peer, Idle);
/* bgp log-neighbor-changes of neighbor Down */
if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
@@ -469,9 +483,6 @@ bgp_stop (struct peer *peer)
/* Reset uptime. */
bgp_uptime_reset (peer);
- /* Need of clear of peer. */
- bgp_clear_route_all (peer);
-
/* Reset peer synctime */
peer->synctime = 0;
}
@@ -488,11 +499,6 @@ bgp_stop (struct peer *peer)
BGP_TIMER_OFF (peer->t_asorig);
BGP_TIMER_OFF (peer->t_routeadv);
- /* Delete all existing events of the peer,
- and corresponding peer ref-count */
- for (i = thread_cancel_event (master, peer); i > 0; i--)
- peer_unlock (peer); /* thread event reference */
-
/* Stream reset. */
peer->packet_size = 0;
@@ -625,6 +631,14 @@ bgp_start (struct peer *peer)
{
int status;
+ if (BGP_PEER_START_SUPPRESSED (peer))
+ {
+ if (BGP_DEBUG (fsm, FSM))
+ plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
+ " - this is never supposed to happen!", peer->host);
+ return -1;
+ }
+
/* Scrub some information that might be left over from a previous,
* session
*/
@@ -903,6 +917,7 @@ struct {
{bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
{bgp_ignore, Idle}, /* Receive_UPDATE_message */
{bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
},
{
/* Connect */
@@ -919,6 +934,7 @@ struct {
{bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
{bgp_ignore, Idle}, /* Receive_UPDATE_message */
{bgp_stop, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
},
{
/* Active, */
@@ -935,6 +951,7 @@ struct {
{bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
{bgp_ignore, Idle}, /* Receive_UPDATE_message */
{bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
},
{
/* OpenSent, */
@@ -951,6 +968,7 @@ struct {
{bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */
{bgp_ignore, Idle}, /* Receive_UPDATE_message */
{bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
},
{
/* OpenConfirm, */
@@ -967,22 +985,58 @@ struct {
{bgp_establish, Established}, /* Receive_KEEPALIVE_message */
{bgp_ignore, Idle}, /* Receive_UPDATE_message */
{bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
},
{
/* Established, */
- {bgp_ignore, Established}, /* BGP_Start */
- {bgp_stop, Idle}, /* BGP_Stop */
- {bgp_stop, Idle}, /* TCP_connection_open */
- {bgp_stop, Idle}, /* TCP_connection_closed */
- {bgp_ignore, Idle}, /* TCP_connection_open_failed */
- {bgp_stop, Idle}, /* TCP_fatal_error */
- {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */
- {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */
+ {bgp_ignore, Established}, /* BGP_Start */
+ {bgp_stop, Clearing}, /* BGP_Stop */
+ {bgp_stop, Clearing}, /* TCP_connection_open */
+ {bgp_stop, Clearing}, /* TCP_connection_closed */
+ {bgp_ignore, Clearing}, /* TCP_connection_open_failed */
+ {bgp_stop, Clearing}, /* TCP_fatal_error */
+ {bgp_ignore, Clearing}, /* ConnectRetry_timer_expired */
+ {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */
{bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */
- {bgp_stop, Idle}, /* Receive_OPEN_message */
- {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
- {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
- {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+ {bgp_stop, Clearing}, /* Receive_OPEN_message */
+ {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */
+ {bgp_fsm_update, Established}, /* Receive_UPDATE_message */
+ {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle}, /* Clearing_Completed */
+ },
+ {
+ /* Clearing, */
+ {bgp_ignore, Clearing}, /* BGP_Start */
+ {bgp_ignore, Clearing}, /* BGP_Stop */
+ {bgp_ignore, Clearing}, /* TCP_connection_open */
+ {bgp_ignore, Clearing}, /* TCP_connection_closed */
+ {bgp_ignore, Clearing}, /* TCP_connection_open_failed */
+ {bgp_ignore, Clearing}, /* TCP_fatal_error */
+ {bgp_ignore, Clearing}, /* ConnectRetry_timer_expired */
+ {bgp_ignore, Clearing}, /* Hold_Timer_expired */
+ {bgp_ignore, Clearing}, /* KeepAlive_timer_expired */
+ {bgp_ignore, Clearing}, /* Receive_OPEN_message */
+ {bgp_ignore, Clearing}, /* Receive_KEEPALIVE_message */
+ {bgp_ignore, Clearing}, /* Receive_UPDATE_message */
+ {bgp_ignore, Clearing}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Idle }, /* Clearing_Completed */
+ },
+ {
+ /* Deleted, */
+ {bgp_ignore, Deleted}, /* BGP_Start */
+ {bgp_ignore, Deleted}, /* BGP_Stop */
+ {bgp_ignore, Deleted}, /* TCP_connection_open */
+ {bgp_ignore, Deleted}, /* TCP_connection_closed */
+ {bgp_ignore, Deleted}, /* TCP_connection_open_failed */
+ {bgp_ignore, Deleted}, /* TCP_fatal_error */
+ {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */
+ {bgp_ignore, Deleted}, /* Hold_Timer_expired */
+ {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */
+ {bgp_ignore, Deleted}, /* Receive_OPEN_message */
+ {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */
+ {bgp_ignore, Deleted}, /* Receive_UPDATE_message */
+ {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */
+ {bgp_ignore, Deleted}, /* Clearing_Completed */
},
};
@@ -1001,14 +1055,15 @@ static const char *bgp_event_str[] =
"Receive_OPEN_message",
"Receive_KEEPALIVE_message",
"Receive_UPDATE_message",
- "Receive_NOTIFICATION_message"
+ "Receive_NOTIFICATION_message",
+ "Clearing_Completed",
};
/* Execute event process. */
int
bgp_event (struct thread *thread)
{
- int ret;
+ int ret = 0;
int event;
int next;
struct peer *peer;
@@ -1019,26 +1074,32 @@ bgp_event (struct thread *thread)
/* Logging this event. */
next = FSM [peer->status -1][event - 1].next_state;
- if (BGP_DEBUG (fsm, FSM))
+ if (BGP_DEBUG (fsm, FSM) && peer->status != next)
plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
bgp_event_str[event],
LOOKUP (bgp_status_msg, peer->status),
LOOKUP (bgp_status_msg, next));
/* Call function. */
- ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
+ if (FSM [peer->status -1][event - 1].func)
+ ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
/* When function do not want proceed next job return -1. */
if (ret >= 0)
{
/* If status is changed. */
if (next != peer->status)
- bgp_fsm_change_status (peer, next);
-
+ {
+ /* Transition into Clearing must /always/ clear all routes.. */
+ if (next == Clearing)
+ bgp_clear_route_all (peer);
+
+ bgp_fsm_change_status (peer, next);
+ }
+
/* Make sure timer is set. */
bgp_timer_set (peer);
}
- peer_unlock (peer); /* bgp-event peer reference */
return ret;
}
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index e90f3b43..a749f8ea 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -25,67 +25,48 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* Macro for BGP read, write and timer thread. */
#define BGP_READ_ON(T,F,V) \
do { \
- if (!T) \
- { \
- peer_lock (peer); \
- THREAD_READ_ON(master,T,F,peer,V); \
- } \
+ if (!(T) && (peer->status != Deleted)) \
+ THREAD_READ_ON(master,T,F,peer,V); \
} while (0)
#define BGP_READ_OFF(T) \
do { \
if (T) \
- { \
- peer_unlock (peer); \
- THREAD_READ_OFF(T); \
- } \
+ THREAD_READ_OFF(T); \
} while (0)
#define BGP_WRITE_ON(T,F,V) \
do { \
- if (!T) \
- { \
- peer_lock (peer); \
- THREAD_WRITE_ON(master,(T),(F),peer,(V)); \
- } \
+ if (!(T) && (peer->status != Deleted)) \
+ THREAD_WRITE_ON(master,(T),(F),peer,(V)); \
} while (0)
#define BGP_WRITE_OFF(T) \
do { \
if (T) \
- { \
- peer_unlock (peer); \
- THREAD_WRITE_OFF(T); \
- } \
+ THREAD_WRITE_OFF(T); \
} while (0)
#define BGP_TIMER_ON(T,F,V) \
do { \
- if (!T) \
- { \
- peer_lock (peer); \
- THREAD_TIMER_ON(master,(T),(F),peer,(V)); \
- } \
+ if (!(T) && (peer->status != Deleted)) \
+ THREAD_TIMER_ON(master,(T),(F),peer,(V)); \
} while (0)
#define BGP_TIMER_OFF(T) \
do { \
if (T) \
- { \
- peer_unlock (peer); \
- THREAD_TIMER_OFF(T); \
- } \
+ THREAD_TIMER_OFF(T); \
} while (0)
#define BGP_EVENT_ADD(P,E) \
do { \
- peer_lock (peer); /* bgp event reference */ \
- thread_add_event (master, bgp_event, (P), (E)); \
+ if ((P)->status != Deleted) \
+ thread_add_event (master, bgp_event, (P), (E)); \
} while (0)
-#define BGP_EVENT_DELETE(P) \
+#define BGP_EVENT_FLUSH(P) \
do { \
- peer_unlock (peer); /* bgp event peer reference */ \
assert (peer); \
thread_cancel_event (master, (P)); \
} while (0)
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 0baae3bf..ecfe62ef 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -50,6 +50,7 @@ struct option longopts[] =
{ "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'},
{ "version", no_argument, NULL, 'v'},
+ { "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
{ 0 }
};
@@ -141,6 +142,7 @@ redistribution between different routing protocols.\n\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
-v, --version Print program version\n\
+-C, --dryrun Check configuration for validity and exit\n\
-h, --help Display this help and exit\n\
\n\
Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
@@ -196,6 +198,7 @@ main (int argc, char **argv)
char *p;
int opt;
int daemon_mode = 0;
+ int dryrun = 0;
char *progname;
struct thread thread;
@@ -214,7 +217,7 @@ main (int argc, char **argv)
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:hp:A:P:rnu:g:v", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:hp:A:P:rnu:g:vC", longopts, 0);
if (opt == EOF)
break;
@@ -265,6 +268,9 @@ main (int argc, char **argv)
print_version (progname);
exit (0);
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'h':
usage (progname, 0);
break;
@@ -294,6 +300,10 @@ main (int argc, char **argv)
/* Parse config file. */
vty_read_config (config_file, config_default);
+ /* Start execution only if not in dry-run mode */
+ if(dryrun)
+ return(0);
+
/* Turn into daemon if daemon_mode is set. */
if (daemon_mode)
daemon (0, 0);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index ea707ccb..bfc41a18 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -478,11 +478,11 @@ bgp_scan (afi_t afi, safi_t safi)
{
bgp_aggregate_decrement (bgp, &rn->p, bi,
afi, SAFI_UNICAST);
- UNSET_FLAG (bi->flags, BGP_INFO_VALID);
+ bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
}
else
{
- SET_FLAG (bi->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
bgp_aggregate_increment (bgp, &rn->p, bi,
afi, SAFI_UNICAST);
}
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 8b024a1c..9859e50b 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -158,14 +158,14 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
while (adv)
{
- if (adv->rn)
- rn = adv->rn;
+ assert (adv->rn);
+ rn = adv->rn;
adj = adv->adj;
if (adv->binfo)
binfo = adv->binfo;
/* When remaining space can't include NLRI and it's length. */
- if (rn && STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))
+ if (STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))
break;
/* If packet is empty, set attribute. */
@@ -173,11 +173,15 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
{
struct prefix_rd *prd = NULL;
u_char *tag = NULL;
+ struct peer *from = NULL;
if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p;
if (binfo)
- tag = binfo->tag;
+ {
+ tag = binfo->tag;
+ from = binfo->peer;
+ }
bgp_packet_set_marker (s, BGP_MSG_UPDATE);
stream_putw (s, 0);
@@ -186,7 +190,7 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
total_attr_len = bgp_packet_attribute (NULL, peer, s,
adv->baa->attr,
&rn->p, afi, safi,
- binfo->peer, prd, tag);
+ from, prd, tag);
stream_putw_at (s, pos, total_attr_len);
}
@@ -288,6 +292,7 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
{
+ assert (adv->rn);
adj = adv->adj;
rn = adv->rn;
@@ -637,9 +642,7 @@ bgp_write (struct thread *thread)
if (write_errno == EWOULDBLOCK || write_errno == EAGAIN)
break;
- BGP_EVENT_ADD (peer, BGP_Stop);
- peer->status = Idle;
- bgp_timer_set (peer);
+ BGP_EVENT_ADD (peer, TCP_fatal_error);
return 0;
}
if (num != writenum)
@@ -673,10 +676,8 @@ bgp_write (struct thread *thread)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
+ /* Flush any existing events */
BGP_EVENT_ADD (peer, BGP_Stop);
- /*bgp_stop (peer);*/
- peer->status = Idle;
- bgp_timer_set (peer);
return 0;
case BGP_MSG_KEEPALIVE:
peer->keepalive_out++;
@@ -721,9 +722,7 @@ bgp_write_notify (struct peer *peer)
ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
if (ret <= 0)
{
- BGP_EVENT_ADD (peer, BGP_Stop);
- peer->status = Idle;
- bgp_timer_set (peer);
+ BGP_EVENT_ADD (peer, TCP_fatal_error);
return 0;
}
@@ -743,10 +742,7 @@ bgp_write_notify (struct peer *peer)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
- /* We don't call event manager at here for avoiding other events. */
- bgp_stop (peer);
- peer->status = Idle;
- bgp_timer_set (peer);
+ BGP_EVENT_ADD (peer, BGP_Stop);
return 0;
}
@@ -2375,14 +2371,6 @@ bgp_read (struct thread *thread)
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
peer_delete (peer);
- /* we've lost track of a reference to ACCEPT_PEER somehow. It doesnt
- * _seem_ to be the 'update realpeer with accept peer' hack, yet it
- * *must* be.. Very very odd, but I give up trying to
- * root cause this - ACCEPT_PEER is a dirty hack, it should be fixed
- * instead, which would make root-causing this a moot point..
- * A hack because of a hack, appropriate.
- */
- peer_unlock (peer); /* god knows what reference... ACCEPT_PEER sucks */
}
return 0;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 20276b49..8216fd4e 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -187,12 +187,87 @@ bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri)
void
bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri)
{
- /* leave info in place for now in place for now,
- * bgp_process will reap it later. */
- SET_FLAG (ri->flags, BGP_INFO_REMOVED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_REMOVED);
+ /* set of previous already took care of pcount */
UNSET_FLAG (ri->flags, BGP_INFO_VALID);
}
+/* undo the effects of a previous call to bgp_info_delete; typically
+ called when a route is deleted and then quickly re-added before the
+ deletion has been processed */
+static void
+bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri)
+{
+ bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED);
+ /* unset of previous already took care of pcount */
+ SET_FLAG (ri->flags, BGP_INFO_VALID);
+}
+
+/* Adjust pcount as required */
+static void
+bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
+{
+ assert (rn && rn->table);
+ assert (ri && ri->peer && ri->peer->bgp);
+
+ /* Ignore 'pcount' for RS-client tables */
+ if (rn->table->type != BGP_TABLE_MAIN
+ || ri->peer == ri->peer->bgp->peer_self)
+ return;
+
+ if (BGP_INFO_HOLDDOWN (ri)
+ && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+ {
+
+ UNSET_FLAG (ri->flags, BGP_INFO_COUNTED);
+
+ /* slight hack, but more robust against errors. */
+ if (ri->peer->pcount[rn->table->afi][rn->table->safi])
+ ri->peer->pcount[rn->table->afi][rn->table->safi]--;
+ else
+ {
+ zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s",
+ __func__, ri->peer->host);
+ zlog_backtrace (LOG_WARNING);
+ zlog_warn ("%s: Please report to Quagga bugzilla", __func__);
+ }
+ }
+ else if (!BGP_INFO_HOLDDOWN (ri)
+ && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+ {
+ SET_FLAG (ri->flags, BGP_INFO_COUNTED);
+ ri->peer->pcount[rn->table->afi][rn->table->safi]++;
+ }
+}
+
+
+/* Set/unset bgp_info flags, adjusting any other state as needed.
+ * This is here primarily to keep prefix-count in check.
+ */
+void
+bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
+{
+ SET_FLAG (ri->flags, flag);
+
+ /* early bath if we know it's not a flag that changes useability state */
+ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+ return;
+
+ bgp_pcount_adjust (rn, ri);
+}
+
+void
+bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
+{
+ UNSET_FLAG (ri->flags, flag);
+
+ /* early bath if we know it's not a flag that changes useability state */
+ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+ return;
+
+ bgp_pcount_adjust (rn, ri);
+}
+
/* Get MED value. If MED value is missing and "bgp bestpath
missing-as-worst" is specified, treat it as the worst value. */
static u_int32_t
@@ -1235,15 +1310,15 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *
{
if (bgp_info_cmp (bgp, ri2, new_select))
{
- UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
new_select = ri2;
}
- SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK);
+ bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK);
}
}
- SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK);
- SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
}
/* Check old selected route and new selected route. */
@@ -1269,11 +1344,11 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *
if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
&& (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))
{
- UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
continue;
}
- UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
- UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED);
if (bgp_info_cmp (bgp, ri, new_select))
new_select = ri;
@@ -1367,11 +1442,11 @@ bgp_process_rsclient (struct work_queue *wq, void *data)
continue;
if (old_select)
- UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
if (new_select)
{
- SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
- UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
}
bgp_process_announce_selected (rsclient, new_select, rn, &attr,
@@ -1381,11 +1456,11 @@ bgp_process_rsclient (struct work_queue *wq, void *data)
else
{
if (old_select)
- UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
if (new_select)
{
- SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
- UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
}
bgp_process_announce_selected (rsclient, new_select, rn,
&attr, afi, safi);
@@ -1433,11 +1508,11 @@ bgp_process_main (struct work_queue *wq, void *data)
}
if (old_select)
- UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
if (new_select)
{
- SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
- UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
}
@@ -1504,7 +1579,7 @@ bgp_process_queue_init (void)
bm->process_main_queue->spec.max_retries
= bm->process_main_queue->spec.max_retries = 0;
bm->process_rsclient_queue->spec.hold
- = bm->process_main_queue->spec.hold = 500;
+ = bm->process_main_queue->spec.hold = 50;
}
void
@@ -1636,43 +1711,6 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
return 0;
}
-static void
-bgp_pcount_increment (struct bgp_node *rn, struct bgp_info *ri,
- afi_t afi, safi_t safi)
-{
- assert (ri && rn);
-
- if (!CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)
- && rn->table->type == BGP_TABLE_MAIN)
- {
- SET_FLAG (ri->flags, BGP_INFO_COUNTED);
- ri->peer->pcount[afi][safi]++;
- }
-}
-
-static void
-bgp_pcount_decrement (struct bgp_node *rn, struct bgp_info *ri,
- afi_t afi, safi_t safi)
-{
- /* Ignore 'pcount' for RS-client tables */
- if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)
- && rn->table->type == BGP_TABLE_MAIN)
- {
- UNSET_FLAG (ri->flags, BGP_INFO_COUNTED);
-
- /* slight hack, but more robust against errors. */
- if (ri->peer->pcount[afi][safi])
- ri->peer->pcount[afi][safi]--;
- else
- {
- zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s",
- __func__, ri->peer->host);
- zlog_backtrace (LOG_WARNING);
- zlog_warn ("%s: Please report to Quagga bugzilla", __func__);
- }
- }
-}
-
/* Unconditionally remove the route from the RIB, without taking
* damping into consideration (eg, because the session went down)
*/
@@ -1680,7 +1718,6 @@ static void
bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
afi_t afi, safi_t safi)
{
- bgp_pcount_decrement (rn, ri, afi, safi);
bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
@@ -1703,7 +1740,6 @@ bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0))
== BGP_DAMP_SUPPRESSED)
{
- bgp_pcount_decrement (rn, ri, afi, safi);
bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
return;
}
@@ -1800,7 +1836,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
if (attrhash_cmp (ri->attr, attr_new))
{
- UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
if (BGP_DEBUG (update, UPDATE_IN))
zlog (peer->log, LOG_DEBUG,
@@ -1823,7 +1859,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
p->prefixlen, rsclient->host);
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Update to new attribute. */
bgp_attr_unintern (ri->attr);
@@ -1833,7 +1869,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
if (safi == SAFI_MPLS_VPN)
memcpy (ri->tag, tag, 3);
- SET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
/* Process change. */
bgp_process (bgp, rn, afi, safi);
@@ -1863,7 +1899,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
if (safi == SAFI_MPLS_VPN)
memcpy (new->tag, tag, 3);
- SET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, new, BGP_INFO_VALID);
/* Register new BGP information. */
bgp_info_add (rn, new);
@@ -2044,7 +2080,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* Same attribute comes in. */
if (attrhash_cmp (ri->attr, attr_new))
{
- UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer_sort (peer) == BGP_PEER_EBGP
@@ -2056,8 +2092,6 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
p->prefixlen);
- bgp_pcount_increment (rn, ri, afi, safi);
-
if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED)
{
bgp_aggregate_increment (bgp, p, ri, afi, safi);
@@ -2076,8 +2110,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
{
- UNSET_FLAG (ri->flags, BGP_INFO_STALE);
- bgp_pcount_increment (rn, ri, afi, safi);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
bgp_process (bgp, rn, afi, safi);
}
}
@@ -2096,15 +2129,14 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
- UNSET_FLAG (ri->flags, BGP_INFO_STALE);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* implicit withdraw, decrement aggregate and pcount here.
* only if update is accepted, they'll increment below.
*/
- bgp_pcount_decrement (rn, ri, afi, safi);
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
/* Update bgp route dampening information. */
@@ -2146,15 +2178,14 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
{
if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL))
- SET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
else
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
}
else
- SET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
/* Process change. */
- bgp_pcount_increment (rn, ri, afi, safi);
bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi);
@@ -2191,15 +2222,14 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
{
if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL))
- SET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, new, BGP_INFO_VALID);
else
- UNSET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
}
else
- SET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, new, BGP_INFO_VALID);
/* Increment prefix */
- bgp_pcount_increment (rn, new, afi, safi);
bgp_aggregate_increment (bgp, p, new, afi, safi);
/* Register new BGP information. */
@@ -2566,13 +2596,8 @@ bgp_clear_route_node (struct work_queue *wq, void *data)
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)
- && ! CHECK_FLAG (ri->flags, BGP_INFO_REMOVED))
- {
- bgp_pcount_decrement (rn, ri, afi, safi);
- SET_FLAG (ri->flags, BGP_INFO_STALE);
- }
+ && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ bgp_info_set_flag (rn, ri, BGP_INFO_STALE);
else
bgp_rib_remove (rn, ri, peer, afi, safi);
break;
@@ -2607,11 +2632,10 @@ bgp_clear_node_complete (struct work_queue *wq)
{
struct peer *peer = wq->spec.data;
- UNSET_FLAG (peer->sflags, PEER_STATUS_CLEARING);
peer_unlock (peer); /* bgp_clear_node_complete */
/* Tickle FSM to start moving again */
- BGP_EVENT_ADD (peer, BGP_Start);
+ BGP_EVENT_ADD (peer, Clearing_Completed);
}
static void
@@ -2673,9 +2697,10 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
if (peer->clear_node_queue == NULL)
bgp_clear_node_queue_init (peer);
- /* bgp_fsm.c will not bring CLEARING sessions out of Idle this
- * protects against peers which flap faster than we can we clear,
- * which could lead to:
+ /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
+ * Idle until it receives a Clearing_Completed event. This protects
+ * against peers which flap faster than we can we clear, which could
+ * lead to:
*
* a) race with routes from the new session being installed before
* clear_route_node visits the node (to delete the route of that
@@ -2684,11 +2709,8 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
* on the process_main queue. Fast-flapping could cause that queue
* to grow and grow.
*/
- if (!CHECK_FLAG (peer->sflags, PEER_STATUS_CLEARING))
- {
- SET_FLAG (peer->sflags, PEER_STATUS_CLEARING);
- peer_lock (peer); /* bgp_clear_node_complete */
- }
+ if (!peer->clear_node_queue->thread)
+ peer_lock (peer); /* bgp_clear_node_complete */
if (safi != SAFI_MPLS_VPN)
bgp_clear_route_table (peer, afi, safi, NULL, NULL);
@@ -2704,11 +2726,37 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
bgp_clear_route_table (peer, afi, safi, NULL, rsclient);
}
- /* If no routes were cleared, nothing was added to workqueue, run the
- * completion function now.
+ /* If no routes were cleared, nothing was added to workqueue, the
+ * completion function won't be run by workqueue code - call it here.
+ *
+ * Additionally, there is a presumption in FSM that clearing is only
+ * needed if peer state is Established - peers in pre-Established states
+ * shouldn't have any route-update state associated with them (in or out).
+ *
+ * We still get here from FSM through bgp_stop->clear_route_all in
+ * pre-Established though, so this is a useful sanity check to ensure
+ * the assumption above holds.
+ *
+ * At some future point, this check could be move to the top of the
+ * function, and do a quick early-return when state is
+ * pre-Established, avoiding above list and table scans. Once we're
+ * sure it is safe..
*/
if (!peer->clear_node_queue->thread)
bgp_clear_node_complete (peer->clear_node_queue);
+ else
+ {
+ /* clearing queue scheduled. Normal if in Established state
+ * (and about to transition out of it), but otherwise...
+ */
+ if (peer->status != Established)
+ {
+ plog_err (peer->log, "%s [Error] State %s is not Established,"
+ " but routes were cleared - bug!",
+ peer->host, LOOKUP (bgp_status_msg, peer->status));
+ assert (peer->status == Established);
+ }
+ }
}
void
@@ -3002,9 +3050,8 @@ bgp_static_withdraw_rsclient (struct bgp *bgp, struct peer *rsclient,
/* Withdraw static BGP route from routing table. */
if (ri)
{
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -3106,7 +3153,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
if (ri)
{
- if (attrhash_cmp (ri->attr, attr_new))
+ if (attrhash_cmp (ri->attr, attr_new) &&
+ !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
bgp_attr_unintern (attr_new);
@@ -3116,9 +3164,11 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
else
{
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
+ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+ bgp_info_restore(rn, ri);
bgp_attr_unintern (ri->attr);
ri->attr = attr_new;
ri->uptime = time (NULL);
@@ -3213,7 +3263,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
if (ri)
{
- if (attrhash_cmp (ri->attr, attr_new))
+ if (attrhash_cmp (ri->attr, attr_new) &&
+ !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
bgp_attr_unintern (attr_new);
@@ -3223,10 +3274,13 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
else
{
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+ bgp_info_restore(rn, ri);
+ else
+ bgp_aggregate_decrement (bgp, p, ri, afi, safi);
bgp_attr_unintern (ri->attr);
ri->attr = attr_new;
ri->uptime = time (NULL);
@@ -3333,9 +3387,8 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -3382,9 +3435,8 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -4165,7 +4217,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
if (aggregate->summary_only)
{
ri->suppress++;
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
@@ -4368,7 +4420,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
if (aggregate->summary_only)
{
ri->suppress++;
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
/* as-set aggregate route generate origin, as path,
@@ -4468,7 +4520,7 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
if (ri->suppress == 0)
{
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
}
@@ -4494,9 +4546,8 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
/* Withdraw static BGP route from routing table. */
if (ri)
{
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -5010,7 +5061,8 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
if (bi)
{
- if (attrhash_cmp (bi->attr, new_attr))
+ if (attrhash_cmp (bi->attr, new_attr) &&
+ !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
{
bgp_attr_unintern (new_attr);
aspath_unintern (attr.aspath);
@@ -5020,10 +5072,13 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
else
{
/* The attribute is changed. */
- SET_FLAG (bi->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
- bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
+ bgp_info_restore(bn, bi);
+ else
+ bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
bgp_attr_unintern (bi->attr);
bi->attr = new_attr;
bi->uptime = time (NULL);
@@ -5081,9 +5136,8 @@ bgp_redistribute_delete (struct prefix *p, u_char type)
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, SAFI_UNICAST);
}
bgp_unlock_node (rn);
}
@@ -5110,9 +5164,8 @@ bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type)
if (ri)
{
bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, SAFI_UNICAST);
}
}
}
@@ -8495,6 +8548,598 @@ peer_lookup_in_view (struct vty *vty, const char *view_name,
return peer;
}
+
+enum bgp_stats
+{
+ BGP_STATS_MAXBITLEN = 0,
+ BGP_STATS_RIB,
+ BGP_STATS_PREFIXES,
+ BGP_STATS_TOTPLEN,
+ BGP_STATS_UNAGGREGATEABLE,
+ BGP_STATS_MAX_AGGREGATEABLE,
+ BGP_STATS_AGGREGATES,
+ BGP_STATS_SPACE,
+ BGP_STATS_ASPATH_COUNT,
+ BGP_STATS_ASPATH_MAXHOPS,
+ BGP_STATS_ASPATH_TOTHOPS,
+ BGP_STATS_ASPATH_MAXSIZE,
+ BGP_STATS_ASPATH_TOTSIZE,
+ BGP_STATS_ASN_HIGHEST,
+ BGP_STATS_MAX,
+};
+
+static const char *table_stats_strs[] =
+{
+ [BGP_STATS_PREFIXES] = "Total Prefixes",
+ [BGP_STATS_TOTPLEN] = "Average prefix length",
+ [BGP_STATS_RIB] = "Total Advertisements",
+ [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
+ [BGP_STATS_MAX_AGGREGATEABLE] = "Maximum aggregateable prefixes",
+ [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
+ [BGP_STATS_SPACE] = "Address space advertised",
+ [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
+ [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
+ [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
+ [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
+ [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
+ [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
+ [BGP_STATS_MAX] = NULL,
+};
+
+struct bgp_table_stats
+{
+ struct bgp_table *table;
+ unsigned long long counts[BGP_STATS_MAX];
+};
+
+#if 0
+#define TALLY_SIGFIG 100000
+static unsigned long
+ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
+{
+ unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
+ unsigned long res = (newtot * TALLY_SIGFIG) / count;
+ unsigned long ret = newtot / count;
+
+ if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
+ return ret + 1;
+ else
+ return ret;
+}
+#endif
+
+static int
+bgp_table_stats_walker (struct thread *t)
+{
+ struct bgp_node *rn;
+ struct bgp_node *top;
+ struct bgp_table_stats *ts = THREAD_ARG (t);
+ unsigned int space = 0;
+
+ if (!(top = bgp_table_top (ts->table)))
+ return 0;
+
+ switch (top->p.family)
+ {
+ case AF_INET:
+ space = IPV4_MAX_BITLEN;
+ break;
+ case AF_INET6:
+ space = IPV6_MAX_BITLEN;
+ break;
+ }
+
+ ts->counts[BGP_STATS_MAXBITLEN] = space;
+
+ for (rn = top; rn; rn = bgp_route_next (rn))
+ {
+ struct bgp_info *ri;
+ struct bgp_node *prn = rn->parent;
+ unsigned int rinum = 0;
+
+ if (rn == top)
+ continue;
+
+ if (!rn->info)
+ continue;
+
+ ts->counts[BGP_STATS_PREFIXES]++;
+ ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
+
+#if 0
+ ts->counts[BGP_STATS_AVGPLEN]
+ = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
+ ts->counts[BGP_STATS_AVGPLEN],
+ rn->p.prefixlen);
+#endif
+
+ /* check if the prefix is included by any other announcements */
+ while (prn && !prn->info)
+ prn = prn->parent;
+
+ if (prn == NULL || prn == top)
+ {
+ ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
+ /* announced address space */
+ if (space)
+ ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen);
+ }
+ else if (prn->info)
+ ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
+
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ rinum++;
+ ts->counts[BGP_STATS_RIB]++;
+
+ if (ri->attr &&
+ (CHECK_FLAG (ri->attr->flag,
+ ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))))
+ ts->counts[BGP_STATS_AGGREGATES]++;
+
+ /* as-path stats */
+ if (ri->attr && ri->attr->aspath)
+ {
+ unsigned int hops = aspath_count_hops (ri->attr->aspath);
+ unsigned int size = aspath_size (ri->attr->aspath);
+ as_t highest = aspath_highest (ri->attr->aspath);
+
+ ts->counts[BGP_STATS_ASPATH_COUNT]++;
+
+ if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
+ ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
+
+ if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
+ ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
+
+ ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
+ ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
+#if 0
+ ts->counts[BGP_STATS_ASPATH_AVGHOPS]
+ = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
+ ts->counts[BGP_STATS_ASPATH_AVGHOPS],
+ hops);
+ ts->counts[BGP_STATS_ASPATH_AVGSIZE]
+ = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
+ ts->counts[BGP_STATS_ASPATH_AVGSIZE],
+ size);
+#endif
+ if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
+ ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ struct bgp_table_stats ts;
+ unsigned int i;
+
+ if (!bgp->rib[afi][safi])
+ {
+ vty_out (vty, "%% No RIB exist for the AFI/SAFI%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ memset (&ts, 0, sizeof (ts));
+ ts.table = bgp->rib[afi][safi];
+ thread_execute (bm->master, bgp_table_stats_walker, &ts, 0);
+
+ vty_out (vty, "BGP %s RIB statistics%s%s",
+ afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE);
+
+ for (i = 0; i < BGP_STATS_MAX; i++)
+ {
+ if (!table_stats_strs[i])
+ continue;
+
+ switch (i)
+ {
+#if 0
+ case BGP_STATS_ASPATH_AVGHOPS:
+ case BGP_STATS_ASPATH_AVGSIZE:
+ case BGP_STATS_AVGPLEN:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12.2f",
+ (float)ts.counts[i] / (float)TALLY_SIGFIG);
+ break;
+#endif
+ case BGP_STATS_ASPATH_TOTHOPS:
+ case BGP_STATS_ASPATH_TOTSIZE:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12.2f",
+ ts.counts[i] ?
+ (float)ts.counts[i] /
+ (float)ts.counts[BGP_STATS_ASPATH_COUNT]
+ : 0);
+ break;
+ case BGP_STATS_TOTPLEN:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12.2f",
+ ts.counts[i] ?
+ (float)ts.counts[i] /
+ (float)ts.counts[BGP_STATS_PREFIXES]
+ : 0);
+ break;
+ case BGP_STATS_SPACE:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12llu%s", ts.counts[i], VTY_NEWLINE);
+ if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
+ break;
+ vty_out (vty, "%30s: ", "\% announced ");
+ vty_out (vty, "%12.2f%s",
+ 100 * (float)ts.counts[BGP_STATS_SPACE] /
+ (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]),
+ VTY_NEWLINE);
+ vty_out (vty, "%30s: ", "/8 equivalent ");
+ vty_out (vty, "%12.2f%s",
+ (float)ts.counts[BGP_STATS_SPACE] /
+ (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)),
+ VTY_NEWLINE);
+ if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
+ break;
+ vty_out (vty, "%30s: ", "/24 equivalent ");
+ vty_out (vty, "%12.2f",
+ (float)ts.counts[BGP_STATS_SPACE] /
+ (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24)));
+ break;
+ default:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12llu", ts.counts[i]);
+ }
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
+static int
+bgp_table_stats_vty (struct vty *vty, const char *name,
+ const char *afi_str, const char *safi_str)
+{
+ struct bgp *bgp;
+ afi_t afi;
+ safi_t safi;
+
+ if (name)
+ bgp = bgp_lookup_by_name (name);
+ else
+ bgp = bgp_get_default ();
+
+ if (!bgp)
+ {
+ vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (strncmp (afi_str, "ipv", 3) == 0)
+ {
+ if (strncmp (afi_str, "ipv4", 4) == 0)
+ afi = AFI_IP;
+ else if (strncmp (afi_str, "ipv6", 4) == 0)
+ afi = AFI_IP6;
+ else
+ {
+ vty_out (vty, "%% Invalid address family %s%s",
+ afi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (strncmp (safi_str, "m", 1) == 0)
+ safi = SAFI_MULTICAST;
+ else if (strncmp (safi_str, "u", 1) == 0)
+ safi = SAFI_UNICAST;
+ else if (strncmp (safi_str, "vpnv4", 5) == 0)
+ safi = BGP_SAFI_VPNV4;
+ else if (strncmp (safi_str, "vpnv6", 6) == 0)
+ safi = BGP_SAFI_VPNV6;
+ else
+ {
+ vty_out (vty, "%% Invalid subsequent address family %s%s",
+ safi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ vty_out (vty, "%% Invalid address family %s%s",
+ afi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if ((afi == AFI_IP && safi == BGP_SAFI_VPNV6)
+ || (afi == AFI_IP6 && safi == BGP_SAFI_VPNV4))
+ {
+ vty_out (vty, "%% Invalid subsequent address family %s for %s%s",
+ afi_str, safi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return bgp_table_stats (vty, bgp, afi, safi);
+}
+
+DEFUN (show_bgp_statistics,
+ show_bgp_statistics_cmd,
+ "show bgp (ipv4|ipv6) (unicast|multicast) statistics",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+{
+ return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
+}
+
+ALIAS (show_bgp_statistics,
+ show_bgp_statistics_vpnv4_cmd,
+ "show bgp (ipv4) (vpnv4) statistics",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+
+DEFUN (show_bgp_statistics_view,
+ show_bgp_statistics_view_cmd,
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) statistics",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "Address family\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+{
+ return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
+}
+
+ALIAS (show_bgp_statistics_view,
+ show_bgp_statistics_view_vpnv4_cmd,
+ "show bgp view WORD (ipv4) (vpnv4) statistics",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+
+enum bgp_pcounts
+{
+ PCOUNT_ADJ_IN = 0,
+ PCOUNT_DAMPED,
+ PCOUNT_REMOVED,
+ PCOUNT_HISTORY,
+ PCOUNT_STALE,
+ PCOUNT_VALID,
+ PCOUNT_ALL,
+ PCOUNT_COUNTED,
+ PCOUNT_PFCNT, /* the figure we display to users */
+ PCOUNT_MAX,
+};
+
+static const char *pcount_strs[] =
+{
+ [PCOUNT_ADJ_IN] = "Adj-in",
+ [PCOUNT_DAMPED] = "Damped",
+ [PCOUNT_REMOVED] = "Removed",
+ [PCOUNT_HISTORY] = "History",
+ [PCOUNT_STALE] = "Stale",
+ [PCOUNT_VALID] = "Valid",
+ [PCOUNT_ALL] = "All RIB",
+ [PCOUNT_COUNTED] = "PfxCt counted",
+ [PCOUNT_PFCNT] = "Useable",
+ [PCOUNT_MAX] = NULL,
+};
+
+struct peer_pcounts
+{
+ unsigned int count[PCOUNT_MAX];
+ const struct peer *peer;
+ const struct bgp_table *table;
+};
+
+static int
+bgp_peer_count_walker (struct thread *t)
+{
+ struct bgp_node *rn;
+ struct peer_pcounts *pc = THREAD_ARG (t);
+ const struct peer *peer = pc->peer;
+
+ for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn))
+ {
+ struct bgp_adj_in *ain;
+ struct bgp_info *ri;
+
+ for (ain = rn->adj_in; ain; ain = ain->next)
+ if (ain->peer == peer)
+ pc->count[PCOUNT_ADJ_IN]++;
+
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ char buf[SU_ADDRSTRLEN];
+
+ if (ri->peer != peer)
+ continue;
+
+ pc->count[PCOUNT_ALL]++;
+
+ if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
+ pc->count[PCOUNT_DAMPED]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+ pc->count[PCOUNT_HISTORY]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED))
+ pc->count[PCOUNT_REMOVED]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
+ pc->count[PCOUNT_STALE]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_VALID))
+ pc->count[PCOUNT_VALID]++;
+ if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ pc->count[PCOUNT_PFCNT]++;
+
+ if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+ {
+ pc->count[PCOUNT_COUNTED]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ plog_warn (peer->log,
+ "%s [pcount] %s/%d is counted but flags 0x%x",
+ peer->host,
+ inet_ntop(rn->p.family, &rn->p.u.prefix,
+ buf, SU_ADDRSTRLEN),
+ rn->p.prefixlen,
+ ri->flags);
+ }
+ else
+ {
+ if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ plog_warn (peer->log,
+ "%s [pcount] %s/%d not counted but flags 0x%x",
+ peer->host,
+ inet_ntop(rn->p.family, &rn->p.u.prefix,
+ buf, SU_ADDRSTRLEN),
+ rn->p.prefixlen,
+ ri->flags);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi)
+{
+ struct peer_pcounts pcounts = { .peer = peer };
+ unsigned int i;
+
+ if (!peer || !peer->bgp || !peer->afc[afi][safi]
+ || !peer->bgp->rib[afi][safi])
+ {
+ vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ memset (&pcounts, 0, sizeof(pcounts));
+ pcounts.peer = peer;
+ pcounts.table = peer->bgp->rib[afi][safi];
+
+ /* in-place call via thread subsystem so as to record execution time
+ * stats for the thread-walk (i.e. ensure this can't be blamed on
+ * on just vty_read()).
+ */
+ thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0);
+
+ vty_out (vty, "Prefix counts for %s, %s%s",
+ peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
+ vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE);
+ vty_out (vty, "%sCounts from RIB table walk:%s%s",
+ VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+
+ for (i = 0; i < PCOUNT_MAX; i++)
+ vty_out (vty, "%20s: %-10d%s",
+ pcount_strs[i], pcounts.count[i], VTY_NEWLINE);
+
+ if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
+ {
+ vty_out (vty, "%s [pcount] PfxCt drift!%s",
+ peer->host, VTY_NEWLINE);
+ vty_out (vty, "Please report this bug, with the above command output%s",
+ VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_neighbor_prefix_counts,
+ show_ip_bgp_neighbor_prefix_counts_cmd,
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_bgp_ipv6_neighbor_prefix_counts,
+ show_bgp_ipv6_neighbor_prefix_counts_cmd,
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_peer_counts (vty, peer, AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts,
+ show_ip_bgp_ipv4_neighbor_prefix_counts_cmd,
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ if (! peer)
+ return CMD_WARNING;
+
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MULTICAST);
+
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
+ show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd,
+ "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN);
+}
+
static void
show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
@@ -10776,7 +11421,13 @@ bgp_route_init ()
install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
+ /* prefix count */
+ install_element (ENABLE_NODE, &show_ip_bgp_neighbor_prefix_counts_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_prefix_counts_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd);
#ifdef HAVE_IPV6
+ install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_prefix_counts_cmd);
+
/* New config IPv6 BGP commands. */
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
@@ -10946,7 +11597,13 @@ bgp_route_init ()
install_element (ENABLE_NODE, &show_bgp_view_rsclient_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd);
-
+
+ /* Statistics */
+ install_element (ENABLE_NODE, &show_bgp_statistics_cmd);
+ install_element (ENABLE_NODE, &show_bgp_statistics_vpnv4_cmd);
+ install_element (ENABLE_NODE, &show_bgp_statistics_view_cmd);
+ install_element (ENABLE_NODE, &show_bgp_statistics_view_vpnv4_cmd);
+
/* old command */
install_element (VIEW_NODE, &show_ipv6_bgp_cmd);
install_element (VIEW_NODE, &show_ipv6_bgp_route_cmd);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index e5f3ae59..b0c2fccf 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -105,6 +105,17 @@ struct bgp_static
u_char tag[3];
};
+/* Flags which indicate a route is unuseable in some form */
+#define BGP_INFO_UNUSEABLE \
+ (BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED)
+/* Macro to check BGP information is alive or not. Sadly,
+ * not equivalent to just checking previous, because of the
+ * sense of the additional VALID flag.
+ */
+#define BGP_INFO_HOLDDOWN(BI) \
+ (! CHECK_FLAG ((BI)->flags, BGP_INFO_VALID) \
+ || CHECK_FLAG ((BI)->flags, BGP_INFO_UNUSEABLE))
+
#define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name)
#define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist)
#define DISTRIBUTE_OUT_NAME(F) ((F)->dlist[FILTER_OUT].name)
@@ -151,6 +162,8 @@ extern struct bgp_info *bgp_info_lock (struct bgp_info *);
extern struct bgp_info *bgp_info_unlock (struct bgp_info *);
extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri);
+extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
+extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
extern int bgp_nlri_sanity_check (struct peer *, int, u_char *, bgp_size_t);
extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 93096dc0..10c9778e 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -6800,8 +6800,6 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
vty_out (vty, " Idle (Admin)");
else if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
vty_out (vty, " Idle (PfxCt)");
- else if (CHECK_FLAG (peer->sflags, PEER_STATUS_CLEARING))
- vty_out (vty, " Idle (Clrng)");
else
vty_out (vty, " %-11s", LOOKUP(bgp_status_msg, peer->status));
}
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index a25297ab..1686b20e 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA. */
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_debug.h"
/* All information about zebra. */
static struct zclient *zclient = NULL;
@@ -50,6 +51,14 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
struct bgp *bgp;
zebra_router_id_update_read(zclient->ibuf,&router_id);
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[128];
+ prefix2str(&router_id, buf, sizeof(buf));
+ zlog_debug("Zebra rcvd: router id update %s", buf);
+ }
+
router_id_zebra = router_id.u.prefix4;
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
@@ -69,6 +78,9 @@ bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
ifp = zebra_interface_add_read (zclient->ibuf);
+ if (BGP_DEBUG(zebra, ZEBRA) && ifp)
+ zlog_debug("Zebra rcvd: interface add %s", ifp->name);
+
return 0;
}
@@ -83,6 +95,9 @@ bgp_interface_delete (int command, struct zclient *zclient,
ifp = zebra_interface_state_read (s);
ifp->ifindex = IFINDEX_INTERNAL;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
+
return 0;
}
@@ -100,6 +115,9 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
if (! ifp)
return 0;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Zebra rcvd: interface %s up", ifp->name);
+
for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
bgp_connected_add (c);
@@ -119,6 +137,9 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
if (! ifp)
return 0;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Zebra rcvd: interface %s down", ifp->name);
+
for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
bgp_connected_delete (c);
@@ -164,6 +185,14 @@ bgp_interface_address_add (int command, struct zclient *zclient,
if (ifc == NULL)
return 0;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[128];
+ prefix2str(ifc->address, buf, sizeof(buf));
+ zlog_debug("Zebra rcvd: interface %s address add %s",
+ ifc->ifp->name, buf);
+ }
+
if (if_is_operative (ifc->ifp))
bgp_connected_add (ifc);
@@ -181,6 +210,14 @@ bgp_interface_address_delete (int command, struct zclient *zclient,
if (ifc == NULL)
return 0;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[128];
+ prefix2str(ifc->address, buf, sizeof(buf));
+ zlog_debug("Zebra rcvd: interface %s address delete %s",
+ ifc->ifp->name, buf);
+ }
+
if (if_is_operative (ifc->ifp))
bgp_connected_delete (ifc);
@@ -233,9 +270,34 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
api.metric = 0;
if (command == ZEBRA_IPV4_ROUTE_ADD)
- bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type);
+ {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
+ zebra_route_string(api.type),
+ inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
+ p.prefixlen,
+ inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+ bgp_redistribute_add((struct prefix *)&p, &nexthop, api.metric, api.type);
+ }
else
- bgp_redistribute_delete ((struct prefix *)&p, api.type);
+ {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
+ "nexthop %s metric %u",
+ zebra_route_string(api.type),
+ inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
+ p.prefixlen,
+ inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+ bgp_redistribute_delete((struct prefix *)&p, api.type);
+ }
return 0;
}
@@ -291,9 +353,29 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
return 0;
if (command == ZEBRA_IPV6_ROUTE_ADD)
- bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
+ {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[INET6_ADDRSTRLEN];
+ zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d metric %u",
+ zebra_route_string(api.type),
+ inet_ntop(AF_INET6, &p.prefix, buf, sizeof(buf)),
+ p.prefixlen, api.metric);
+ }
+ bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
+ }
else
- bgp_redistribute_delete ((struct prefix *) &p, api.type);
+ {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[INET6_ADDRSTRLEN];
+ zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
+ zebra_route_string(api.type),
+ inet_ntop(AF_INET6, &p.prefix, buf, sizeof(buf)),
+ p.prefixlen, api.metric);
+ }
+ bgp_redistribute_delete ((struct prefix *) &p, api.type);
+ }
return 0;
}
@@ -649,6 +731,16 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
}
#endif
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u",
+ inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
(struct prefix_ipv4 *) p, &api);
}
@@ -705,6 +797,16 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET6_ADDRSTRLEN];
+ zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u",
+ inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
(struct prefix_ipv6 *) p, &api);
}
@@ -753,6 +855,16 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u",
+ inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
(struct prefix_ipv4 *) p, &api);
}
@@ -798,6 +910,16 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET6_ADDRSTRLEN];
+ zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u",
+ inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
(struct prefix_ipv6 *) p, &api);
}
@@ -820,6 +942,9 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
/* Return if zebra connection is not established. */
if (zclient->sock < 0)
return CMD_WARNING;
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
/* Send distribute add message to zebra. */
zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
@@ -884,8 +1009,13 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
if (bgp->redist[AFI_IP][type] == 0
&& bgp->redist[AFI_IP6][type] == 0
&& zclient->sock >= 0)
- /* Send distribute delete message to zebra. */
- zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+ {
+ /* Send distribute delete message to zebra. */
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Zebra send: redistribute delete %s",
+ zebra_route_string(type));
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+ }
/* Withdraw redistributed routes from current BGP's routing table. */
bgp_redistribute_withdraw (bgp, afi, type);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 6256c54a..7163f3f9 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -691,6 +691,16 @@ peer_sort (struct peer *peer)
static inline void
peer_free (struct peer *peer)
{
+ assert (peer->status == Deleted);
+
+ /* this /ought/ to have been done already through bgp_stop earlier,
+ * but just to be sure..
+ */
+ bgp_timer_set (peer);
+ BGP_READ_OFF (peer->t_read);
+ BGP_WRITE_OFF (peer->t_write);
+ BGP_EVENT_FLUSH (peer);
+
if (peer->desc)
XFREE (MTYPE_PEER_DESC, peer->desc);
@@ -708,6 +718,7 @@ peer_free (struct peer *peer)
if (peer->clear_node_queue)
work_queue_free (peer->clear_node_queue);
+ bgp_sync_delete (peer);
memset (peer, 0, sizeof (struct peer));
XFREE (MTYPE_BGP_PEER, peer);
@@ -718,7 +729,8 @@ struct peer *
peer_lock (struct peer *peer)
{
assert (peer && (peer->lock >= 0));
-
+ assert (peer->status != Deleted);
+
peer->lock++;
return peer;
@@ -757,26 +769,31 @@ peer_unlock (struct peer *peer)
/* Allocate new peer object, implicitely locked. */
static struct peer *
-peer_new ()
+peer_new (struct bgp *bgp)
{
afi_t afi;
safi_t safi;
struct peer *peer;
struct servent *sp;
-
+
+ /* bgp argument is absolutely required */
+ assert (bgp);
+ if (!bgp)
+ return NULL;
+
/* Allocate new peer. */
- peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
- memset (peer, 0, sizeof (struct peer));
+ peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
/* Set default value. */
peer->fd = -1;
- peer->lock = 1;
peer->v_start = BGP_INIT_START_TIMER;
peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
peer->status = Idle;
peer->ostatus = Idle;
peer->weight = 0;
+ peer->bgp = bgp;
+ peer = peer_lock (peer); /* initial reference */
#ifdef SUPPORT_REALMS
peer->realm = 0;
@@ -818,8 +835,7 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
struct peer *peer;
char buf[SU_ADDRSTRLEN];
- peer = peer_new ();
- peer->bgp = bgp;
+ peer = peer_new (bgp);
peer->su = *su;
peer->local_as = local_as;
peer->as = remote_as;
@@ -865,8 +881,7 @@ peer_create_accept (struct bgp *bgp)
{
struct peer *peer;
- peer = peer_new ();
- peer->bgp = bgp;
+ peer = peer_new (bgp);
peer = peer_lock (peer); /* bgp peer list reference */
listnode_add_sort (bgp->peer, peer);
@@ -1147,7 +1162,17 @@ peer_nsf_stop (struct peer *peer)
bgp_clear_route_all (peer);
}
-/* Delete peer from confguration. */
+/* Delete peer from confguration.
+ *
+ * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
+ * it to "cool off" and refcounts to hit 0, at which state it is freed.
+ *
+ * This function /should/ take care to be idempotent, to guard against
+ * it being called multiple times through stray events that come in
+ * that happen to result in this function being called again. That
+ * said, getting here for a "Deleted" peer is a bug in the neighbour
+ * FSM.
+ */
int
peer_delete (struct peer *peer)
{
@@ -1157,6 +1182,8 @@ peer_delete (struct peer *peer)
struct bgp *bgp;
struct bgp_filter *filter;
+ assert (peer->status != Deleted);
+
bgp = peer->bgp;
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
@@ -1166,8 +1193,13 @@ peer_delete (struct peer *peer)
relationship. */
if (peer->group)
{
- peer = peer_unlock (peer); /* peer-group reference */
- listnode_delete (peer->group->peer, peer);
+ struct listnode *pn;
+
+ if ((pn = listnode_lookup (peer->group->peer, peer)))
+ {
+ peer = peer_unlock (peer); /* group->peer list reference */
+ list_delete_node (peer->group->peer, pn);
+ }
peer->group = NULL;
}
@@ -1177,29 +1209,25 @@ peer_delete (struct peer *peer)
*/
peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
bgp_stop (peer);
- bgp_fsm_change_status (peer, Idle); /* stops all timers */
+ bgp_fsm_change_status (peer, Deleted);
+ bgp_timer_set (peer); /* stops all timers for Deleted */
- /* Stop all timers - should already have been done in bgp_stop */
- BGP_TIMER_OFF (peer->t_start);
- BGP_TIMER_OFF (peer->t_connect);
- BGP_TIMER_OFF (peer->t_holdtime);
- BGP_TIMER_OFF (peer->t_keepalive);
- 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))
{
- peer_unlock (peer); /* bgp peer list reference */
- listnode_delete (bgp->peer, peer);
+ struct listnode *pn;
- if (peer_rsclient_active (peer))
+ if ((pn = listnode_lookup (bgp->peer, peer)))
+ {
+ peer_unlock (peer); /* bgp peer list reference */
+ list_delete_node (bgp->peer, pn);
+ }
+
+ if (peer_rsclient_active (peer)
+ && (pn = listnode_lookup (bgp->rsclient, peer)))
{
peer_unlock (peer); /* rsclient list reference */
- listnode_delete (bgp->rsclient, peer);
+ list_delete_node (bgp->rsclient, pn);
}
}
@@ -1227,8 +1255,6 @@ peer_delete (struct peer *peer)
sockunion_free (peer->su_remote);
peer->su_local = peer->su_remote = NULL;
- bgp_sync_delete (peer);
-
/* Free filter related memory. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
@@ -1330,11 +1356,10 @@ peer_group_get (struct bgp *bgp, const char *name)
group->bgp = bgp;
group->name = strdup (name);
group->peer = list_new ();
- group->conf = peer_new ();
+ group->conf = peer_new (bgp);
if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
group->conf->host = strdup (name);
- group->conf->bgp = bgp;
group->conf->group = group;
group->conf->as = 0;
group->conf->ttl = 1;
@@ -1707,7 +1732,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
peer->group = group;
peer->af_group[afi][safi] = 1;
- peer = peer_lock (peer); /* peer-group group->peer reference */
+ peer = peer_lock (peer); /* group->peer list reference */
listnode_add (group->peer, peer);
peer_group2peer_config_copy (group, peer, afi, safi);
@@ -1748,9 +1773,11 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
{
peer->group = group;
- peer = peer_lock (peer); /* peer-group group->peer reference */
+ peer = peer_lock (peer); /* group->peer list reference */
listnode_add (group->peer, peer);
}
+ else
+ assert (group && peer->group == group);
if (first_member)
{
@@ -1774,13 +1801,16 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
{
+ struct listnode *pn;
+
/* If it's not configured as RSERVER_CLIENT in any other address
family, without being member of a peer_group, remove it from
list bgp->rsclient.*/
- if (! peer_rsclient_active (peer))
+ if (! peer_rsclient_active (peer)
+ && (pn = listnode_lookup (bgp->rsclient, peer)))
{
peer_unlock (peer); /* peer rsclient reference */
- listnode_delete (bgp->rsclient, peer);
+ list_delete_node (bgp->rsclient, pn);
}
bgp_table_finish (peer->rib[afi][safi]);
@@ -1836,6 +1866,7 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
if (! peer_group_active (peer))
{
+ assert (listnode_lookup (group->peer, peer));
peer_unlock (peer); /* peer group list reference */
listnode_delete (group->peer, peer);
peer->group = NULL;
@@ -1870,7 +1901,7 @@ bgp_create (as_t *as, const char *name)
if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
return NULL;
- bgp->peer_self = peer_new ();
+ bgp->peer_self = peer_new (bgp);
bgp->peer_self->host = strdup ("Static announcement");
bgp->peer = list_new ();
@@ -4290,8 +4321,7 @@ peer_uptime (time_t uptime2, char *buf, size_t len)
/* Check buffer length. */
if (len < BGP_UPTIME_LEN)
{
- /* XXX: warning: long int format, size_t arg (arg 2) */
- zlog_warn ("peer_uptime (): buffer shortage %ld", len);
+ zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
/* XXX: should return status instead of buf... */
snprintf (buf, len, "<error> ");
return buf;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index dc451e78..e2802b9b 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -386,7 +386,6 @@ struct peer
#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 */
-#define PEER_STATUS_CLEARING (1 << 7) /* peers table being cleared */
/* Peer status af flags (reset in bgp_stop) */
u_int16_t af_sflags[AFI_MAX][SAFI_MAX];
@@ -667,7 +666,9 @@ struct bgp_nlri
#define OpenSent 4
#define OpenConfirm 5
#define Established 6
-#define BGP_STATUS_MAX 7
+#define Clearing 7
+#define Deleted 8
+#define BGP_STATUS_MAX 9
/* BGP finite state machine events. */
#define BGP_Start 1
@@ -683,7 +684,8 @@ struct bgp_nlri
#define Receive_KEEPALIVE_message 11
#define Receive_UPDATE_message 12
#define Receive_NOTIFICATION_message 13
-#define BGP_EVENTS_MAX 14
+#define Clearing_Completed 14
+#define BGP_EVENTS_MAX 15
/* BGP timers default value. */
#define BGP_INIT_START_TIMER 5
@@ -745,13 +747,6 @@ enum bgp_clear_type
#define BGP_INPUT(P) ((P)->ibuf)
#define BGP_INPUT_PNT(P) (STREAM_PNT(BGP_INPUT(P)))
-/* Macro to check BGP information is alive or not. */
-#define BGP_INFO_HOLDDOWN(BI) \
- (! CHECK_FLAG ((BI)->flags, BGP_INFO_VALID) \
- || CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \
- || CHECK_FLAG ((BI)->flags, BGP_INFO_DAMPED) \
- || CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED))
-
/* Count prefix size from mask length */
#define PSIZE(a) (((a) + 7) / (8))