summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey C. Ollie <jeff@ocjtech.us>2007-04-09 15:36:33 -0500
committerJeffrey C. Ollie <jeff@ocjtech.us>2007-04-09 15:36:33 -0500
commit37e11172f8ed157340783b73d56595bb02d0a2d2 (patch)
tree65163a9cdb8ded9c55c94da92e8a6327bda9067c
parent8d3e3ccfd0d0cb82b253f937339d1c6189a2bf54 (diff)
parent43cd33a44e010f818633b7f144b5a0be352b41e7 (diff)
downloadquagga-37e11172f8ed157340783b73d56595bb02d0a2d2.tar.bz2
quagga-37e11172f8ed157340783b73d56595bb02d0a2d2.tar.xz
Merge commit 'quagga_0_99_6_release' into linux-realmsquagga-0.99.6-realms.patch
-rw-r--r--ChangeLog28
-rw-r--r--INSTALL.quagga.txt11
-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
-rwxr-xr-xconfigure.ac2
-rw-r--r--isisd/ChangeLog9
-rw-r--r--isisd/isis_adjacency.c5
-rw-r--r--isisd/isis_circuit.c12
-rw-r--r--isisd/isis_lsp.c2
-rw-r--r--isisd/isis_main.c22
-rw-r--r--isisd/isis_misc.c16
-rw-r--r--isisd/isis_misc.h5
-rw-r--r--isisd/isis_pdu.c6
-rw-r--r--isisd/isis_route.c9
-rw-r--r--isisd/isis_routemap.c8
-rw-r--r--isisd/isis_spf.c8
-rw-r--r--isisd/isis_tlv.c5
-rw-r--r--isisd/isis_zebra.c6
-rw-r--r--isisd/isisd.c25
-rw-r--r--isisd/iso_checksum.c6
-rw-r--r--isisd/topology/random.c12
-rw-r--r--isisd/topology/spgrid.c9
-rw-r--r--lib/ChangeLog20
-rw-r--r--lib/if.c48
-rw-r--r--lib/smux.c14
-rw-r--r--ospf6d/ospf6_main.c12
-rw-r--r--ospfd/ChangeLog77
-rw-r--r--ospfd/ospf_interface.c3
-rw-r--r--ospfd/ospf_interface.h7
-rw-r--r--ospfd/ospf_main.c12
-rw-r--r--ospfd/ospf_packet.c61
-rw-r--r--ospfd/ospf_vty.c153
-rw-r--r--ospfd/ospf_zebra.c47
-rw-r--r--ospfd/ospfd.c4
-rw-r--r--ospfd/ospfd.h1
-rw-r--r--ripd/ChangeLog8
-rw-r--r--ripd/rip_main.c12
-rw-r--r--ripd/rip_routemap.c2
-rw-r--r--ripd/ripd.c5
-rw-r--r--ripngd/ripng_main.c12
-rw-r--r--vtysh/vtysh_main.c12
-rw-r--r--zebra/ChangeLog11
-rw-r--r--zebra/kernel_socket.c4
-rw-r--r--zebra/main.c14
-rw-r--r--zebra/zebra_rib.c22
60 files changed, 2047 insertions, 431 deletions
diff --git a/ChangeLog b/ChangeLog
index 83d22abc..fca2eebc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2006-12-08 Paul Jakma <paul.jakma@sun.com>
+
+ * configure.ac: Bump to 0.99.6
+
+2006-10-04 Oliver Hookins <ohookins@gmail.com>
+
+ * bgpd/bgp_main.c: Add configuration check option, with
+ '-C' rather than '-c' for consistency between daemons.
+ * isisd/isis_main.c: ditto
+ * ospf6d/ospf6_main.c: ditto
+ * ospfd/ospf_main.c: ditto
+ * ripngd/ripng_main.c: ditto
+ * vtysh/vtysh_main.c: ditto
+ * ripd/rip_main.c: Change the config check option to
+ '-C' and tidy up the code.
+ * zebra/main.c: ditto
+
+2006-10-04 Stergiakis Alexandros <astergiakis@antcor.com>
+
+ * ripd/rip_main.c: This trivial patch introduces a new
+ command-line option '-c', which instructs zebra/ripd
+ to check its configuration file for validity, print
+ any error message, and then exit. This is useful when
+ the configuration file is edited by hand or otherwise,
+ and you simply want to validate it without any other
+ effect.
+ * zebra/main.c: ditto
+
2006-08-27 Paul Jakma <paul.jakma@sun.com>
* configure.ac: Bump to 0.99.5
diff --git a/INSTALL.quagga.txt b/INSTALL.quagga.txt
index b1bab82f..4ed9a67f 100644
--- a/INSTALL.quagga.txt
+++ b/INSTALL.quagga.txt
@@ -1,4 +1,4 @@
-# $Id: INSTALL.quagga.txt,v 1.11 2005/08/10 15:07:02 gdt Exp $
+# $Id$
--------------------------------------------------------------------------
Building and Installing Quagga from releases or snapshots:
@@ -6,7 +6,8 @@ Building and Installing Quagga from releases or snapshots:
The 'INSTALL' file contains generic instructions on how to use 'configure'
scripts.
-Quagga requires a C compiler supporting the C99 standard.
+Quagga requires a C compiler (and associated header files and
+libraries) supporting the C99 standard.
Quagga requires a reasonable make. It is considered a bug if quagga
does not compile with the system make on recent FreeBSD, NetBSD or
@@ -20,11 +21,17 @@ following systems (where .x indicates the most recent release), or
such systems "-current" versions. (Note that considering it a bug is
not a guarantee of support, merely "we agree that it is broken".)
+ Dragonfly ?
FreeBSD 4.x
FreeBSD 5.x
+ FreeBSD 6.x
+ FreeBSD-current
Linux [kernel/distribution information needed]
NetBSD 1.6.x
NetBSD 2.x
+ NetBSD 3.x
+ NetBSD 4.x
+ NetBSD-current
OpenBSD ? [info needed on what should work]
Solaris 9
Solaris 10
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))
diff --git a/configure.ac b/configure.ac
index 7c0b5df7..13e59e6a 100755
--- a/configure.ac
+++ b/configure.ac
@@ -8,7 +8,7 @@
## $Id$
AC_PREREQ(2.53)
-AC_INIT(Quagga, 0.99.5-realms, [http://bugzilla.quagga.net])
+AC_INIT(Quagga, 0.99.6-realms, [http://bugzilla.quagga.net])
AC_CONFIG_SRCDIR(lib/zebra.h)
dnl -----------------------------------
diff --git a/isisd/ChangeLog b/isisd/ChangeLog
index 5e203c8c..8797af18 100644
--- a/isisd/ChangeLog
+++ b/isisd/ChangeLog
@@ -1,3 +1,12 @@
+2006-12-08 Hannes Gredler <hannes@gredler.at>
+
+ * isis_adjacency.c: (isis_new_adj) Allow NULL snpa argument.
+ * isis_pdu.c: (various) Update calls to isis_new_adj() to pass
+ NULL and use default.
+ * (general) Add forward declarations where required.
+ Fix up const char *'s.
+ Allow V4-only compilation.
+
2006-01-17 Paul Jakma <paul.jakma@sun.com>
* isis_zebra.c: (isis_zebra_route_add_ipv4) fix for new
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index d8c7448e..aab8d1a3 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -72,7 +72,12 @@ isis_new_adj (u_char * id, u_char * snpa, int level,
return NULL;
}
+ if (snpa) {
memcpy (adj->snpa, snpa, 6);
+ } else {
+ memset (adj->snpa, ' ', 6);
+ }
+
adj->circuit = circuit;
adj->level = level;
adj->flaps = 0;
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 76145f02..6ef24a9a 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -57,6 +57,14 @@
extern struct thread_master *master;
extern struct isis *isis;
+/*
+ * Prototypes.
+ */
+void isis_circuit_down(struct isis_circuit *);
+int isis_interface_config_write(struct vty *);
+int isis_if_new_hook(struct interface *);
+int isis_if_delete_hook(struct interface *);
+
struct isis_circuit *
isis_circuit_new ()
{
@@ -275,10 +283,10 @@ isis_circuit_del_addr (struct isis_circuit *circuit,
{
struct prefix_ipv4 *ipv4, *ip = NULL;
struct listnode *node;
- int found = 0;
u_char buf[BUFSIZ];
#ifdef HAVE_IPV6
struct prefix_ipv6 *ipv6, *ip6 = NULL;
+ int found = 0;
#endif /* HAVE_IPV6 */
memset (&buf, 0, BUFSIZ);
@@ -944,7 +952,7 @@ DEFUN (isis_circuit_type,
assert (circuit);
- circuit_t = string2circuit_t ((u_char *)argv[0]);
+ circuit_t = string2circuit_t (argv[0]);
if (!circuit_t)
{
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 63f2b6b9..1a4deb1b 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -727,10 +727,10 @@ lsp_print_detail (dnode_t * node, struct vty *vty, char dynhost)
#ifdef HAVE_IPV6
struct ipv6_reachability *ipv6_reach;
struct in6_addr in6;
+ u_char buff[BUFSIZ];
#endif
u_char LSPid[255];
u_char hostname[255];
- u_char buff[BUFSIZ];
u_char ipv4_reach_prefix[20];
u_char ipv4_reach_mask[20];
u_char ipv4_address[20];
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 6971874d..2411518d 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -80,6 +80,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}
};
@@ -106,6 +107,16 @@ int _argc;
char **_argv;
char **_envp;
+/*
+ * Prototypes.
+ */
+void reload(void);
+void sighup(void);
+void sigint(void);
+void sigterm(void);
+void sigusr1(void);
+
+
/* Help information display. */
static void
usage (int status)
@@ -124,6 +135,7 @@ Daemon which manages IS-IS routing\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 http://bugzilla.quagga.net\n", progname);
@@ -213,6 +225,7 @@ main (int argc, char **argv, char **envp)
struct thread thread;
char *config_file = NULL;
char *vty_addr = NULL;
+ int dryrun = 0;
/* Get the programname without the preceding path. */
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
@@ -233,7 +246,7 @@ main (int argc, char **argv, char **envp)
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:hA:p:P:u:g:v", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:hA:p:P:u:g:vC", longopts, 0);
if (opt == EOF)
break;
@@ -278,6 +291,9 @@ main (int argc, char **argv, char **envp)
print_version ("Zebra");
exit (0);
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'h':
usage (0);
break;
@@ -312,6 +328,10 @@ main (int argc, char **argv, char **envp)
vty_read_config (config_file, config_default);
vty_read_config (config_file, config_default);
+ /* Start execution only if not in dry-run mode */
+ if (dryrun)
+ return(0);
+
/* demonize */
if (daemon_mode)
daemon (0, 0);
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 384ebe0b..6b565bcb 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -99,15 +99,15 @@ isonet_print (u_char * from, int len)
* extract dot from the dotted str, and insert all the number in a buff
*/
int
-dotformat2buff (u_char * buff, u_char * dotted)
+dotformat2buff (u_char * buff, const u_char * dotted)
{
int dotlen, len = 0;
- u_char *pos = dotted;
+ const u_char *pos = dotted;
u_char number[3];
int nextdotpos = 2;
number[2] = '\0';
- dotlen = strlen ((char *)dotted);
+ dotlen = strlen(dotted);
if (dotlen > 50)
{
/* this can't be an iso net, its too long */
@@ -165,7 +165,7 @@ sysid2buff (u_char * buff, const u_char * dotted)
number[2] = '\0';
// surely not a sysid_string if not 14 length
- if (strlen ((char *)dotted) != 14)
+ if (strlen (dotted) != 14)
{
return 0;
}
@@ -271,19 +271,19 @@ speaks (struct nlpids *nlpids, int family)
* Returns 0 on error, IS-IS Circuit Type on ok
*/
int
-string2circuit_t (u_char * str)
+string2circuit_t (const u_char * str)
{
if (!str)
return 0;
- if (!strcmp ((char *)str, "level-1"))
+ if (!strcmp (str, "level-1"))
return IS_LEVEL_1;
- if (!strcmp ((char *)str, "level-2-only") || !strcmp ((char *)str, "level-2"))
+ if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
return IS_LEVEL_2;
- if (!strcmp ((char *)str, "level-1-2"))
+ if (!strcmp (str, "level-1-2"))
return IS_LEVEL_1_AND_2;
return 0;
diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h
index 3b975895..d5003a8e 100644
--- a/isisd/isis_misc.h
+++ b/isisd/isis_misc.h
@@ -24,8 +24,7 @@
#ifndef _ZEBRA_ISIS_MISC_H
#define _ZEBRA_ISIS_MISC_H
-int dotformat2buff (u_char *, u_char *);
-int string2circuit_t (u_char *);
+int string2circuit_t (const u_char *);
const char *circuit_t2string (int);
const char *syst2string (int);
struct in_addr newprefix2inaddr (u_char * prefix_start,
@@ -34,7 +33,7 @@ struct in_addr newprefix2inaddr (u_char * prefix_start,
* Converting input to memory stored format
* return value of 0 indicates wrong input
*/
-int dotformat2buff (u_char *, u_char *);
+int dotformat2buff (u_char *, const u_char *);
int sysid2buff (u_char *, const u_char *);
/*
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 2dc82156..6fcc5ed5 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -335,7 +335,7 @@ process_p2p_hello (struct isis_circuit *circuit)
adj = circuit->u.p2p.neighbor;
if (!adj)
{
- adj = isis_new_adj (hdr->source_id, (u_char *) " ", 0, circuit);
+ adj = isis_new_adj (hdr->source_id, NULL, 0, circuit);
if (adj == NULL)
return ISIS_ERROR;
circuit->u.p2p.neighbor = adj;
@@ -1596,7 +1596,7 @@ process_is_hello (struct isis_circuit *circuit)
if (!adj)
{
/* 8.2.2 */
- adj = isis_new_adj (sysid, (u_char *) " ", 0, circuit);
+ adj = isis_new_adj (sysid, NULL, 0, circuit);
if (adj == NULL)
return ISIS_ERROR;
@@ -1612,7 +1612,7 @@ process_is_hello (struct isis_circuit *circuit)
/* 8.2.2 a) 2) delete the adj */
XFREE (MTYPE_ISIS_ADJACENCY, adj);
/* 8.2.2 a) 3) create a new adj */
- adj = isis_new_adj (sysid, (u_char *) " ", 0, circuit);
+ adj = isis_new_adj (sysid, NULL, 0, circuit);
if (adj == NULL)
return ISIS_ERROR;
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index c8f0aaba..1286486c 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -631,6 +631,8 @@ isis_route_validate_table (struct isis_area *area, struct route_table *table)
if (drnode->info == rnode->info)
drnode->info = NULL;
}
+
+#ifdef HAVE_IPV6
if (rnode->p.family == AF_INET6)
{
drnode = route_node_get (area->route_table6[0], &rnode->p);
@@ -640,6 +642,7 @@ isis_route_validate_table (struct isis_area *area, struct route_table *table)
if (drnode->info == rnode->info)
drnode->info = NULL;
}
+#endif
isis_route_delete (&rnode->p, table);
}
@@ -667,8 +670,10 @@ isis_route_validate_merge (struct isis_area *area, int family)
if (family == AF_INET)
table = area->route_table[0];
+#ifdef HAVE_IPV6
else if (family == AF_INET6)
table = area->route_table6[0];
+#endif
for (rnode = route_top (table); rnode; rnode = route_next (rnode))
{
@@ -680,8 +685,10 @@ isis_route_validate_merge (struct isis_area *area, int family)
if (family == AF_INET)
table = area->route_table[1];
+#ifdef HAVE_IPV6
else if (family == AF_INET6)
table = area->route_table6[1];
+#endif
for (rnode = route_top (table); rnode; rnode = route_next (rnode))
{
@@ -719,8 +726,8 @@ isis_route_validate (struct thread *thread)
isis_route_validate_merge (area, AF_INET);
-#ifdef HAVE_IPV6
validate_ipv6:
+#ifdef HAVE_IPV6
if (area->is_type == IS_LEVEL_1)
{
isis_route_validate_table (area, area->route_table6[0]);
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
index 4235d882..cff0fa3f 100644
--- a/isisd/isis_routemap.c
+++ b/isisd/isis_routemap.c
@@ -49,6 +49,14 @@
extern struct isis *isis;
+/*
+ * Prototypes.
+ */
+void isis_route_map_upd(const char *);
+void isis_route_map_event(route_map_event_t, const char *);
+void isis_route_map_init(void);
+
+
void
isis_route_map_upd (const char *name)
{
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 706ed16c..5d7e9da4 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -998,8 +998,10 @@ isis_run_spf (struct isis_area *area, int level, int family)
/* Make all routes in current route table inactive. */
if (family == AF_INET)
table = area->route_table[level - 1];
+#ifdef HAVE_IPV6
else if (family == AF_INET6)
table = area->route_table6[level - 1];
+#endif
for (rode = route_top (table); rode; rode = route_next (rode))
{
@@ -1333,16 +1335,16 @@ isis_print_paths (struct vty *vty, struct list *paths)
nh_dyn = dynhn_find_by_id (adj->sysid);
vty_out (vty, "%-20s %-10u %-20s %-11s %-5s%s",
(dyn != NULL) ? dyn->name.name :
- (u_char *) rawlspid_print ((u_char *) vertex->N.id),
+ (const u_char *)rawlspid_print ((u_char *) vertex->N.id),
vertex->d_N, (nh_dyn != NULL) ? nh_dyn->name.name :
- (u_char *) rawlspid_print (adj->sysid),
+ (const u_char *)rawlspid_print (adj->sysid),
adj->circuit->interface->name,
snpa_print (adj->snpa), VTY_NEWLINE);
}
else
{
vty_out (vty, "%s %u %s", dyn ? dyn->name.name :
- (u_char *) rawlspid_print (vertex->N.id),
+ (const u_char *) rawlspid_print (vertex->N.id),
vertex->d_N, VTY_NEWLINE);
}
}
diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c
index 7b99ab5d..94fa65ed 100644
--- a/isisd/isis_tlv.c
+++ b/isisd/isis_tlv.c
@@ -45,6 +45,11 @@
extern struct isis *isis;
+/*
+ * Prototypes.
+ */
+int add_tlv (u_char, u_char, u_char *, struct stream *);
+
void
free_tlv (void *val)
{
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 4631cc70..9ee5ffc5 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -72,7 +72,7 @@ isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
if (isis->debugs & DEBUG_ZEBRA)
zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+ ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
if (if_is_operative (ifp))
isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
@@ -98,7 +98,7 @@ isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
if (isis->debugs & DEBUG_ZEBRA)
zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+ ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
/* Cannot call if_delete because we should retain the pseudo interface
@@ -571,12 +571,14 @@ isis_zebra_read_ipv4 (int command, struct zclient *zclient,
return 0;
}
+#ifdef HAVE_IPV6
static int
isis_zebra_read_ipv6 (int command, struct zclient *zclient,
zebra_size_t length)
{
return 0;
}
+#endif
#define ISIS_TYPE_IS_REDISTRIBUTED(T) \
T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
diff --git a/isisd/isisd.c b/isisd/isisd.c
index c5c2153f..48ea47af 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -61,6 +61,21 @@ u_char DEFAULT_TOPOLOGY_BASEIS[6] = { 0xFE, 0xED, 0xFE, 0xED, 0x00, 0x00 };
struct isis *isis = NULL;
extern struct thread_master *master;
+/*
+ * Prototypes.
+ */
+void isis_new(unsigned long);
+struct isis_area *isis_area_create(void);
+int isis_area_get(struct vty *, const char *);
+int isis_area_destroy(struct vty *, const char *);
+int area_net_title(struct vty *, const u_char *);
+int area_clear_net_title(struct vty *, const u_char *);
+int show_clns_neigh(struct vty *, char);
+void print_debug(struct vty *, int, int);
+int isis_config_write(struct vty *);
+
+
+
void
isis_new (unsigned long process_id)
{
@@ -217,7 +232,7 @@ isis_area_destroy (struct vty *vty, const char *area_tag)
}
int
-area_net_title (struct vty *vty, u_char *net_title)
+area_net_title (struct vty *vty, const u_char *net_title)
{
struct isis_area *area;
struct area_addr *addr;
@@ -311,7 +326,7 @@ area_net_title (struct vty *vty, u_char *net_title)
}
int
-area_clear_net_title (struct vty *vty, u_char *net_title)
+area_clear_net_title (struct vty *vty, const u_char *net_title)
{
struct isis_area *area;
struct area_addr addr, *addrp = NULL;
@@ -997,7 +1012,7 @@ DEFUN (net,
"A Network Entity Title for this process (OSI only)\n"
"XX.XXXX. ... .XXX.XX Network entity title (NET)\n")
{
- return area_net_title (vty, (u_char *)argv[0]);
+ return area_net_title (vty, argv[0]);
}
/*
@@ -1010,7 +1025,7 @@ DEFUN (no_net,
"A Network Entity Title for this process (OSI only)\n"
"XX.XXXX. ... .XXX.XX Network entity title (NET)\n")
{
- return area_clear_net_title (vty, (u_char *)argv[0]);
+ return area_clear_net_title (vty, argv[0]);
}
DEFUN (area_passwd,
@@ -1182,7 +1197,7 @@ DEFUN (is_type,
return CMD_WARNING;
}
- type = string2circuit_t ((u_char *)argv[0]);
+ type = string2circuit_t (argv[0]);
if (!type)
{
vty_out (vty, "Unknown IS level %s", VTY_NEWLINE);
diff --git a/isisd/iso_checksum.c b/isisd/iso_checksum.c
index eabe281f..16f18e50 100644
--- a/isisd/iso_checksum.c
+++ b/isisd/iso_checksum.c
@@ -191,9 +191,3 @@ iso_csum_create (u_char * buffer, int len, u_int16_t n)
/* return the checksum for user usage */
return checksum;
}
-
-int
-iso_csum_modify (u_char * buffer, int len, uint16_t * csum)
-{
- return 0;
-}
diff --git a/isisd/topology/random.c b/isisd/topology/random.c
index 6ee17a0a..c49c0820 100644
--- a/isisd/topology/random.c
+++ b/isisd/topology/random.c
@@ -10,7 +10,17 @@
#include <sys/types.h>
#include <sys/times.h>
-unsigned long timer()
+/*
+ * Prototypes.
+ */
+unsigned long timer(void);
+void init_rand(long);
+double rand01(void);
+double randg01(void);
+long nrand(long);
+void free_arc(void *);
+
+unsigned long timer ()
{ struct tms hold;
times(&hold);
diff --git a/isisd/topology/spgrid.c b/isisd/topology/spgrid.c
index a1aa6d77..611b6727 100644
--- a/isisd/topology/spgrid.c
+++ b/isisd/topology/spgrid.c
@@ -26,6 +26,15 @@
#define NODE( x, y ) (x*Y + y + 1)
+/*
+ * Prototypes.
+ */
+void free_arc(void *);
+void help(struct vty *);
+void print_arc(struct vty *, struct list *, long, long, long);
+void hhelp(struct vty *);
+void usage(struct vty *);
+
const char *graph_type[] = {
"double cycle",
"cycle",
diff --git a/lib/ChangeLog b/lib/ChangeLog
index e2c25ca6..896e1b37 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,23 @@
+2006-10-14 Paul Jakma <paul.jakma@sun.com>
+
+ * if.c: (general) Handle upgrades from SUNWzebra, which tried
+ to track each logical interface as a seperate struct
+ interface, to Quagga, which assigns only one struct interface
+ per ifindex.
+ (if_sunwzebra_get) Try decompose a logical interface name
+ (fooX:Y) to the 'primary' name (fooX), for Solaris.
+ (interface_cmd) Use if_sunwzebra_get on Solaris.
+
+2006-09-26 Pierre-Yves Ritschard <pierre-yves@spootnik.org>
+
+ * smux.c: (smux_open,smux_trap,smux_register) Fix various
+ asn_build_* calls to pass the proper length in the final
+ argument: use sizeof(<variable>) instead of sizeof(<type>),
+ since there were several inconsistencies between the actual
+ variable type and the size that was passed. This should
+ fix some problems on 64-bit architectures where sizeof(int)
+ != sizeof(long).
+
2006-08-25 Paul Jakma <paul.jakma@sun.com>
* thread.c: (general) Add support for monotonic clock, it may still
diff --git a/lib/if.c b/lib/if.c
index c43d9564..4493cc74 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -501,9 +501,49 @@ DEFUN (no_interface_desc,
return CMD_SUCCESS;
}
+
+#ifdef SUNOS_5
+/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
+ * a seperate struct interface for each logical interface, so config
+ * file may be full of 'interface fooX:Y'. Solaris however does not
+ * expose logical interfaces via PF_ROUTE, so trying to track logical
+ * interfaces can be fruitless, for that reason Quagga only tracks
+ * the primary IP interface.
+ *
+ * We try accomodate SUNWzebra by:
+ * - looking up the interface name, to see whether it exists, if so
+ * its useable
+ * - for protocol daemons, this could only because zebra told us of
+ * the interface
+ * - for zebra, only because it learnt from kernel
+ * - if not:
+ * - search the name to see if it contains a sub-ipif / logical interface
+ * seperator, the ':' char. If it does:
+ * - text up to that char must be the primary name - get that name.
+ * if not:
+ * - no idea, just get the name in its entirety.
+ */
+static struct interface *
+if_sunwzebra_get (const char *name, size_t nlen)
+{
+ struct interface *ifp;
+ size_t seppos = 0;
-
-/* See also wrapper function zebra_interface() in zebra/interface.c */
+ if ( (ifp = if_lookup_by_name_len(name, nlen)) != NULL)
+ return ifp;
+
+ /* hunt the primary interface name... */
+ while (seppos < nlen && name[seppos] != ':')
+ seppos++;
+
+ /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
+ if (seppos < nlen)
+ return if_get_by_name_len (name, seppos);
+ else
+ return if_get_by_name_len (name, nlen);
+}
+#endif /* SUNOS_5 */
+
DEFUN (interface,
interface_cmd,
"interface IFNAME",
@@ -521,7 +561,11 @@ DEFUN (interface,
return CMD_WARNING;
}
+#ifdef SUNOS_5
+ ifp = if_sunwzebra_get (argv[0], sl);
+#else
ifp = if_get_by_name_len(argv[0], sl);
+#endif /* SUNOS_5 */
vty->index = ifp;
vty->node = INTERFACE_NODE;
diff --git a/lib/smux.c b/lib/smux.c
index c9b7a880..1bec1209 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -963,7 +963,7 @@ smux_open (int sock)
version = 0;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
- &version, sizeof (u_long));
+ &version, sizeof (version));
/* SMUX connection oid. */
ptr = asn_build_objid (ptr, &len,
@@ -1026,25 +1026,25 @@ smux_trap (oid *name, size_t namelen,
ptr = asn_build_string (ptr, &len,
(u_char)
(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_IPADDRESS),
- (u_char *)&addr, sizeof (struct in_addr));
+ (u_char *)&addr, sizeof (addr));
/* Generic trap integer. */
val = SNMP_TRAP_ENTERPRISESPECIFIC;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
- &val, sizeof (int));
+ &val, sizeof (val));
/* Specific trap integer. */
val = sptrap;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
- &val, sizeof (int));
+ &val, sizeof (val));
/* Timeticks timestamp. */
val = 0;
ptr = asn_build_unsigned_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS),
- &val, sizeof (int));
+ &val, sizeof (val));
/* Variables. */
h1 = ptr;
@@ -1148,13 +1148,13 @@ smux_register (int sock)
priority = -1;
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
- &priority, sizeof (u_long));
+ &priority, sizeof (priority));
/* Operation. */
operation = 2; /* Register R/W */
ptr = asn_build_int (ptr, &len,
(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
- &operation, sizeof (u_long));
+ &operation, sizeof (operation));
if (debug_smux)
{
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index c40b46ed..8380bc89 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -77,6 +77,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 }
};
@@ -114,6 +115,7 @@ Daemon which manages OSPF version 3.\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 zebra@zebra.org\n", progname);
@@ -184,6 +186,7 @@ main (int argc, char *argv[], char *envp[])
int vty_port = 0;
char *config_file = NULL;
struct thread thread;
+ int dryrun = 0;
/* Set umask before anything for security */
umask (0027);
@@ -194,7 +197,7 @@ main (int argc, char *argv[], char *envp[])
/* Command line argument treatment. */
while (1)
{
- opt = getopt_long (argc, argv, "df:i:hp:A:P:u:g:v", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:hp:A:P:u:g:vC", longopts, 0);
if (opt == EOF)
break;
@@ -236,6 +239,9 @@ main (int argc, char *argv[], char *envp[])
print_version (progname);
exit (0);
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'h':
usage (progname, 0);
break;
@@ -271,6 +277,10 @@ main (int argc, char *argv[], char *envp[])
/* parse config file */
vty_read_config (config_file, config_default);
+ /* Start execution only if not in dry-run mode */
+ if (dryrun)
+ return(0);
+
if (daemon_mode)
daemon (0, 0);
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index 0015ee6d..0a2b9994 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,80 @@
+2006-12-04 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * ospfd.c: (ospf_network_run) Remove an offending 'break' statement.
+ Previously, after creating a single ospf_interface on a given
+ network interface, the code would skip to the next interface
+ without considering other connected addresses on the interface.
+ After removing the 'break', we now consider all connected addresses.
+
+2006-11-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * ospf_zebra.c: (ospf_router_id_update_zebra,
+ ospf_interface_address_add, ospf_interface_address_delete)
+ If (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) is enabled, then
+ add a debug message about what Zebra is telling us.
+ (ospf_zebra_add_discard) Add a debug message matching the one
+ already in ospf_zebra_delete_discard.
+
+2006-11-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * ospf_vty.c: (ospf_passive_interface_default) Take additional
+ 'newval' arg so we can update ospf->passive_interface_default inside
+ this function. More importantly, we now call ospf_if_set_multicast
+ on all ospf_interfaces.
+ (ospf_passive_interface, no_ospf_passive_interface) Fix bug:
+ for 'default' case, argv[0] is undefined, so we must test for
+ (argc == 0) before using argv[0]. And since
+ ospf_passive_interface_default now calls ospf_if_set_multicast as
+ needed, we can just return after calling
+ ospf_passive_interface_default.
+
+2006-10-24 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * ospf_zebra.c: (ospf_redistribute_default_set) Fix bug where
+ a new value for ospf->default_originate was being ignored
+ if a previous 'default-information originate' command
+ had already been processed.
+
+2006-10-22 Yar Tikhiy <yar@comp.chem.msu.su>
+
+ * (general) Add support for passive-interface default (with
+ minor edits by Paul Jakma).
+ * ospf_interface.h: Add OSPF_IF_PASSIVE_STATUS macro, looking
+ at configured value, or the global 'default' value, as
+ required.
+ * ospf_interface.c: (ospf_if_new_hook) Leave passive
+ unconfigured per default, allowing global 'default' to
+ take effect for unconfigured interfaces.
+ * ospf_packet.c: (various) use OSPF_IF_PASSIVE_STATUS
+ * ospf_vty.c: (ospf_passive_interface_default) new function,
+ unset passive from all interfaces if default is enabled, as
+ the per-iface settings become redundant.
+ (ospf_passive_interface_update) new func, update passive
+ setting taking global default into account.
+ ({no,}ospf_passive_interface_addr_cmd) Add support for
+ 'default' variant of command.
+ (show_ip_ospf_interface_sub) Update to take global
+ default into account when printing passive status.
+ (ospf_config_write) ditto.
+ * ospfd.c: (ospf_new) set global passive-interface default.
+ * ospfd.h: (struct ospf) Add field for global
+ passive-interface.
+
+2006-09-25 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+ * ospf_packet.c: (ospf_packet_dup, ospf_make_md5_digest)
+ Fix zlog_warn messages to eliminate compiler warnings.
+ (ospf_hello) Improve warning messages to show why we
+ are complaining.
+
+2006-08-28 Andy Gay <andy@andynet.net>
+
+ * ospf_packet.c: (ospf_make_db_desc) Assert added with More-bit
+ fixes does not hold up with addition of Ogier DB-Exchange
+ optimisation, which can empty the db-summary list in between
+ sent DD packets. Remove assert, update More-bit always when
+ in Exchange.
+
2006-08-27 J.J. Krabbendam <jkrabbendam@aimsys.nl>
* ospfd.c: (ospf_finish_final) default redistribute should be
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 31275f89..b6e34746 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -682,9 +682,6 @@ ospf_if_new_hook (struct interface *ifp)
IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
- SET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface);
- IF_DEF_PARAMS (ifp)->passive_interface = OSPF_IF_ACTIVE;
-
SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 5a825ea5..79b178d8 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -50,6 +50,13 @@ struct ospf_if_params
DECLARE_IF_PARAM (u_char, type); /* type of interface */
#define OSPF_IF_ACTIVE 0
#define OSPF_IF_PASSIVE 1
+
+#define OSPF_IF_PASSIVE_STATUS(O) \
+ (OSPF_IF_PARAM_CONFIGURED((O)->params, passive_interface) ? \
+ (O)->params->passive_interface : \
+ (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp), passive_interface) ? \
+ IF_DEF_PARAMS((O)->ifp)->passive_interface : \
+ (O)->ospf->passive_interface_default))
DECLARE_IF_PARAM (u_int32_t, v_hello); /* Hello Interval */
DECLARE_IF_PARAM (u_int32_t, v_wait); /* Router Dead Interval */
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index c105f192..27a12dd0 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -81,6 +81,7 @@ struct option longopts[] =
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
{ "log_mode", no_argument, NULL, 'l'},
+ { "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
@@ -122,6 +123,7 @@ Daemon which manages OSPF.\n\n\
-g, --group Group to run as\n\
-a. --apiserver Enable OSPF apiserver\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);
@@ -182,6 +184,7 @@ main (int argc, char **argv)
char *config_file = NULL;
char *progname;
struct thread thread;
+ int dryrun = 0;
/* Set umask before anything for security */
umask (0027);
@@ -212,7 +215,7 @@ main (int argc, char **argv)
{
int opt;
- opt = getopt_long (argc, argv, "dlf:i:hA:P:u:g:av", longopts, 0);
+ opt = getopt_long (argc, argv, "dlf:i:hA:P:u:g:avC", longopts, 0);
if (opt == EOF)
break;
@@ -259,6 +262,9 @@ main (int argc, char **argv)
print_version (progname);
exit (0);
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'h':
usage (progname, 0);
break;
@@ -303,6 +309,10 @@ main (int argc, char **argv)
/* Get configuration file. */
vty_read_config (config_file, config_default);
+ /* Start execution only if not in dry-run mode */
+ if (dryrun)
+ return(0);
+
/* Change to the daemon program. */
if (daemon_mode)
daemon (0, 0);
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index d7a35645..2addc497 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -216,8 +216,9 @@ ospf_packet_dup (struct ospf_packet *op)
struct ospf_packet *new;
if (stream_get_endp(op->s) != op->length)
- zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
- STREAM_SIZE(op->s), op->length);
+ /* XXX size_t */
+ zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch",
+ (u_long)STREAM_SIZE(op->s), op->length);
/* Reserve space for MD5 authentication that may be added later. */
new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
@@ -371,7 +372,9 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
if (stream_get_endp(op->s) != op->length)
- zlog_warn("ospf_make_md5_digest: length mismatch stream %ld ospf_packet %d", stream_get_endp(op->s), op->length);
+ /* XXX size_t */
+ zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
+ (u_long)stream_get_endp(op->s), op->length);
return OSPF_AUTH_MD5_SIZE;
}
@@ -759,7 +762,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
}
/* If incoming interface is passive one, ignore Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) {
char buf[3][INET_ADDRSTRLEN];
zlog_debug ("ignoring HELLO from router %s sent to %s, "
"received on a passive interface, %s",
@@ -796,8 +799,10 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
/* Compare Router Dead Interval. */
if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
{
- zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch "
+ "(expected %u, but received %u).",
+ inet_ntoa(ospfh->router_id),
+ OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
return;
}
@@ -806,8 +811,10 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
{
if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
{
- zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch "
+ "(expected %u, but received %u).",
+ inet_ntoa(ospfh->router_id),
+ OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval));
return;
}
}
@@ -2712,25 +2719,9 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
/* Set DD Sequence Number. */
stream_putl (s, nbr->dd_seqnum);
+ /* shortcut unneeded walk of (empty) summary LSDBs */
if (ospf_db_summary_isempty (nbr))
- {
- /* Sanity check:
- *
- * Must be here either:
- * - Initial DBD (ospf_nsm.c)
- * - M must be set
- * or
- * - finishing Exchange, and DB-Summary list empty
- * - from ospf_db_desc_proc()
- * - M must not be set
- */
- if (nbr->state >= NSM_Exchange)
- assert (!IS_SET_DD_M(nbr->dd_flags));
- else
- assert (IS_SET_DD_M(nbr->dd_flags));
-
- return length;
- }
+ goto empty;
/* Describe LSA Header from Database Summary List. */
lsdb = &nbr->db_sum;
@@ -2785,9 +2776,17 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
/* Update 'More' bit */
if (ospf_db_summary_isempty (nbr))
{
- UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
- /* Rewrite DD flags */
- stream_putc_at (s, pp, nbr->dd_flags);
+empty:
+ if (nbr->state >= NSM_Exchange)
+ {
+ UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
+ /* Rewrite DD flags */
+ stream_putc_at (s, pp, nbr->dd_flags);
+ }
+ else
+ {
+ assert (IS_SET_DD_M(nbr->dd_flags));
+ }
}
return length;
}
@@ -2979,7 +2978,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
assert(oi);
/* If this is passive interface, do not send OSPF Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
if (oi->type != OSPF_IFTYPE_NBMA)
@@ -3047,7 +3046,7 @@ ospf_hello_send (struct ospf_interface *oi)
u_int16_t length = OSPF_HEADER_SIZE;
/* If this is passive interface, do not send OSPF Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
op = ospf_packet_new (oi->ifp->mtu);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 04e1df46..d6da11dc 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -249,19 +249,82 @@ ALIAS (no_ospf_router_id,
NO_STR
"router-id for the OSPF process\n")
+static void
+ospf_passive_interface_default (struct ospf *ospf, u_char newval)
+{
+ struct listnode *ln;
+ struct interface *ifp;
+ struct ospf_interface *oi;
+
+ ospf->passive_interface_default = newval;
+
+ for (ALL_LIST_ELEMENTS_RO (om->iflist, ln, ifp))
+ {
+ if (ifp &&
+ OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface))
+ UNSET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface);
+ }
+ for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, ln, oi))
+ {
+ if (OSPF_IF_PARAM_CONFIGURED (oi->params, passive_interface))
+ UNSET_IF_PARAM (oi->params, passive_interface);
+ /* update multicast memberships */
+ ospf_if_set_multicast(oi);
+ }
+}
+
+static void
+ospf_passive_interface_update (struct ospf *ospf, struct interface *ifp,
+ struct in_addr addr,
+ struct ospf_if_params *params, u_char value)
+{
+ u_char dflt;
+
+ params->passive_interface = value;
+ if (params != IF_DEF_PARAMS (ifp))
+ {
+ if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface))
+ dflt = IF_DEF_PARAMS (ifp)->passive_interface;
+ else
+ dflt = ospf->passive_interface_default;
+
+ if (value != dflt)
+ SET_IF_PARAM (params, passive_interface);
+ else
+ UNSET_IF_PARAM (params, passive_interface);
+
+ ospf_free_if_params (ifp, addr);
+ ospf_if_update_params (ifp, addr);
+ }
+ else
+ {
+ if (value != ospf->passive_interface_default)
+ SET_IF_PARAM (params, passive_interface);
+ else
+ UNSET_IF_PARAM (params, passive_interface);
+ }
+}
+
DEFUN (ospf_passive_interface,
ospf_passive_interface_addr_cmd,
"passive-interface IFNAME A.B.C.D",
"Suppress routing updates on an interface\n"
"Interface's name\n")
{
- struct interface *ifp;
- struct in_addr addr;
- int ret;
- struct ospf_if_params *params;
- struct route_node *rn;
+ struct interface *ifp;
+ struct in_addr addr;
+ int ret;
+ struct ospf_if_params *params;
+ struct route_node *rn;
+ struct ospf *ospf = vty->index;
+
+ if (argc == 0)
+ {
+ ospf_passive_interface_default (ospf, OSPF_IF_PASSIVE);
+ return CMD_SUCCESS;
+ }
- ifp = if_get_by_name (argv[0]);
+ ifp = if_get_by_name (argv[0]);
params = IF_DEF_PARAMS (ifp);
@@ -278,9 +341,7 @@ DEFUN (ospf_passive_interface,
params = ospf_get_if_params (ifp, addr);
ospf_if_update_params (ifp, addr);
}
-
- SET_IF_PARAM (params, passive_interface);
- params->passive_interface = OSPF_IF_PASSIVE;
+ ospf_passive_interface_update (ospf, ifp, addr, params, OSPF_IF_PASSIVE);
/* XXX We should call ospf_if_set_multicast on exactly those
* interfaces for which the passive property changed. It is too much
@@ -289,12 +350,13 @@ DEFUN (ospf_passive_interface,
* record of joined groups to avoid systems calls if the desired
* memberships match the current memership.
*/
+
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next (rn))
{
struct ospf_interface *oi = rn->info;
if (oi && (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_PASSIVE))
- ospf_if_set_multicast(oi);
+ ospf_if_set_multicast(oi);
}
/*
* XXX It is not clear what state transitions the interface needs to
@@ -312,6 +374,12 @@ ALIAS (ospf_passive_interface,
"Suppress routing updates on an interface\n"
"Interface's name\n")
+ALIAS (ospf_passive_interface,
+ ospf_passive_interface_default_cmd,
+ "passive-interface default",
+ "Suppress routing updates on an interface\n"
+ "Suppress routing updates on interfaces by default\n")
+
DEFUN (no_ospf_passive_interface,
no_ospf_passive_interface_addr_cmd,
"no passive-interface IFNAME A.B.C.D",
@@ -324,6 +392,13 @@ DEFUN (no_ospf_passive_interface,
struct ospf_if_params *params;
int ret;
struct route_node *rn;
+ struct ospf *ospf = vty->index;
+
+ if (argc == 0)
+ {
+ ospf_passive_interface_default (ospf, OSPF_IF_ACTIVE);
+ return CMD_SUCCESS;
+ }
ifp = if_get_by_name (argv[0]);
@@ -343,15 +418,7 @@ DEFUN (no_ospf_passive_interface,
if (params == NULL)
return CMD_SUCCESS;
}
-
- UNSET_IF_PARAM (params, passive_interface);
- params->passive_interface = OSPF_IF_ACTIVE;
-
- if (params != IF_DEF_PARAMS (ifp))
- {
- ospf_free_if_params (ifp, addr);
- ospf_if_update_params (ifp, addr);
- }
+ ospf_passive_interface_update (ospf, ifp, addr, params, OSPF_IF_ACTIVE);
/* XXX We should call ospf_if_set_multicast on exactly those
* interfaces for which the passive property changed. It is too much
@@ -378,6 +445,13 @@ ALIAS (no_ospf_passive_interface,
"Allow routing updates on an interface\n"
"Interface's name\n")
+ALIAS (no_ospf_passive_interface,
+ no_ospf_passive_interface_default_cmd,
+ "no passive-interface default",
+ NO_STR
+ "Allow routing updates on an interface\n"
+ "Allow routing updates on interfaces by default\n")
+
DEFUN (ospf_network_area,
ospf_network_area_cmd,
"network A.B.C.D/M area (A.B.C.D|<0-4294967295>)",
@@ -2791,7 +2865,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
struct in_addr *dest;
const char *dstr;
- if ((ifp->flags & IFF_POINTOPOINT)
+ if ((ifp->flags & IFF_POINTOPOINT)
|| oi->type == OSPF_IFTYPE_VIRTUALLINK)
dstr = "Peer";
else
@@ -2883,14 +2957,14 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
OSPF_IF_PARAM (oi, retransmit_interval),
VTY_NEWLINE);
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_ACTIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_ACTIVE)
{
char timebuf[OSPF_TIME_DUMP_SIZE];
vty_out (vty, " Hello due in %s%s",
ospf_timer_dump (oi->t_hello, timebuf, sizeof(timebuf)),
VTY_NEWLINE);
}
- else /* OSPF_IF_PASSIVE is set */
+ else /* passive-interface is set */
vty_out (vty, " No Hellos (Passive interface)%s", VTY_NEWLINE);
vty_out (vty, " Neighbor Count is %d, Adjacent neighbor count is %d%s",
@@ -7868,17 +7942,36 @@ ospf_config_write (struct vty *vty)
config_write_ospf_redistribute (vty, ospf);
/* passive-interface print. */
+ if (ospf->passive_interface_default == OSPF_IF_PASSIVE)
+ vty_out (vty, " passive-interface default%s", VTY_NEWLINE);
+
for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
- if (IF_DEF_PARAMS (ifp)->passive_interface == OSPF_IF_PASSIVE)
- vty_out (vty, " passive-interface %s%s",
- ifp->name, VTY_NEWLINE);
-
+ if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface)
+ && IF_DEF_PARAMS (ifp)->passive_interface !=
+ ospf->passive_interface_default)
+ {
+ vty_out (vty, " %spassive-interface %s%s",
+ IF_DEF_PARAMS (ifp)->passive_interface ? "" : "no ",
+ ifp->name, VTY_NEWLINE);
+ }
for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
- if (OSPF_IF_PARAM_CONFIGURED (oi->params, passive_interface) &&
- oi->params->passive_interface == OSPF_IF_PASSIVE)
- vty_out (vty, " passive-interface %s %s%s",
+ {
+ if (!OSPF_IF_PARAM_CONFIGURED (oi->params, passive_interface))
+ continue;
+ if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (oi->ifp),
+ passive_interface))
+ {
+ if (oi->params->passive_interface == IF_DEF_PARAMS (oi->ifp)->passive_interface)
+ continue;
+ }
+ else if (oi->params->passive_interface == ospf->passive_interface_default)
+ continue;
+
+ vty_out (vty, " %spassive-interface %s %s%s",
+ oi->params->passive_interface ? "" : "no ",
oi->ifp->name,
inet_ntoa (oi->address->u.prefix4), VTY_NEWLINE);
+ }
/* Network area print. */
config_write_network_area (vty, ospf);
@@ -8199,8 +8292,10 @@ ospf_vty_init (void)
/* "passive-interface" commands. */
install_element (OSPF_NODE, &ospf_passive_interface_addr_cmd);
install_element (OSPF_NODE, &ospf_passive_interface_cmd);
+ install_element (OSPF_NODE, &ospf_passive_interface_default_cmd);
install_element (OSPF_NODE, &no_ospf_passive_interface_addr_cmd);
install_element (OSPF_NODE, &no_ospf_passive_interface_cmd);
+ install_element (OSPF_NODE, &no_ospf_passive_interface_default_cmd);
/* "ospf abr-type" commands. */
install_element (OSPF_NODE, &ospf_abr_type_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 5a722e05..bdd01424 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -65,6 +65,13 @@ ospf_router_id_update_zebra (int command, struct zclient *zclient,
struct prefix router_id;
zebra_router_id_update_read(zclient->ibuf,&router_id);
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ {
+ 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;
ospf = ospf_lookup ();
@@ -256,6 +263,13 @@ ospf_interface_address_add (int command, struct zclient *zclient,
if (c == NULL)
return 0;
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ {
+ char buf[128];
+ prefix2str(c->address, buf, sizeof(buf));
+ zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
+ }
+
ospf = ospf_lookup ();
if (ospf != NULL)
ospf_if_update (ospf);
@@ -283,6 +297,13 @@ ospf_interface_address_delete (int command, struct zclient *zclient,
if (c == NULL)
return 0;
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ {
+ char buf[128];
+ prefix2str(c->address, buf, sizeof(buf));
+ zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
+ }
+
ifp = c->ifp;
p = *c->address;
p.prefixlen = IPV4_MAX_PREFIXLEN;
@@ -470,6 +491,10 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p)
api.ifindex_num = 0;
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
+
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+ zlog_debug ("Zebra: Route add discard %s/%d",
+ inet_ntoa (p->prefix), p->prefixlen);
}
}
@@ -576,21 +601,15 @@ int
ospf_redistribute_default_set (struct ospf *ospf, int originate,
int mtype, int mvalue)
{
- int force = 0;
+ ospf->default_originate = originate;
+ ospf->dmetric[DEFAULT_ROUTE].type = mtype;
+ ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
if (ospf_is_type_redistributed (DEFAULT_ROUTE))
{
- if (mtype != ospf->dmetric[DEFAULT_ROUTE].type)
- {
- ospf->dmetric[DEFAULT_ROUTE].type = mtype;
- force = 1;
- }
- if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value)
- {
- force = 1;
- ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
- }
-
+ /* if ospf->default_originate changes value, is calling
+ ospf_external_lsa_refresh_default sufficient to implement
+ the change? */
ospf_external_lsa_refresh_default (ospf);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
@@ -601,10 +620,6 @@ ospf_redistribute_default_set (struct ospf *ospf, int originate,
return CMD_SUCCESS;
}
- ospf->default_originate = originate;
- ospf->dmetric[DEFAULT_ROUTE].type = mtype;
- ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
-
zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 8c151d98..dd5af5e9 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -167,6 +167,8 @@ ospf_new (void)
new->default_originate = DEFAULT_ORIGINATE_NONE;
+ new->passive_interface_default = OSPF_IF_ACTIVE;
+
new->new_external_route = route_table_init ();
new->old_external_route = route_table_init ();
new->external_lsas = route_table_init ();
@@ -894,8 +896,6 @@ ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
if ((ospf->router_id.s_addr != 0)
&& if_is_operative (ifp))
ospf_if_up (oi);
-
- break;
}
}
}
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index c15b4d39..ec9d9d6b 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -216,6 +216,7 @@ struct ospf
struct ospf_area *backbone; /* Pointer to the Backbone Area. */
struct list *oiflist; /* ospf interfaces */
+ u_char passive_interface_default; /* passive-interface default */
/* LSDB of AS-external-LSAs. */
struct ospf_lsdb *lsdb;
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index 50f8dfd7..68813f14 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,11 @@
+2006-09-11 Paul Jakma <paul.jakma@sun.com>
+
+ * ripd.c: (rip_read) remove gratuitous use of mid-function
+ declaration of vrecv, bug #278.
+ * rip_routemap.c: (route_set_metric) underflow check needs to
+ use signed, problem identified and diagnosed by Pavel
+ Nikiforov in bug #293.
+
2006-06-29 Paul Jakma <paul.jakma@sun.com>
* rip_zebra: (general) convert redistribute commands to use
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index c9d564b7..dfcd6c26 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -42,6 +42,7 @@ static struct option longopts[] =
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
{ "help", no_argument, NULL, 'h'},
+ { "dryrun", no_argument, NULL, 'C'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
@@ -110,6 +111,7 @@ Daemon which manages RIP version 1 and 2.\n\n\
-i, --pid_file Set process identifier file name\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
+-C, --dryrun Check configuration for validity and exit\n\
-r, --retain When program terminates, retain added route by ripd.\n\
-u, --user User to run as\n\
-g, --group Group to run as\n\
@@ -185,6 +187,7 @@ main (int argc, char **argv)
{
char *p;
int daemon_mode = 0;
+ int dryrun = 0;
char *progname;
struct thread thread;
@@ -203,7 +206,7 @@ main (int argc, char **argv)
{
int opt;
- opt = getopt_long (argc, argv, "df:i:hA:P:u:g:rv", longopts, 0);
+ opt = getopt_long (argc, argv, "df:i:hA:P:u:g:rvC", longopts, 0);
if (opt == EOF)
break;
@@ -238,6 +241,9 @@ main (int argc, char **argv)
case 'r':
retain_mode = 1;
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'u':
ripd_privs.user = optarg;
break;
@@ -280,6 +286,10 @@ main (int argc, char **argv)
/* Get configuration file. */
vty_read_config (config_file, config_default);
+ /* Start execution only if not in dry-run mode */
+ if(dryrun)
+ return (0);
+
/* Change to the daemon program. */
if (daemon_mode)
daemon (0, 0);
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index 9d6fd16e..cb87ea55 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -530,7 +530,7 @@ route_set_metric (void *rule, struct prefix *prefix,
else if (mod->type == metric_absolute)
rinfo->metric_out = mod->metric;
- if (rinfo->metric_out < 1)
+ if ((signed int)rinfo->metric_out < 1)
rinfo->metric_out = 1;
if (rinfo->metric_out > RIP_METRIC_INFINITY)
rinfo->metric_out = RIP_METRIC_INFINITY;
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 518e4861..a1630f6c 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1818,6 +1818,7 @@ rip_read (struct thread *t)
struct rip_packet *packet;
struct sockaddr_in from;
int len;
+ int vrecv;
socklen_t fromlen;
struct interface *ifp;
struct connected *ifc;
@@ -1937,8 +1938,8 @@ rip_read (struct thread *t)
}
/* RIP Version check. RFC2453, 4.6 and 5.1 */
- int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
- rip->version_recv : ri->ri_receive);
+ vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
+ rip->version_recv : ri->ri_receive);
if ((packet->version == RIPv1) && !(vrecv & RIPv1))
{
if (IS_RIP_DEBUG_PACKET)
diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c
index e6276c1b..70553910 100644
--- a/ripngd/ripng_main.c
+++ b/ripngd/ripng_main.c
@@ -48,6 +48,7 @@ struct option longopts[] =
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
{ "log_mode", no_argument, NULL, 'l'},
+ { "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
@@ -119,6 +120,7 @@ Daemon which manages RIPng.\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);
@@ -190,6 +192,7 @@ main (int argc, char **argv)
int daemon_mode = 0;
char *progname;
struct thread thread;
+ int dryrun = 0;
/* Set umask before anything for security */
umask (0027);
@@ -204,7 +207,7 @@ main (int argc, char **argv)
{
int opt;
- opt = getopt_long (argc, argv, "dlf:i:hA:P:u:g:v", longopts, 0);
+ opt = getopt_long (argc, argv, "dlf:i:hA:P:u:g:vC", longopts, 0);
if (opt == EOF)
break;
@@ -252,6 +255,9 @@ main (int argc, char **argv)
print_version (progname);
exit (0);
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'h':
usage (progname, 0);
break;
@@ -281,6 +287,10 @@ main (int argc, char **argv)
/* Get configuration file. */
vty_read_config (config_file, config_default);
+ /* Start execution only if not in dry-run mode */
+ if(dryrun)
+ return(0);
+
/* Change to the daemon program. */
if (daemon_mode)
daemon (0, 0);
diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index 134bcf73..51f376c7 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -138,6 +138,7 @@ usage (int status)
"-c, --command Execute argument as command\n" \
"-d, --daemon Connect only to the specified daemon\n" \
"-E, --echo Echo prompt and command in -c mode\n" \
+ "-C, --dryrun Check configuration for validity and exit\n" \
"-h, --help Display this help and exit\n\n" \
"Note that multiple commands may be executed from the command\n" \
"line by passing multiple -c args, or by embedding linefeed\n" \
@@ -156,6 +157,7 @@ struct option longopts[] =
{ "command", required_argument, NULL, 'c'},
{ "daemon", required_argument, NULL, 'd'},
{ "echo", no_argument, NULL, 'E'},
+ { "dryrun", no_argument, NULL, 'C'},
{ "help", no_argument, NULL, 'h'},
{ 0 }
};
@@ -195,6 +197,7 @@ main (int argc, char **argv, char **env)
{
char *p;
int opt;
+ int dryrun = 0;
int boot_flag = 0;
const char *daemon_name = NULL;
struct cmd_rec {
@@ -210,7 +213,7 @@ main (int argc, char **argv, char **env)
/* Option handling. */
while (1)
{
- opt = getopt_long (argc, argv, "be:c:d:Eh", longopts, 0);
+ opt = getopt_long (argc, argv, "be:c:d:EhC", longopts, 0);
if (opt == EOF)
break;
@@ -242,6 +245,9 @@ main (int argc, char **argv, char **env)
case 'E':
echo_command = 1;
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'h':
usage (0);
break;
@@ -270,6 +276,10 @@ main (int argc, char **argv, char **env)
/* Read vtysh configuration file before connecting to daemons. */
vtysh_read_config (config_default);
+ /* Start execution only if not in dry-run mode */
+ if(dryrun)
+ return(0);
+
/* Make sure we pass authentication before proceeding. */
vtysh_auth ();
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 9a26750f..55b11223 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,14 @@
+2006-12-08 Piotr Chytla <pch@packetconsulting.pl>
+
+ * zebra_rib.c: (static_install_ipv{4,6}) Case where existing
+ RIB is updated must explicitely rib_addqueue the route_node,
+ to ensure the update actually takes effect.
+
+2006-09-13 Tom Everett <tom@khubla.com>
+
+ * kernel_socket.c (rtm_type_str): ifdef RTM_OLD{ADD,DEL} to
+ compile on systems that no longer define them.
+
2006-08-06 Paul Jakma <paul.jakma@sun.com>
* interface.h: (ifstat_update_proc) declaration should match
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index bd4d9c4b..f384e979 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -136,8 +136,12 @@ struct message rtm_type_str[] =
{RTM_REDIRECT, "RTM_REDIRECT"},
{RTM_MISS, "RTM_MISS"},
{RTM_LOCK, "RTM_LOCK"},
+#ifdef OLDADD
{RTM_OLDADD, "RTM_OLDADD"},
+#endif /* RTM_OLDADD */
+#ifdef RTM_OLDDEL
{RTM_OLDDEL, "RTM_OLDDEL"},
+#endif /* RTM_OLDDEL */
{RTM_RESOLVE, "RTM_RESOLVE"},
{RTM_NEWADDR, "RTM_NEWADDR"},
{RTM_DELADDR, "RTM_DELADDR"},
diff --git a/zebra/main.c b/zebra/main.c
index dbe1b537..ed45bd13 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -76,6 +76,7 @@ struct option longopts[] =
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
{ "retain", no_argument, NULL, 'r'},
+ { "dryrun", no_argument, NULL, 'C'},
#ifdef HAVE_NETLINK
{ "nl-bufsize", required_argument, NULL, 's'},
#endif /* HAVE_NETLINK */
@@ -131,6 +132,7 @@ usage (char *progname, int status)
"-k, --keep_kernel Don't delete old routes which installed by "\
"zebra.\n"\
"-l, --log_mode Set verbose log mode flag\n"\
+ "-C, --dryrun Check configuration for validity and exit\n"\
"-A, --vty_addr Set vty's bind address\n"\
"-P, --vty_port Set vty's port number\n"\
"-r, --retain When program terminates, retain added route "\
@@ -208,6 +210,7 @@ main (int argc, char **argv)
char *p;
char *vty_addr = NULL;
int vty_port = ZEBRA_VTY_PORT;
+ int dryrun = 0;
int batch_mode = 0;
int daemon_mode = 0;
char *config_file = NULL;
@@ -228,9 +231,9 @@ main (int argc, char **argv)
int opt;
#ifdef HAVE_NETLINK
- opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vs:", longopts, 0);
+ opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vs:C", longopts, 0);
#else
- opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:v", longopts, 0);
+ opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vC", longopts, 0);
#endif /* HAVE_NETLINK */
if (opt == EOF)
@@ -248,6 +251,9 @@ main (int argc, char **argv)
case 'k':
keep_kernel_mode = 1;
break;
+ case 'C':
+ dryrun = 1;
+ break;
case 'l':
/* log_mode = 1; */
break;
@@ -345,6 +351,10 @@ main (int argc, char **argv)
/* Configuration file read*/
vty_read_config (config_file, config_default);
+ /* Don't start execution if we are in dry-run mode */
+ if (dryrun)
+ return(0);
+
/* Clean up rib. */
rib_weed_tables ();
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8d4e732c..64d23199 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1103,20 +1103,20 @@ rib_queue_init (struct zebra_t *zebra)
* The queue length is bounded by the maximal size of the routing table,
* as a route_node will not be requeued, if already queued.
*
- * RIBs are submitted via rib_addnode and rib_delnode, which set
- * minimal state and then submit route_node to queue for best-path
- * selection later. Order of add/delete state changes are preserved for
- * any given RIB.
+ * RIBs are submitted via rib_addnode or rib_delnode which set minimal
+ * state, or static_install_ipv{4,6} (when an existing RIB is updated)
+ * and then submit route_node to queue for best-path selection later.
+ * Order of add/delete state changes are preserved for any given RIB.
*
* Deleted RIBs are reaped during best-path selection.
*
* rib_addnode
* |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
- * |-> rib_addqueue | best RIB, if required
- * | |
- * |-> .......................... -> rib_process
- * | |
- * |-> rib_addqueue |-> rib_unlink
+ * |-------->| | best RIB, if required
+ * | |
+ * static_install->|->rib_addqueue...... -> rib_process
+ * | |
+ * |-------->| |-> rib_unlink
* |-> set RIB_ENTRY_REMOVE |
* rib_delnode (RIB freed)
*
@@ -1557,6 +1557,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
nexthop_blackhole_add (rib);
break;
}
+ rib_queue_add (&zebrad, rn);
}
else
{
@@ -1721,7 +1722,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
}
}
- /* Distance chaged. */
+ /* Distance changed. */
if (update)
static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
@@ -2118,6 +2119,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
break;
}
+ rib_queue_add (&zebrad, rn);
}
else
{