From a38401b6af746794db0b4bdbd3954289b8d00aef Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Apr 2015 10:21:34 +0200 Subject: [PATCH 1/8] lib: hide internal prefix list structures These are about to be touched and there's no point in other code touching into prefix list's internas. Add some isolation. Signed-off-by: David Lamparter --- bgpd/bgpd.c | 4 ++-- lib/Makefile.am | 3 +++ lib/plist.c | 25 ++++++------------------- lib/plist.h | 26 ++------------------------ ospfd/ospf_zebra.c | 4 ++-- 5 files changed, 15 insertions(+), 47 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 2d831acdd2..8ff16e07ac 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -13,7 +13,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License +You should have received a copy of the GN5U General Public License along with GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -5144,7 +5144,7 @@ peer_prefix_list_update (struct prefix_list *plist) * Update the prefix-list on update groups. */ update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST, - plist ? plist->name : NULL, 0, 0); + plist ? prefix_list_name(plist) : NULL, 0, 0); for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { diff --git a/lib/Makefile.am b/lib/Makefile.am index 49a721f7f9..43fa906128 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -32,6 +32,9 @@ pkginclude_HEADERS = \ workqueue.h route_types.h libospf.h nexthop.h json.h \ ptm_lib.h csv.h bfd.h vrf.h +noinst_HEADERS = \ + plist_int.h + EXTRA_DIST = \ regex.c regex-gnu.h \ queue.h \ diff --git a/lib/plist.c b/lib/plist.c index 2418c8621d..0174a53fec 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -32,25 +32,7 @@ #include "log.h" #include "routemap.h" -/* Each prefix-list's entry. */ -struct prefix_list_entry -{ - int seq; - - int le; - int ge; - - enum prefix_list_type type; - - int any; - struct prefix prefix; - - unsigned long refcnt; - unsigned long hitcnt; - - struct prefix_list_entry *next; - struct prefix_list_entry *prev; -}; +#include "plist_int.h" /* List of struct prefix_list. */ struct prefix_list_list @@ -127,6 +109,11 @@ prefix_master_get (afi_t afi) return NULL; } +const char *prefix_list_name (struct prefix_list *plist) +{ + return plist->name; +} + /* Lookup prefix_list from list of prefix_list by name. */ struct prefix_list * prefix_list_lookup (afi_t afi, const char *name) diff --git a/lib/plist.h b/lib/plist.h index 4359a8935c..cfc43c781c 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -31,30 +31,7 @@ enum prefix_list_type PREFIX_PERMIT, }; -enum prefix_name_type -{ - PREFIX_TYPE_STRING, - PREFIX_TYPE_NUMBER -}; - -struct prefix_list -{ - char *name; - char *desc; - - struct prefix_master *master; - - enum prefix_name_type type; - - int count; - int rangecount; - - struct prefix_list_entry *head; - struct prefix_list_entry *tail; - - struct prefix_list *next; - struct prefix_list *prev; -}; +struct prefix_list; struct orf_prefix { @@ -70,6 +47,7 @@ extern void prefix_list_reset (void); extern void prefix_list_add_hook (void (*func) (struct prefix_list *)); extern void prefix_list_delete_hook (void (*func) (struct prefix_list *)); +extern const char *prefix_list_name (struct prefix_list *); extern struct prefix_list *prefix_list_lookup (afi_t, const char *); extern enum prefix_list_type prefix_list_apply (struct prefix_list *, void *); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index a95b2e1b67..8119dde5e8 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1379,7 +1379,7 @@ ospf_prefix_list_update (struct prefix_list *plist) { /* Update filter-list in. */ if (PREFIX_NAME_IN (area)) - if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0) + if (strcmp (PREFIX_NAME_IN (area), prefix_list_name (plist)) == 0) { PREFIX_LIST_IN (area) = prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area)); @@ -1388,7 +1388,7 @@ ospf_prefix_list_update (struct prefix_list *plist) /* Update filter-list out. */ if (PREFIX_NAME_OUT (area)) - if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0) + if (strcmp (PREFIX_NAME_OUT (area), prefix_list_name (plist)) == 0) { PREFIX_LIST_IN (area) = prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area)); From c7da3d50b38b430494465c1ba0d68244bfd16d56 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Apr 2015 10:21:35 +0200 Subject: [PATCH 2/8] lib: straighten out ORF prefix list support BGP ORF prefix lists are in a separate namespace; this was previously hooked up with a special-purpose AFI value. This is a little kludgy for extension, hence this splits it off. Signed-off-by: David Lamparter --- bgpd/bgp_fsm.c | 2 +- bgpd/bgp_packet.c | 6 +- bgpd/bgpd.c | 2 +- lib/plist.c | 149 ++++++++++++++++------------------------------ lib/plist.h | 5 +- 5 files changed, 58 insertions(+), 106 deletions(-) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 9bfb730469..02dddadf99 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1104,7 +1104,7 @@ bgp_stop (struct peer *peer) if ((peer->status == OpenConfirm) || (peer->status == Established)) { /* ORF received prefix-filter pnt */ sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all (orf_name); + prefix_bgp_orf_remove_all (afi, orf_name); } } diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index d378be639f..efac3bbbbe 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1892,7 +1892,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host); - prefix_bgp_orf_remove_all (name); + prefix_bgp_orf_remove_all (afi, name); break; } ok = ((u_int32_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ; @@ -1952,12 +1952,12 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) { zlog_info ("%s Received misformatted prefixlist ORF." " Remove All pfxlist", peer->host); - prefix_bgp_orf_remove_all (name); + prefix_bgp_orf_remove_all (afi, name); break; } } peer->orf_plist[afi][safi] = - prefix_list_lookup (AFI_ORF_PREFIX, name); + prefix_list_lookup (afi, name); } stream_forward_getp (s, orf_len); } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 8ff16e07ac..5a950ee91e 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -807,7 +807,7 @@ peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi) /* Clear ORF info */ peer->orf_plist[afi][safi] = NULL; sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all (orf_name); + prefix_bgp_orf_remove_all (afi, orf_name); /* Set default neighbor send-community. */ if (! bgp_option_check (BGP_OPT_CONFIG_CISCO)) diff --git a/lib/plist.c b/lib/plist.c index 0174a53fec..7a356dffbd 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -86,7 +86,17 @@ static struct prefix_master prefix_master_ipv6 = #endif /* HAVE_IPV6*/ /* Static structure of BGP ORF prefix_list's master. */ -static struct prefix_master prefix_master_orf = +static struct prefix_master prefix_master_orf_v4 = +{ + {NULL, NULL}, + {NULL, NULL}, + 1, + NULL, + NULL, +}; + +/* Static structure of BGP ORF prefix_list's master. */ +static struct prefix_master prefix_master_orf_v6 = { {NULL, NULL}, {NULL, NULL}, @@ -96,16 +106,12 @@ static struct prefix_master prefix_master_orf = }; static struct prefix_master * -prefix_master_get (afi_t afi) +prefix_master_get (afi_t afi, int orf) { if (afi == AFI_IP) - return &prefix_master_ipv4; -#ifdef HAVE_IPV6 - else if (afi == AFI_IP6) - return &prefix_master_ipv6; -#endif /* HAVE_IPV6 */ - else if (afi == AFI_ORF_PREFIX) - return &prefix_master_orf; + return orf ? &prefix_master_orf_v4 : &prefix_master_ipv4; + if (afi == AFI_IP6) + return orf ? &prefix_master_orf_v6 : &prefix_master_ipv6; return NULL; } @@ -115,8 +121,8 @@ const char *prefix_list_name (struct prefix_list *plist) } /* Lookup prefix_list from list of prefix_list by name. */ -struct prefix_list * -prefix_list_lookup (afi_t afi, const char *name) +static struct prefix_list * +prefix_list_lookup_do (afi_t afi, int orf, const char *name) { struct prefix_list *plist; struct prefix_master *master; @@ -124,7 +130,7 @@ prefix_list_lookup (afi_t afi, const char *name) if (name == NULL) return NULL; - master = prefix_master_get (afi); + master = prefix_master_get (afi, orf); if (master == NULL) return NULL; @@ -139,6 +145,18 @@ prefix_list_lookup (afi_t afi, const char *name) return NULL; } +struct prefix_list * +prefix_list_lookup (afi_t afi, const char *name) +{ + return prefix_list_lookup_do (afi, 0, name); +} + +struct prefix_list * +prefix_bgp_orf_lookup (afi_t afi, const char *name) +{ + return prefix_list_lookup_do (afi, 1, name); +} + static struct prefix_list * prefix_list_new (void) { @@ -172,7 +190,7 @@ prefix_list_entry_free (struct prefix_list_entry *pentry) /* Insert new prefix list to list of prefix_list. Each prefix_list is sorted by the name. */ static struct prefix_list * -prefix_list_insert (afi_t afi, const char *name) +prefix_list_insert (afi_t afi, int orf, const char *name) { unsigned int i; long number; @@ -181,7 +199,7 @@ prefix_list_insert (afi_t afi, const char *name) struct prefix_list_list *list; struct prefix_master *master; - master = prefix_master_get (afi); + master = prefix_master_get (afi, orf); if (master == NULL) return NULL; @@ -262,14 +280,14 @@ prefix_list_insert (afi_t afi, const char *name) } static struct prefix_list * -prefix_list_get (afi_t afi, const char *name) +prefix_list_get (afi_t afi, int orf, const char *name) { struct prefix_list *plist; - plist = prefix_list_lookup (afi, name); + plist = prefix_list_lookup_do (afi, orf, name); if (plist == NULL) - plist = prefix_list_insert (afi, name); + plist = prefix_list_insert (afi, orf, name); return plist; } @@ -740,7 +758,7 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, lenum = 0; /* Get prefix_list with name. */ - plist = prefix_list_get (afi, name); + plist = prefix_list_get (afi, 0, name); /* Make prefix entry. */ pentry = prefix_list_entry_make (&p, type, seqnum, lenum, genum, any); @@ -995,7 +1013,7 @@ vty_show_prefix_list (struct vty *vty, afi_t afi, const char *name, struct prefix_master *master; int seqnum = 0; - master = prefix_master_get (afi); + master = prefix_master_get (afi, 0); if (master == NULL) return CMD_WARNING; @@ -1113,7 +1131,7 @@ vty_clear_prefix_list (struct vty *vty, afi_t afi, const char *name, int ret; struct prefix p; - master = prefix_master_get (afi); + master = prefix_master_get (afi, 0); if (master == NULL) return CMD_WARNING; @@ -1568,7 +1586,7 @@ DEFUN (ip_prefix_list_description, { struct prefix_list *plist; - plist = prefix_list_get (AFI_IP, argv[0]); + plist = prefix_list_get (AFI_IP, 0, argv[0]); if (plist->desc) { @@ -2164,7 +2182,7 @@ DEFUN (ipv6_prefix_list_description, { struct prefix_list *plist; - plist = prefix_list_get (AFI_IP6, argv[0]); + plist = prefix_list_get (AFI_IP6, 0, argv[0]); if (plist->desc) { @@ -2359,7 +2377,7 @@ config_write_prefix_afi (afi_t afi, struct vty *vty) struct prefix_master *master; int write = 0; - master = prefix_master_get (afi); + master = prefix_master_get (afi, 0); if (master == NULL) return 0; @@ -2502,7 +2520,7 @@ prefix_bgp_orf_set (char *name, afi_t afi, struct orf_prefix *orfp, if (orfp->ge && orfp->le == (afi == AFI_IP ? 32 : 128)) orfp->le = 0; - plist = prefix_list_get (AFI_ORF_PREFIX, name); + plist = prefix_list_get (afi, 1, name); if (! plist) return CMD_WARNING; @@ -2536,11 +2554,11 @@ prefix_bgp_orf_set (char *name, afi_t afi, struct orf_prefix *orfp, } void -prefix_bgp_orf_remove_all (char *name) +prefix_bgp_orf_remove_all (afi_t afi, char *name) { struct prefix_list *plist; - plist = prefix_list_lookup (AFI_ORF_PREFIX, name); + plist = prefix_bgp_orf_lookup (afi, name); if (plist) prefix_list_delete (plist); } @@ -2555,7 +2573,7 @@ prefix_bgp_show_prefix_list (struct vty *vty, afi_t afi, char *name, u_char use_ json_object *json_prefix = NULL; json_object *json_list = NULL; - plist = prefix_list_lookup (AFI_ORF_PREFIX, name); + plist = prefix_bgp_orf_lookup (afi, name); if (! plist) return 0; @@ -2626,13 +2644,13 @@ prefix_bgp_show_prefix_list (struct vty *vty, afi_t afi, char *name, u_char use_ } static void -prefix_list_reset_orf (void) +prefix_list_reset_afi (afi_t afi, int orf) { struct prefix_list *plist; struct prefix_list *next; struct prefix_master *master; - master = prefix_master_get (AFI_ORF_PREFIX); + master = prefix_master_get (afi, orf); if (master == NULL) return; @@ -2672,38 +2690,6 @@ config_write_prefix_ipv4 (struct vty *vty) return config_write_prefix_afi (AFI_IP, vty); } -static void -prefix_list_reset_ipv4 (void) -{ - struct prefix_list *plist; - struct prefix_list *next; - struct prefix_master *master; - - master = prefix_master_get (AFI_IP); - if (master == NULL) - return; - - for (plist = master->num.head; plist; plist = next) - { - next = plist->next; - prefix_list_delete (plist); - } - for (plist = master->str.head; plist; plist = next) - { - next = plist->next; - prefix_list_delete (plist); - } - - assert (master->num.head == NULL); - assert (master->num.tail == NULL); - - assert (master->str.head == NULL); - assert (master->str.tail == NULL); - - master->seqnum = 1; - master->recent = NULL; -} - static void prefix_list_init_ipv4 (void) { @@ -2781,38 +2767,6 @@ config_write_prefix_ipv6 (struct vty *vty) return config_write_prefix_afi (AFI_IP6, vty); } -static void -prefix_list_reset_ipv6 (void) -{ - struct prefix_list *plist; - struct prefix_list *next; - struct prefix_master *master; - - master = prefix_master_get (AFI_IP6); - if (master == NULL) - return; - - for (plist = master->num.head; plist; plist = next) - { - next = plist->next; - prefix_list_delete (plist); - } - for (plist = master->str.head; plist; plist = next) - { - next = plist->next; - prefix_list_delete (plist); - } - - assert (master->num.head == NULL); - assert (master->num.tail == NULL); - - assert (master->str.head == NULL); - assert (master->str.tail == NULL); - - master->seqnum = 1; - master->recent = NULL; -} - static void prefix_list_init_ipv6 (void) { @@ -2888,9 +2842,8 @@ prefix_list_init () void prefix_list_reset () { - prefix_list_reset_ipv4 (); -#ifdef HAVE_IPV6 - prefix_list_reset_ipv6 (); -#endif /* HAVE_IPV6 */ - prefix_list_reset_orf (); + prefix_list_reset_afi (AFI_IP, 0); + prefix_list_reset_afi (AFI_IP6, 0); + prefix_list_reset_afi (AFI_IP, 1); + prefix_list_reset_afi (AFI_IP6, 1); } diff --git a/lib/plist.h b/lib/plist.h index cfc43c781c..2c6f13a5c4 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -23,8 +23,6 @@ #ifndef _QUAGGA_PLIST_H #define _QUAGGA_PLIST_H -#define AFI_ORF_PREFIX 65535 - enum prefix_list_type { PREFIX_DENY, @@ -51,11 +49,12 @@ extern const char *prefix_list_name (struct prefix_list *); extern struct prefix_list *prefix_list_lookup (afi_t, const char *); extern enum prefix_list_type prefix_list_apply (struct prefix_list *, void *); +extern struct prefix_list *prefix_bgp_orf_lookup (afi_t, const char *); extern struct stream * prefix_bgp_orf_entry (struct stream *, struct prefix_list *, u_char, u_char, u_char); extern int prefix_bgp_orf_set (char *, afi_t, struct orf_prefix *, int, int); -extern void prefix_bgp_orf_remove_all (char *); +extern void prefix_bgp_orf_remove_all (afi_t, char *); extern int prefix_bgp_show_prefix_list (struct vty *, afi_t, char *, u_char); #endif /* _QUAGGA_PLIST_H */ From 7e111b6b0de44a9d351cdfeda4c674224a65ec3b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Apr 2015 10:21:36 +0200 Subject: [PATCH 3/8] lib: use trie structure for prefix list matching Prefix lists were implemented with a simple linear list that is scanned sequentially. This is, of course, extremely inefficient as it scales by O(n). This patch adds a trie-ish data structure that allows quickly descending based on the prefix. Note that the trie structure used here is designed for real-world use, hence it uses a relatively crude fixed-size bytewise table instead of some fancy balancing scheme. It is quite cacheline efficient. Using real-world routeserver prefix lists, matching against a fulltable dump: entries before after factor 9103 63.8s .0124s 5142x 772 4.52s .0101s 445.3x 86 .445s .0098s 45.51x 7 .0379s .0099s 3.834x 2 .0136s .0095s 1.440x 1 .0084s .0095s .879x This buys CPU with memory. Memory usage on an IXP setup with 100k prefix list entries is an additional 4 MB on top of the 9.5 MB that it was before. --- lib/memtypes.c | 1 + lib/plist.c | 220 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 206 insertions(+), 15 deletions(-) diff --git a/lib/memtypes.c b/lib/memtypes.c index 828820f309..c63178b6dd 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -50,6 +50,7 @@ struct memory_list memory_list_lib[] = { MTYPE_PREFIX_LIST, "Prefix List" }, { MTYPE_PREFIX_LIST_ENTRY, "Prefix List Entry" }, { MTYPE_PREFIX_LIST_STR, "Prefix List Str" }, + { MTYPE_PREFIX_LIST_TRIE, "Prefix List Trie Table" }, { MTYPE_ROUTE_MAP, "Route map" }, { MTYPE_ROUTE_MAP_NAME, "Route map name" }, { MTYPE_ROUTE_MAP_INDEX, "Route map index" }, diff --git a/lib/plist.c b/lib/plist.c index 7a356dffbd..2fdb0b33e8 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -34,6 +34,26 @@ #include "plist_int.h" +/* not currently changeable, code assumes bytes further down */ +#define PLC_BITS 8 +#define PLC_LEN (1 << PLC_BITS) +#define PLC_MAXLEVELV4 2 /* /24 for IPv4 */ +#define PLC_MAXLEVELV6 4 /* /48 for IPv6 */ +#define PLC_MAXLEVEL 4 /* max(v4,v6) */ + +struct pltrie_entry { + union { + struct pltrie_table *next_table; + struct prefix_list_entry *final_chain; + }; + + struct prefix_list_entry *up_chain; +}; + +struct pltrie_table { + struct pltrie_entry entries[PLC_LEN]; +}; + /* List of struct prefix_list. */ struct prefix_list_list { @@ -61,6 +81,9 @@ struct prefix_master /* Hook function which is executed when prefix_list is deleted. */ void (*delete_hook) (struct prefix_list *); + + /* number of bytes that have a trie level */ + size_t trie_depth; }; /* Static structure of IPv4 prefix_list's master. */ @@ -71,6 +94,8 @@ static struct prefix_master prefix_master_ipv4 = 1, NULL, NULL, + NULL, + PLC_MAXLEVELV4, }; #ifdef HAVE_IPV6 @@ -82,27 +107,33 @@ static struct prefix_master prefix_master_ipv6 = 1, NULL, NULL, + NULL, + PLC_MAXLEVELV6, }; #endif /* HAVE_IPV6*/ /* Static structure of BGP ORF prefix_list's master. */ -static struct prefix_master prefix_master_orf_v4 = -{ +static struct prefix_master prefix_master_orf_v4 = +{ {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, + NULL, + PLC_MAXLEVELV4, }; /* Static structure of BGP ORF prefix_list's master. */ -static struct prefix_master prefix_master_orf_v6 = -{ +static struct prefix_master prefix_master_orf_v6 = +{ {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, + NULL, + PLC_MAXLEVELV6, }; static struct prefix_master * @@ -207,6 +238,7 @@ prefix_list_insert (afi_t afi, int orf, const char *name) plist = prefix_list_new (); plist->name = XSTRDUP (MTYPE_PREFIX_LIST_STR, name); plist->master = master; + plist->trie = XCALLOC (MTYPE_PREFIX_LIST_TRIE, sizeof (struct pltrie_table)); /* If name is made by all digit character. We treat it as number. */ @@ -340,6 +372,8 @@ prefix_list_delete (struct prefix_list *plist) if (plist->name) XFREE (MTYPE_PREFIX_LIST_STR, plist->name); + XFREE (MTYPE_PREFIX_LIST_TRIE, plist->trie); + prefix_list_free (plist); } @@ -440,11 +474,88 @@ prefix_list_entry_lookup (struct prefix_list *plist, struct prefix *prefix, return NULL; } +static void +trie_walk_affected (size_t validbits, struct pltrie_table *table, uint8_t byte, + struct prefix_list_entry *object, + void (*fn)(struct prefix_list_entry *object, + struct prefix_list_entry **updptr)) +{ + uint8_t mask; + uint16_t bwalk; + + if (validbits > PLC_BITS) + { + fn (object, &table->entries[byte].final_chain); + return; + } + + mask = (1 << (8 - validbits)) - 1; + for (bwalk = byte & ~mask; bwalk <= byte + mask; bwalk++) + { + fn (object, &table->entries[bwalk].up_chain); + } +} + +static void trie_uninstall_fn (struct prefix_list_entry *object, + struct prefix_list_entry **updptr) +{ + for (; *updptr; updptr = &(*updptr)->next_best) + if (*updptr == object) + { + *updptr = object->next_best; + break; + } +} + +static int +trie_table_empty (struct pltrie_table *table) +{ + size_t i; + for (i = 0; i < PLC_LEN; i++) + if (table->entries[i].next_table || table->entries[i].final_chain) + return 0; + return 1; +} + +static void +prefix_list_trie_del (struct prefix_list *plist, + struct prefix_list_entry *pentry) +{ + size_t depth, maxdepth = plist->master->trie_depth; + uint8_t *bytes = &pentry->prefix.u.prefix; + size_t validbits = pentry->prefix.prefixlen; + struct pltrie_table *table, **tables[PLC_MAXLEVEL]; + + table = plist->trie; + for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) + { + uint8_t byte = bytes[depth]; + assert (table->entries[byte].next_table); + + tables[depth + 1] = &table->entries[byte].next_table; + table = table->entries[byte].next_table; + + validbits -= PLC_BITS; + } + + trie_walk_affected (validbits, table, bytes[depth], pentry, trie_uninstall_fn); + + for (; depth > 0; depth--) + if (trie_table_empty (*tables[depth])) + { + XFREE (MTYPE_PREFIX_LIST_TRIE, *tables[depth]); + *tables[depth] = NULL; + } +} + + static void prefix_list_entry_delete (struct prefix_list *plist, struct prefix_list_entry *pentry, int update_list) { + prefix_list_trie_del (plist, pentry); + if (plist == NULL || pentry == NULL) return; if (pentry->prev) @@ -473,6 +584,52 @@ prefix_list_entry_delete (struct prefix_list *plist, } } +static void trie_install_fn (struct prefix_list_entry *object, + struct prefix_list_entry **updptr) +{ + while (*updptr) + { + if (*updptr == object) + return; + if ((*updptr)->prefix.prefixlen < object->prefix.prefixlen) + break; + if ((*updptr)->seq > object->seq) + break; + updptr = &(*updptr)->next_best; + } + + if (!object->next_best) + object->next_best = *updptr; + else + assert (object->next_best == *updptr || !*updptr); + + *updptr = object; +} + +static void +prefix_list_trie_add (struct prefix_list *plist, + struct prefix_list_entry *pentry) +{ + size_t depth = plist->master->trie_depth; + uint8_t *bytes = &pentry->prefix.u.prefix; + size_t validbits = pentry->prefix.prefixlen; + struct pltrie_table *table; + + table = plist->trie; + while (validbits > PLC_BITS && depth > 1) + { + if (!table->entries[*bytes].next_table) + table->entries[*bytes].next_table = XCALLOC (MTYPE_PREFIX_LIST_TRIE, + sizeof(struct pltrie_table)); + table = table->entries[*bytes].next_table; + bytes++; + depth--; + validbits -= PLC_BITS; + } + + trie_walk_affected (validbits, table, *bytes, pentry, trie_install_fn); +} + static void prefix_list_entry_add (struct prefix_list *plist, struct prefix_list_entry *pentry) @@ -518,6 +675,8 @@ prefix_list_entry_add (struct prefix_list *plist, plist->tail = pentry; } + prefix_list_trie_add (plist, pentry); + /* Increment count. */ plist->count++; @@ -575,10 +734,13 @@ prefix_list_entry_match (struct prefix_list_entry *pentry, struct prefix *p) enum prefix_list_type prefix_list_apply (struct prefix_list *plist, void *object) { - struct prefix_list_entry *pentry; - struct prefix *p; + struct prefix_list_entry *pentry, *pbest = NULL; - p = (struct prefix *) object; + struct prefix *p = (struct prefix *) object; + uint8_t *byte = &p->u.prefix; + size_t depth = plist->master->trie_depth; + size_t validbits = p->prefixlen; + struct pltrie_table *table; if (plist == NULL) return PREFIX_DENY; @@ -586,17 +748,45 @@ prefix_list_apply (struct prefix_list *plist, void *object) if (plist->count == 0) return PREFIX_PERMIT; - for (pentry = plist->head; pentry; pentry = pentry->next) + table = plist->trie; + while (1) { - pentry->refcnt++; - if (prefix_list_entry_match (pentry, p)) - { - pentry->hitcnt++; - return pentry->type; - } + for (pentry = table->entries[*byte].up_chain; pentry; pentry = pentry->next_best) + { + if (pbest && pbest->seq < pentry->seq) + continue; + if (prefix_list_entry_match (pentry, p)) + pbest = pentry; + } + + if (validbits <= PLC_BITS) + break; + validbits -= PLC_BITS; + + if (--depth) + { + if (!table->entries[*byte].next_table) + break; + + table = table->entries[*byte].next_table; + byte++; + continue; + } + + for (pentry = table->entries[*byte].final_chain; pentry; pentry = pentry->next_best) + { + if (pbest && pbest->seq < pentry->seq) + continue; + if (prefix_list_entry_match (pentry, p)) + pbest = pentry; + } + break; } - return PREFIX_DENY; + if (pbest == NULL) + return PREFIX_DENY; + + return pbest->type; } static void __attribute__ ((unused)) From 20b8a998aa1be595b737c25d3fc0991628bfa3c2 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 13 Apr 2015 10:21:37 +0200 Subject: [PATCH 4/8] lib: optimise prefix list setup - duplicate prefix check can use the trie structure - appending with a seq# beyond the end of the list can shortcut Configuration load is now bottlenecked by cmd_element_match() and strcmp(). For a real-world routeserver prefix list configuration (38668 lines of config for multiple prefix lists): before: 4.73s after: 1.92s x 2.46 Signed-off-by: David Lamparter --- lib/plist.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/lib/plist.c b/lib/plist.c index 2fdb0b33e8..63fd94c422 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -641,15 +641,20 @@ prefix_list_entry_add (struct prefix_list *plist, if (pentry->seq == -1) pentry->seq = prefix_new_seq_get (plist); - /* Is there any same seq prefix list entry? */ - replace = prefix_seq_check (plist, pentry->seq); - if (replace) - prefix_list_entry_delete (plist, replace, 0); + if (plist->tail && pentry->seq > plist->tail->seq) + point = NULL; + else + { + /* Is there any same seq prefix list entry? */ + replace = prefix_seq_check (plist, pentry->seq); + if (replace) + prefix_list_entry_delete (plist, replace, 0); - /* Check insert point. */ - for (point = plist->head; point; point = point->next) - if (point->seq >= pentry->seq) - break; + /* Check insert point. */ + for (point = plist->head; point; point = point->next) + if (point->seq >= pentry->seq) + break; + } /* In case of this is the first element of the list. */ pentry->next = point; @@ -829,6 +834,10 @@ static struct prefix_list_entry * prefix_entry_dup_check (struct prefix_list *plist, struct prefix_list_entry *new) { + size_t depth, maxdepth = plist->master->trie_depth; + uint8_t byte, *bytes = &new->prefix.u.prefix; + size_t validbits = new->prefix.prefixlen; + struct pltrie_table *table; struct prefix_list_entry *pentry; int seq = 0; @@ -837,7 +846,24 @@ prefix_entry_dup_check (struct prefix_list *plist, else seq = new->seq; - for (pentry = plist->head; pentry; pentry = pentry->next) + table = plist->trie; + for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) + { + byte = bytes[depth]; + if (!table->entries[byte].next_table) + return NULL; + + table = table->entries[byte].next_table; + validbits -= PLC_BITS; + } + + byte = bytes[depth]; + if (validbits > PLC_BITS) + pentry = table->entries[byte].final_chain; + else + pentry = table->entries[byte].up_chain; + + for (; pentry; pentry = pentry->next_best) { if (prefix_same (&pentry->prefix, &new->prefix) && pentry->type == new->type From 814e24c45dc70c2fe1cde562b397f81031eea2f7 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 3 Nov 2015 10:00:30 -0800 Subject: [PATCH 5/8] lib: Fix missing plist_int.h Signed-off-by: Donald Sharpd --- lib/plist_int.h | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 lib/plist_int.h diff --git a/lib/plist_int.h b/lib/plist_int.h new file mode 100644 index 0000000000..e6e5901dbf --- /dev/null +++ b/lib/plist_int.h @@ -0,0 +1,78 @@ +/* + * Prefix list internal definitions. + * Copyright (C) 1999 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QUAGGA_PLIST_INT_H +#define _QUAGGA_PLIST_INT_H + +enum prefix_name_type +{ + PREFIX_TYPE_STRING, + PREFIX_TYPE_NUMBER +}; + +struct pltrie_table; + +struct prefix_list +{ + char *name; + char *desc; + + struct prefix_master *master; + + enum prefix_name_type type; + + int count; + int rangecount; + + struct prefix_list_entry *head; + struct prefix_list_entry *tail; + + struct pltrie_table *trie; + + struct prefix_list *next; + struct prefix_list *prev; +}; + +/* Each prefix-list's entry. */ +struct prefix_list_entry +{ + int seq; + + int le; + int ge; + + enum prefix_list_type type; + + int any; + struct prefix prefix; + + unsigned long refcnt; + unsigned long hitcnt; + + struct prefix_list_entry *next; + struct prefix_list_entry *prev; + + /* up the chain for best match search */ + struct prefix_list_entry *next_best; +}; + +#endif /* _QUAGGA_PLIST_INT_H */ From 4dfd8affa204c1188fd74f1581b5c51d2c4463f4 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 3 Nov 2015 10:37:25 -0800 Subject: [PATCH 6/8] Add "no debug ospf" and "no debug ospf6" commands to disable all ospf debugging Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-4010 --- ospf6d/ospf6_lsa.h | 2 ++ ospf6d/ospf6_neighbor.c | 51 +++++++++++++++++++++++++++++++++++ ospfd/ospf_dump.c | 60 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index aa64a772f8..940a0f7057 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -158,6 +158,8 @@ extern struct ospf6_lsa_handler unknown_handler; #define OSPF6_LSA_IS_KNOWN(type) \ (ospf6_get_lsa_handler (type) != &unknown_handler ? 1 : 0) +extern vector ospf6_lsa_handler_vector; + /* Macro for LSA Origination */ /* addr is (struct prefix *) */ #define CONTINUE_IF_ADDRESS_LINKLOCAL(debug,addr) \ diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 6f9c8bb4f8..49b4aceaeb 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -40,6 +40,11 @@ #include "ospf6_flood.h" #include "ospf6d.h" #include "ospf6_bfd.h" +#include "ospf6_abr.h" +#include "ospf6_asbr.h" +#include "ospf6_lsa.h" +#include "ospf6_spf.h" +#include "ospf6_zebra.h" unsigned char conf_debug_ospf6_neighbor = 0; @@ -987,6 +992,50 @@ ALIAS (no_debug_ospf6_neighbor, "Debug OSPFv3 Neighbor Event\n" ) +DEFUN (no_debug_ospf6, + no_debug_ospf6_cmd, + "no debug ospf6", + NO_STR + DEBUG_STR + OSPF6_STR) +{ + u_int i; + struct ospf6_lsa_handler *handler = NULL; + + OSPF6_DEBUG_ABR_OFF (); + OSPF6_DEBUG_ASBR_OFF (); + OSPF6_DEBUG_BROUTER_OFF (); + OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF (); + OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF (); + OSPF6_DEBUG_FLOODING_OFF (); + OSPF6_DEBUG_INTERFACE_OFF (); + + for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) + { + handler = vector_slot (ospf6_lsa_handler_vector, i); + + if (handler != NULL) + { + UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG); + } + } + + for (i = 0; i < 6; i++) + OSPF6_DEBUG_MESSAGE_OFF (i, OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT); + + OSPF6_DEBUG_NEIGHBOR_OFF (OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT); + OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_TABLE); + OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_INTRA); + OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_INTER); + OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_MEMORY); + OSPF6_DEBUG_SPF_OFF (OSPF6_DEBUG_SPF_PROCESS); + OSPF6_DEBUG_SPF_OFF (OSPF6_DEBUG_SPF_TIME); + OSPF6_DEBUG_SPF_OFF (OSPF6_DEBUG_SPF_DATABASE); + OSPF6_DEBUG_ZEBRA_OFF (OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV); + + return CMD_SUCCESS; +} + int config_write_ospf6_debug_neighbor (struct vty *vty) { @@ -1007,10 +1056,12 @@ install_element_ospf6_debug_neighbor (void) install_element (ENABLE_NODE, &debug_ospf6_neighbor_detail_cmd); install_element (ENABLE_NODE, &no_debug_ospf6_neighbor_cmd); install_element (ENABLE_NODE, &no_debug_ospf6_neighbor_detail_cmd); + install_element (ENABLE_NODE, &no_debug_ospf6_cmd); install_element (CONFIG_NODE, &debug_ospf6_neighbor_cmd); install_element (CONFIG_NODE, &debug_ospf6_neighbor_detail_cmd); install_element (CONFIG_NODE, &no_debug_ospf6_neighbor_cmd); install_element (CONFIG_NODE, &no_debug_ospf6_neighbor_detail_cmd); + install_element (CONFIG_NODE, &no_debug_ospf6_cmd); } diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 9c73e1b2be..4c1f0549eb 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -1922,6 +1922,64 @@ DEFUN (no_debug_ospf_instance_nssa, return CMD_SUCCESS; } +DEFUN (no_debug_ospf, + no_debug_ospf_cmd, + "no debug ospf", + NO_STR + DEBUG_STR + OSPF_STR) +{ + int flag = OSPF_DEBUG_SEND | OSPF_DEBUG_RECV | OSPF_DEBUG_DETAIL; + int i; + + if (vty->node == CONFIG_NODE) + { + CONF_DEBUG_OFF (event, EVENT); + CONF_DEBUG_OFF (nssa, NSSA); + DEBUG_OFF (ism, ISM_EVENTS); + DEBUG_OFF (ism, ISM_STATUS); + DEBUG_OFF (ism, ISM_TIMERS); + DEBUG_OFF (lsa, LSA); + DEBUG_OFF (lsa, LSA_FLOODING); + DEBUG_OFF (lsa, LSA_GENERATE); + DEBUG_OFF (lsa, LSA_INSTALL); + DEBUG_OFF (lsa, LSA_REFRESH); + DEBUG_OFF (nsm, NSM); + DEBUG_OFF (nsm, NSM_EVENTS); + DEBUG_OFF (nsm, NSM_STATUS); + DEBUG_OFF (nsm, NSM_TIMERS); + DEBUG_OFF (zebra, ZEBRA); + DEBUG_OFF (zebra, ZEBRA_INTERFACE); + DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE); + + for (i = 0; i < 5; i++) + DEBUG_PACKET_OFF (i, flag); + } + + for (i = 0; i < 5; i++) + TERM_DEBUG_PACKET_OFF (i, flag); + + TERM_DEBUG_OFF (event, EVENT); + TERM_DEBUG_OFF (ism, ISM); + TERM_DEBUG_OFF (ism, ISM_EVENTS); + TERM_DEBUG_OFF (ism, ISM_STATUS); + TERM_DEBUG_OFF (ism, ISM_TIMERS); + TERM_DEBUG_OFF (lsa, LSA); + TERM_DEBUG_OFF (lsa, LSA_FLOODING); + TERM_DEBUG_OFF (lsa, LSA_GENERATE); + TERM_DEBUG_OFF (lsa, LSA_INSTALL); + TERM_DEBUG_OFF (lsa, LSA_REFRESH); + TERM_DEBUG_OFF (nsm, NSM); + TERM_DEBUG_OFF (nsm, NSM_EVENTS); + TERM_DEBUG_OFF (nsm, NSM_STATUS); + TERM_DEBUG_OFF (nsm, NSM_TIMERS); + TERM_DEBUG_OFF (nssa, NSSA); + TERM_DEBUG_OFF (zebra, ZEBRA); + TERM_DEBUG_OFF (zebra, ZEBRA_INTERFACE); + TERM_DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE); + + return CMD_SUCCESS; +} static int show_debugging_ospf_common (struct vty *vty, struct ospf *ospf) @@ -2254,6 +2312,7 @@ debug_init () install_element (ENABLE_NODE, &no_debug_ospf_instance_zebra_cmd); install_element (ENABLE_NODE, &no_debug_ospf_instance_event_cmd); install_element (ENABLE_NODE, &no_debug_ospf_instance_nssa_cmd); + install_element (ENABLE_NODE, &no_debug_ospf_cmd); install_element (CONFIG_NODE, &debug_ospf_packet_send_recv_detail_cmd); install_element (CONFIG_NODE, &debug_ospf_packet_send_recv_cmd); @@ -2308,4 +2367,5 @@ debug_init () install_element (CONFIG_NODE, &no_debug_ospf_instance_zebra_cmd); install_element (CONFIG_NODE, &no_debug_ospf_instance_event_cmd); install_element (CONFIG_NODE, &no_debug_ospf_instance_nssa_cmd); + install_element (CONFIG_NODE, &no_debug_ospf_cmd); } From 692c79543296b7223f43f194b3042957cbc7080f Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 3 Nov 2015 10:48:30 -0800 Subject: [PATCH 7/8] Enable OSPF "log-adjacency-changes" by default Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-7941 --- ospf6d/ospf6_top.c | 21 ++++++++++++++------- ospfd/ospf_vty.c | 10 +++++++--- ospfd/ospfd.c | 2 ++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index c90c0a07d6..350e8ac9fd 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -155,6 +155,9 @@ ospf6_create (void) o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; + /* Enable "log-adjacency-changes" */ + SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); + return o; } @@ -349,13 +352,14 @@ DEFUN (ospf6_log_adjacency_changes, struct ospf6 *ospf6 = vty->index; SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); + UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); return CMD_SUCCESS; } DEFUN (ospf6_log_adjacency_changes_detail, ospf6_log_adjacency_changes_detail_cmd, "log-adjacency-changes detail", - "Log changes in adjacency state\n" + "Log changes in adjacency state\n" "Log all state changes\n") { struct ospf6 *ospf6 = vty->index; @@ -368,7 +372,7 @@ DEFUN (ospf6_log_adjacency_changes_detail, DEFUN (no_ospf6_log_adjacency_changes, no_ospf6_log_adjacency_changes_cmd, "no log-adjacency-changes", - NO_STR + NO_STR "Log changes in adjacency state\n") { struct ospf6 *ospf6 = vty->index; @@ -381,13 +385,14 @@ DEFUN (no_ospf6_log_adjacency_changes, DEFUN (no_ospf6_log_adjacency_changes_detail, no_ospf6_log_adjacency_changes_detail_cmd, "no log-adjacency-changes detail", - NO_STR - "Log changes in adjacency state\n" + NO_STR + "Log changes in adjacency state\n" "Log all state changes\n") { struct ospf6 *ospf6 = vty->index; UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); + UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); return CMD_SUCCESS; } @@ -949,10 +954,12 @@ config_write_ospf6 (struct vty *vty) /* log-adjacency-changes flag print. */ if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) { - vty_out(vty, " log-adjacency-changes"); if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) - vty_out(vty, " detail"); - vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE); + } + else + { + vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE); } if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 12187f3136..3aee037445 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2310,6 +2310,7 @@ DEFUN (ospf_log_adjacency_changes, return CMD_SUCCESS; SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); return CMD_SUCCESS; } @@ -2357,6 +2358,7 @@ DEFUN (no_ospf_log_adjacency_changes_detail, if (!ospf) return CMD_SUCCESS; + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); return CMD_SUCCESS; } @@ -9515,11 +9517,13 @@ ospf_config_write (struct vty *vty) /* log-adjacency-changes flag print. */ if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { - vty_out(vty, " log-adjacency-changes"); if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) - vty_out(vty, " detail"); - vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE); } + else + { + vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE); + } /* RFC1583 compatibility flag print -- Compatible with CISCO 12.1. */ if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 75d823c91a..5957918c9c 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -287,6 +287,8 @@ ospf_new (u_short instance) new->oi_write_q = list_new (); new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; + /* Enable "log-adjacency-changes" */ + SET_FLAG(new->config, OSPF_LOG_ADJACENCY_CHANGES); return new; } From 2385a8767a13c07c51e78dbc00239eade99e0fb6 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Tue, 3 Nov 2015 10:59:57 -0800 Subject: [PATCH 8/8] BGP: vtysh should accept just "router bgp" if the AS is already defined Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-5674 --- bgpd/bgp_vty.c | 67 ++++++++++++++++++++++++++++++++------------- vtysh/extract.pl.in | 1 + vtysh/vtysh.c | 8 ++++++ 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 17b3b2fdbc..3b4ae3db70 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -643,26 +643,48 @@ DEFUN (router_bgp, struct bgp *bgp; const char *name = NULL; - VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX); - - if (argc == 2) - name = argv[1]; - - ret = bgp_get (&bgp, &as, name); - switch (ret) + // "router bgp" without an ASN + if (argc < 1) { - case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET: - vty_out (vty, "Please specify 'bgp multiple-instance' first%s", - VTY_NEWLINE); - return CMD_WARNING; - case BGP_ERR_AS_MISMATCH: - vty_out (vty, "BGP is already running; AS is %u%s", as, VTY_NEWLINE); - return CMD_WARNING; - case BGP_ERR_INSTANCE_MISMATCH: - vty_out (vty, "BGP view name and AS number mismatch%s", VTY_NEWLINE); - vty_out (vty, "BGP instance is already running; AS is %u%s", - as, VTY_NEWLINE); - return CMD_WARNING; + bgp = bgp_get_default(); + + if (bgp == NULL) + { + vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (listcount(bm->bgp) > 1) + { + vty_out (vty, "%% Multiple BGP processes are configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + // "router bgp X" + else + { + VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX); + + if (argc == 2) + name = argv[1]; + + ret = bgp_get (&bgp, &as, name); + switch (ret) + { + case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET: + vty_out (vty, "Please specify 'bgp multiple-instance' first%s", + VTY_NEWLINE); + return CMD_WARNING; + case BGP_ERR_AS_MISMATCH: + vty_out (vty, "BGP is already running; AS is %u%s", as, VTY_NEWLINE); + return CMD_WARNING; + case BGP_ERR_INSTANCE_MISMATCH: + vty_out (vty, "BGP view name and AS number mismatch%s", VTY_NEWLINE); + vty_out (vty, "BGP instance is already running; AS is %u%s", + as, VTY_NEWLINE); + return CMD_WARNING; + } } vty->node = BGP_NODE; @@ -680,6 +702,12 @@ ALIAS (router_bgp, "BGP view\n" "view name\n") +ALIAS (router_bgp, + router_bgp_noasn_cmd, + "router bgp", + ROUTER_STR + BGP_STR) + /* "no router bgp" commands. */ DEFUN (no_router_bgp, no_router_bgp_cmd, @@ -12590,6 +12618,7 @@ bgp_vty_init (void) /* "router bgp" commands. */ install_element (CONFIG_NODE, &router_bgp_cmd); install_element (CONFIG_NODE, &router_bgp_view_cmd); + install_element (CONFIG_NODE, &router_bgp_noasn_cmd); /* "no router bgp" commands. */ install_element (CONFIG_NODE, &no_router_bgp_cmd); diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 56e7115925..da0e4563e1 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -39,6 +39,7 @@ $ignore{'"router ospf"'} = "ignore"; $ignore{'"router ospf <1-65535>"'} = "ignore"; $ignore{'"router ospf6"'} = "ignore"; $ignore{'"router babel"'} = "ignore"; +$ignore{'"router bgp"'} = "ignore"; $ignore{'"router bgp " "<1-4294967295>"'} = "ignore"; $ignore{'"router bgp " "<1-4294967295>" " view WORD"'} = "ignore"; $ignore{'"router isis WORD"'} = "ignore"; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 58014c2e0d..5786c68c9b 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1041,6 +1041,13 @@ DEFUNSH (VTYSH_BGPD, return CMD_SUCCESS; } +ALIAS_SH (VTYSH_BGPD, + router_bgp, + router_bgp_asn_cmd, + "router bgp", + ROUTER_STR + BGP_STR) + ALIAS_SH (VTYSH_BGPD, router_bgp, router_bgp_view_cmd, @@ -2817,6 +2824,7 @@ vtysh_init_vty (void) install_element (CONFIG_NODE, &router_babel_cmd); install_element (CONFIG_NODE, &router_isis_cmd); install_element (CONFIG_NODE, &router_bgp_cmd); + install_element (CONFIG_NODE, &router_bgp_asn_cmd); install_element (CONFIG_NODE, &router_bgp_view_cmd); install_element (BGP_NODE, &address_family_vpnv4_cmd); install_element (BGP_NODE, &address_family_vpnv4_unicast_cmd);