2002-12-13 21:15:29 +01:00
|
|
|
/* BGP nexthop scan
|
|
|
|
Copyright (C) 2000 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. */
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "command.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "zclient.h"
|
|
|
|
#include "stream.h"
|
|
|
|
#include "network.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "memory.h"
|
2012-05-07 18:52:52 +02:00
|
|
|
#include "hash.h"
|
|
|
|
#include "jhash.h"
|
2015-05-20 02:40:34 +02:00
|
|
|
#include "nexthop.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "bgpd/bgpd.h"
|
|
|
|
#include "bgpd/bgp_table.h"
|
|
|
|
#include "bgpd/bgp_route.h"
|
|
|
|
#include "bgpd/bgp_attr.h"
|
|
|
|
#include "bgpd/bgp_nexthop.h"
|
2015-05-20 02:40:34 +02:00
|
|
|
#include "bgpd/bgp_nht.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "bgpd/bgp_debug.h"
|
|
|
|
#include "bgpd/bgp_damp.h"
|
|
|
|
#include "zebra/rib.h"
|
|
|
|
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
extern struct zclient *zclient;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
struct bgp_nexthop_cache *zlookup_query (struct in_addr);
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
|
|
|
|
#endif /* HAVE_IPV6 */
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Only one BGP scan thread are activated at the same time. */
|
2005-05-23 16:19:54 +02:00
|
|
|
static struct thread *bgp_scan_thread = NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* BGP import thread */
|
2005-05-23 16:19:54 +02:00
|
|
|
static struct thread *bgp_import_thread = NULL;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* BGP scan interval. */
|
2005-05-23 16:19:54 +02:00
|
|
|
static int bgp_scan_interval;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* BGP import interval. */
|
2005-05-23 16:19:54 +02:00
|
|
|
static int bgp_import_interval;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Route table for next-hop lookup cache. */
|
2015-05-20 02:40:34 +02:00
|
|
|
struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
|
2005-05-23 16:19:54 +02:00
|
|
|
static struct bgp_table *cache1_table[AFI_MAX];
|
|
|
|
static struct bgp_table *cache2_table[AFI_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Route table for connected route. */
|
2005-05-23 16:19:54 +02:00
|
|
|
static struct bgp_table *bgp_connected_table[AFI_MAX];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* BGP nexthop lookup query client. */
|
[bgpd] Stability fixes including bugs 397, 492
I've spent the last several weeks working on stability fixes to bgpd.
These patches fix all of the numerous crashes, assertion failures, memory
leaks and memory stomping I could find. Valgrind was used extensively.
Added new function bgp_exit() to help catch problems. If "debug bgp" is
configured and bgpd exits with status of 0, statistics on remaining
lib/memory.c allocations are printed to stderr. It is my hope that other
developers will use this to stay on top of memory issues.
Example questionable exit:
bgpd: memstats: Current memory utilization in module LIB:
bgpd: memstats: Link List : 6
bgpd: memstats: Link Node : 5
bgpd: memstats: Hash : 8
bgpd: memstats: Hash Bucket : 2
bgpd: memstats: Hash Index : 8
bgpd: memstats: Work queue : 3
bgpd: memstats: Work queue item : 2
bgpd: memstats: Work queue name string : 3
bgpd: memstats: Current memory utilization in module BGP:
bgpd: memstats: BGP instance : 1
bgpd: memstats: BGP peer : 1
bgpd: memstats: BGP peer hostname : 1
bgpd: memstats: BGP attribute : 1
bgpd: memstats: BGP extra attributes : 1
bgpd: memstats: BGP aspath : 1
bgpd: memstats: BGP aspath str : 1
bgpd: memstats: BGP table : 24
bgpd: memstats: BGP node : 1
bgpd: memstats: BGP route : 1
bgpd: memstats: BGP synchronise : 8
bgpd: memstats: BGP Process queue : 1
bgpd: memstats: BGP node clear queue : 1
bgpd: memstats: NOTE: If configuration exists, utilization may be expected.
Example clean exit:
bgpd: memstats: No remaining tracked memory utilization.
This patch fixes bug #397: "Invalid free in bgp_announce_check()".
This patch fixes bug #492: "SIGBUS in bgpd/bgp_route.c:
bgp_clear_route_node()".
My apologies for not separating out these changes into individual patches.
The complexity of doing so boggled what is left of my brain. I hope this
is all still useful to the community.
This code has been production tested, in non-route-server-client mode, on
a linux 32-bit box and a 64-bit box.
Release/reset functions, used by bgp_exit(), added to:
bgpd/bgp_attr.c,h
bgpd/bgp_community.c,h
bgpd/bgp_dump.c,h
bgpd/bgp_ecommunity.c,h
bgpd/bgp_filter.c,h
bgpd/bgp_nexthop.c,h
bgpd/bgp_route.c,h
lib/routemap.c,h
File by file analysis:
* bgpd/bgp_aspath.c: Prevent re-use of ashash after it is released.
* bgpd/bgp_attr.c: #if removed uncalled cluster_dup().
* bgpd/bgp_clist.c,h: Allow community_list_terminate() to be called from
bgp_exit().
* bgpd/bgp_filter.c: Fix aslist->name use without allocation check, and
also fix memory leak.
* bgpd/bgp_main.c: Created bgp_exit() exit routine. This function frees
allocations made as part of bgpd initialization and, to some extent,
configuration. If "debug bgp" is configured, memory stats are printed
as described above.
* bgpd/bgp_nexthop.c: zclient_new() already allocates stream for
ibuf/obuf, so bgp_scan_init() shouldn't do it too. Also, made it so
zlookup is global so bgp_exit() can use it.
* bgpd/bgp_packet.c: bgp_capability_msg_parse() call to bgp_clear_route()
adjusted to use new BGP_CLEAR_ROUTE_NORMAL flag.
* bgpd/bgp_route.h: Correct reference counter "lock" to be signed.
bgp_clear_route() now accepts a bgp_clear_route_type of either
BGP_CLEAR_ROUTE_NORMAL or BGP_CLEAR_ROUTE_MY_RSCLIENT.
* bgpd/bgp_route.c:
- bgp_process_rsclient(): attr was being zero'ed and then
bgp_attr_extra_free() was being called with it, even though it was
never filled with valid data.
- bgp_process_rsclient(): Make sure rsclient->group is not NULL before
use.
- bgp_processq_del(): Add call to bgp_table_unlock().
- bgp_process(): Add call to bgp_table_lock().
- bgp_update_rsclient(): memset clearing of new_attr not needed since
declarationw with "= { 0 }" does it. memset was already commented
out.
- bgp_update_rsclient(): Fix screwed up misleading indentation.
- bgp_withdraw_rsclient(): Fix screwed up misleading indentation.
- bgp_clear_route_node(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_node_queue_del(): Add call to bgp_table_unlock() and also
free struct bgp_clear_node_queue used for work item.
- bgp_clear_node_complete(): Do peer_unlock() after BGP_EVENT_ADD() in
case peer is released by peer_unlock() call.
- bgp_clear_route_table(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT. Use
struct bgp_clear_node_queue to supply data to worker. Add call to
bgp_table_lock().
- bgp_clear_route(): Add support for BGP_CLEAR_ROUTE_NORMAL or
BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_route_all(): Use BGP_CLEAR_ROUTE_NORMAL.
Bug 397 fixes:
- bgp_default_originate()
- bgp_announce_table()
* bgpd/bgp_table.h:
- struct bgp_table: Added reference count. Changed type of owner to be
"struct peer *" rather than "void *".
- struct bgp_node: Correct reference counter "lock" to be signed.
* bgpd/bgp_table.c:
- Added bgp_table reference counting.
- bgp_table_free(): Fixed cleanup code. Call peer_unlock() on owner if
set.
- bgp_unlock_node(): Added assertion.
- bgp_node_get(): Added call to bgp_lock_node() to code path that it was
missing from.
* bgpd/bgp_vty.c:
- peer_rsclient_set_vty(): Call peer_lock() as part of peer assignment
to owner. Handle failure gracefully.
- peer_rsclient_unset_vty(): Add call to bgp_clear_route() with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
* bgpd/bgp_zebra.c: Made it so zclient is global so bgp_exit() can use it.
* bgpd/bgpd.c:
- peer_lock(): Allow to be called when status is "Deleted".
- peer_deactivate(): Supply BGP_CLEAR_ROUTE_NORMAL purpose to
bgp_clear_route() call.
- peer_delete(): Common variable listnode pn. Fix bug in which rsclient
was only dealt with if not part of a peer group. Call
bgp_clear_route() for rsclient, if appropriate, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- peer_group_get(): Use XSTRDUP() instead of strdup() for conf->host.
- peer_group_bind(): Call bgp_clear_route() for rsclient, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- bgp_create(): Use XSTRDUP() instead of strdup() for peer_self->host.
- bgp_delete(): Delete peers before groups, rather than after. And then
rather than deleting rsclients, verify that there are none at this
point.
- bgp_unlock(): Add assertion.
- bgp_free(): Call bgp_table_finish() rather than doing XFREE() itself.
* lib/command.c,h: Compiler warning fixes. Add cmd_terminate(). Fixed
massive leak in install_element() in which cmd_make_descvec() was being
called more than once for the same cmd->strvec/string/doc.
* lib/log.c: Make closezlog() check fp before calling fclose().
* lib/memory.c: Catch when alloc count goes negative by using signed
counts. Correct #endif comment. Add log_memstats_stderr().
* lib/memory.h: Add log_memstats_stderr().
* lib/thread.c: thread->funcname was being accessed in thread_call() after
it had been freed. Rearranged things so that thread_call() frees
funcname. Also made it so thread_master_free() cleans up cpu_record.
* lib/vty.c,h: Use global command_cr. Add vty_terminate().
* lib/zclient.c,h: Re-enable zclient_free().
2009-07-18 07:44:03 +02:00
|
|
|
struct zclient *zlookup = NULL;
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
char *
|
|
|
|
bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
|
|
|
|
{
|
|
|
|
prefix2str(&(bnc->node->p), buf, size);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Add nexthop to the end of the list. */
|
2005-06-28 14:44:16 +02:00
|
|
|
static void
|
2002-12-13 21:15:29 +01:00
|
|
|
bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
|
|
|
|
{
|
|
|
|
struct nexthop *last;
|
|
|
|
|
|
|
|
for (last = bnc->nexthop; last && last->next; last = last->next)
|
|
|
|
;
|
|
|
|
if (last)
|
|
|
|
last->next = nexthop;
|
|
|
|
else
|
|
|
|
bnc->nexthop = nexthop;
|
|
|
|
nexthop->prev = last;
|
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
void
|
2002-12-13 21:15:29 +01:00
|
|
|
bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
|
|
|
|
{
|
|
|
|
struct nexthop *nexthop;
|
|
|
|
struct nexthop *next = NULL;
|
|
|
|
|
|
|
|
for (nexthop = bnc->nexthop; nexthop; nexthop = next)
|
|
|
|
{
|
|
|
|
next = nexthop->next;
|
|
|
|
XFREE (MTYPE_NEXTHOP, nexthop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
struct bgp_nexthop_cache *
|
|
|
|
bnc_new ()
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2015-05-20 02:40:34 +02:00
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
|
|
|
|
bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
|
|
|
|
LIST_INIT(&(bnc->paths));
|
|
|
|
return bnc;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
void
|
2002-12-13 21:15:29 +01:00
|
|
|
bnc_free (struct bgp_nexthop_cache *bnc)
|
|
|
|
{
|
|
|
|
bnc_nexthop_free (bnc);
|
|
|
|
XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2005-06-28 14:44:16 +02:00
|
|
|
static int
|
2011-08-05 16:52:52 +02:00
|
|
|
bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
|
2002-12-13 21:15:29 +01:00
|
|
|
struct bgp_nexthop_cache *bnc2)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct nexthop *next1, *next2;
|
|
|
|
|
|
|
|
if (bnc1->nexthop_num != bnc2->nexthop_num)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
next1 = bnc1->nexthop;
|
|
|
|
next2 = bnc2->nexthop;
|
|
|
|
|
|
|
|
for (i = 0; i < bnc1->nexthop_num; i++)
|
|
|
|
{
|
2015-05-20 02:40:34 +02:00
|
|
|
if (! nexthop_same_no_recurse (next1, next2))
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
next1 = next1->next;
|
|
|
|
next2 = next2->next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If nexthop exists on connected network return 1. */
|
|
|
|
int
|
2011-08-05 16:52:52 +02:00
|
|
|
bgp_nexthop_onlink (afi_t afi, struct attr *attr)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
2012-01-09 12:36:23 +01:00
|
|
|
|
|
|
|
/* If zebra is not enabled return */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
return 1;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Lookup the address is onlink or not. */
|
|
|
|
if (afi == AFI_IP)
|
|
|
|
{
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn)
|
|
|
|
{
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
else if (afi == AFI_IP6)
|
|
|
|
{
|
2007-05-04 22:15:47 +02:00
|
|
|
if (attr->extra->mp_nexthop_len == 32)
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
2007-05-04 22:15:47 +02:00
|
|
|
else if (attr->extra->mp_nexthop_len == 16)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2007-05-04 22:15:47 +02:00
|
|
|
if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
|
2007-05-04 22:15:47 +02:00
|
|
|
&attr->extra->mp_nexthop_global);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn)
|
|
|
|
{
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
/* Check specified next-hop is reachable or not. */
|
2005-06-28 14:44:16 +02:00
|
|
|
static int
|
2002-12-13 21:15:29 +01:00
|
|
|
bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
|
|
|
|
int *metricchanged)
|
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
|
|
|
struct prefix p;
|
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
struct attr *attr;
|
2012-01-09 12:36:23 +01:00
|
|
|
|
|
|
|
/* If lookup is not enabled, return valid. */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
{
|
|
|
|
if (ri->extra)
|
|
|
|
ri->extra->igpmetric = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Only check IPv6 global address only nexthop. */
|
|
|
|
attr = ri->attr;
|
|
|
|
|
2007-05-04 22:15:47 +02:00
|
|
|
if (attr->extra->mp_nexthop_len != 16
|
|
|
|
|| IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
|
2002-12-13 21:15:29 +01:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
memset (&p, 0, sizeof (struct prefix));
|
|
|
|
p.family = AF_INET6;
|
|
|
|
p.prefixlen = IPV6_MAX_BITLEN;
|
2007-05-04 22:15:47 +02:00
|
|
|
p.u.prefix6 = attr->extra->mp_nexthop_global;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* IBGP or ebgp-multihop */
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
bnc = rn->info;
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-08-08 17:36:44 +02:00
|
|
|
if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
|
|
|
|
bnc = bnc_new ();
|
|
|
|
else
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
if (changed)
|
|
|
|
{
|
2011-08-05 16:52:52 +02:00
|
|
|
struct bgp_table *old;
|
|
|
|
struct bgp_node *oldrn;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
|
|
|
|
old = cache2_table[AFI_IP6];
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2004-11-09 02:54:03 +01:00
|
|
|
old = cache1_table[AFI_IP6];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
oldrn = bgp_node_lookup (old, &p);
|
|
|
|
if (oldrn)
|
|
|
|
{
|
2011-08-05 16:52:52 +02:00
|
|
|
struct bgp_nexthop_cache *oldbnc = oldrn->info;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2011-08-05 16:52:52 +02:00
|
|
|
bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (bnc->metric != oldbnc->metric)
|
|
|
|
bnc->metricchanged = 1;
|
2010-07-27 18:28:55 +02:00
|
|
|
|
|
|
|
bgp_unlock_node (oldrn);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rn->info = bnc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed)
|
|
|
|
*changed = bnc->changed;
|
|
|
|
|
|
|
|
if (metricchanged)
|
|
|
|
*metricchanged = bnc->metricchanged;
|
|
|
|
|
2007-05-04 22:15:47 +02:00
|
|
|
if (bnc->valid && bnc->metric)
|
|
|
|
(bgp_info_extra_get (ri))->igpmetric = bnc->metric;
|
|
|
|
else if (ri->extra)
|
|
|
|
ri->extra->igpmetric = 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return bnc->valid;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
/* Check specified next-hop is reachable or not. */
|
|
|
|
int
|
|
|
|
bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
|
|
|
|
int *changed, int *metricchanged)
|
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
|
|
|
struct prefix p;
|
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
struct in_addr addr;
|
2012-01-09 12:36:23 +01:00
|
|
|
|
|
|
|
/* If lookup is not enabled, return valid. */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
{
|
|
|
|
if (ri->extra)
|
|
|
|
ri->extra->igpmetric = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
if (afi == AFI_IP6)
|
|
|
|
return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
addr = ri->attr->nexthop;
|
|
|
|
|
|
|
|
memset (&p, 0, sizeof (struct prefix));
|
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
p.u.prefix4 = addr;
|
|
|
|
|
|
|
|
/* IBGP or ebgp-multihop */
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
bnc = rn->info;
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-08-08 17:36:44 +02:00
|
|
|
if (NULL == (bnc = zlookup_query (addr)))
|
|
|
|
bnc = bnc_new ();
|
|
|
|
else
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
if (changed)
|
|
|
|
{
|
2011-08-05 16:52:52 +02:00
|
|
|
struct bgp_table *old;
|
|
|
|
struct bgp_node *oldrn;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
|
|
|
|
old = cache2_table[AFI_IP];
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2004-11-09 02:54:03 +01:00
|
|
|
old = cache1_table[AFI_IP];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
oldrn = bgp_node_lookup (old, &p);
|
|
|
|
if (oldrn)
|
|
|
|
{
|
2011-08-05 16:52:52 +02:00
|
|
|
struct bgp_nexthop_cache *oldbnc = oldrn->info;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2011-08-05 16:52:52 +02:00
|
|
|
bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (bnc->metric != oldbnc->metric)
|
|
|
|
bnc->metricchanged = 1;
|
2010-07-27 18:28:55 +02:00
|
|
|
|
|
|
|
bgp_unlock_node (oldrn);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rn->info = bnc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed)
|
|
|
|
*changed = bnc->changed;
|
|
|
|
|
|
|
|
if (metricchanged)
|
|
|
|
*metricchanged = bnc->metricchanged;
|
|
|
|
|
2007-05-04 22:15:47 +02:00
|
|
|
if (bnc->valid && bnc->metric)
|
|
|
|
(bgp_info_extra_get(ri))->igpmetric = bnc->metric;
|
|
|
|
else if (ri->extra)
|
|
|
|
ri->extra->igpmetric = 0;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return bnc->valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset and free all BGP nexthop cache. */
|
2005-06-28 14:44:16 +02:00
|
|
|
static void
|
2002-12-13 21:15:29 +01:00
|
|
|
bgp_nexthop_cache_reset (struct bgp_table *table)
|
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
|
|
|
|
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
|
|
|
|
if ((bnc = rn->info) != NULL)
|
|
|
|
{
|
|
|
|
bnc_free (bnc);
|
|
|
|
rn->info = NULL;
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-06-28 14:44:16 +02:00
|
|
|
static void
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_scan (afi_t afi, safi_t safi)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
|
|
|
struct bgp *bgp;
|
|
|
|
struct bgp_info *bi;
|
|
|
|
struct bgp_info *next;
|
|
|
|
struct peer *peer;
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *node, *nnode;
|
2015-05-20 02:40:34 +02:00
|
|
|
#if BGP_SCAN_NEXTHOP
|
2002-12-13 21:15:29 +01:00
|
|
|
int valid;
|
|
|
|
int current;
|
|
|
|
int changed;
|
|
|
|
int metricchanged;
|
|
|
|
|
|
|
|
/* Change cache. */
|
2004-11-09 02:54:03 +01:00
|
|
|
if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
|
|
|
|
bgp_nexthop_cache_table[afi] = cache2_table[afi];
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_nexthop_cache_table[afi] = cache1_table[afi];
|
2015-05-20 02:40:34 +02:00
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* Get default bgp. */
|
|
|
|
bgp = bgp_get_default ();
|
|
|
|
if (bgp == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Maximum prefix check */
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
if (peer->status != Established)
|
|
|
|
continue;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
if (peer->afc[afi][SAFI_UNICAST])
|
|
|
|
bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
|
|
|
|
if (peer->afc[afi][SAFI_MULTICAST])
|
|
|
|
bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
|
|
|
|
if (peer->afc[afi][SAFI_MPLS_VPN])
|
|
|
|
bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
|
2002-12-13 21:15:29 +01:00
|
|
|
rn = bgp_route_next (rn))
|
|
|
|
{
|
|
|
|
for (bi = rn->info; bi; bi = next)
|
|
|
|
{
|
|
|
|
next = bi->next;
|
|
|
|
|
|
|
|
if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
|
|
|
|
{
|
2015-05-20 02:40:34 +02:00
|
|
|
#if BGP_SCAN_NEXTHOP
|
2002-12-13 21:15:29 +01:00
|
|
|
changed = 0;
|
|
|
|
metricchanged = 0;
|
|
|
|
|
2013-04-11 10:24:30 +02:00
|
|
|
if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1
|
|
|
|
&& !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
|
2011-08-05 16:52:52 +02:00
|
|
|
valid = bgp_nexthop_onlink (afi, bi->attr);
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2004-11-09 02:54:03 +01:00
|
|
|
valid = bgp_nexthop_lookup (afi, bi->peer, bi,
|
2002-12-13 21:15:29 +01:00
|
|
|
&changed, &metricchanged);
|
|
|
|
|
|
|
|
current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
|
|
|
|
|
|
|
|
if (changed)
|
|
|
|
SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
|
|
|
|
else
|
|
|
|
UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
|
|
|
|
|
|
|
|
if (valid != current)
|
|
|
|
{
|
|
|
|
if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
|
|
|
|
{
|
|
|
|
bgp_aggregate_decrement (bgp, &rn->p, bi,
|
2004-11-09 02:54:03 +01:00
|
|
|
afi, SAFI_UNICAST);
|
[bgpd] Handle pcount as flags are changed, fixing pcount issues
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-07 02:24:49 +02:00
|
|
|
bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
[bgpd] Handle pcount as flags are changed, fixing pcount issues
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-07 02:24:49 +02:00
|
|
|
bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
|
2002-12-13 21:15:29 +01:00
|
|
|
bgp_aggregate_increment (bgp, &rn->p, bi,
|
2004-11-09 02:54:03 +01:00
|
|
|
afi, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
2015-05-20 02:40:34 +02:00
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
|
2002-12-13 21:15:29 +01:00
|
|
|
BGP_CONFIG_DAMPENING)
|
2007-05-04 22:15:47 +02:00
|
|
|
&& bi->extra && bi->extra->damp_info )
|
2004-11-09 02:54:03 +01:00
|
|
|
if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
|
2002-12-13 21:15:29 +01:00
|
|
|
bgp_aggregate_increment (bgp, &rn->p, bi,
|
2004-11-09 02:54:03 +01:00
|
|
|
afi, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_process (bgp, rn, afi, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
#if BGP_SCAN_NEXTHOP
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Flash old cache. */
|
2004-11-09 02:54:03 +01:00
|
|
|
if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
|
|
|
|
bgp_nexthop_cache_reset (cache2_table[afi]);
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_nexthop_cache_reset (cache1_table[afi]);
|
2015-05-20 02:40:34 +02:00
|
|
|
#endif
|
2005-02-01 21:13:16 +01:00
|
|
|
|
|
|
|
if (BGP_DEBUG (events, EVENTS))
|
|
|
|
{
|
|
|
|
if (afi == AFI_IP)
|
|
|
|
zlog_debug ("scanning IPv4 Unicast routing tables");
|
|
|
|
else if (afi == AFI_IP6)
|
|
|
|
zlog_debug ("scanning IPv6 Unicast routing tables");
|
|
|
|
}
|
2012-12-07 17:45:52 +01:00
|
|
|
|
|
|
|
/* Reevaluate default-originate route-maps and announce/withdraw
|
|
|
|
* default route if neccesary. */
|
|
|
|
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
|
|
|
{
|
|
|
|
if (peer->status == Established
|
|
|
|
&& CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
|
|
|
|
&& peer->default_rmap[afi][safi].name)
|
|
|
|
bgp_default_originate (peer, afi, safi, 0);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* BGP scan thread. This thread check nexthop reachability. */
|
2005-06-28 14:44:16 +02:00
|
|
|
static int
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_scan_timer (struct thread *t)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
bgp_scan_thread =
|
2004-11-09 02:54:03 +01:00
|
|
|
thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2005-02-01 21:13:16 +01:00
|
|
|
if (BGP_DEBUG (events, EVENTS))
|
2004-12-08 21:41:23 +01:00
|
|
|
zlog_debug ("Performing BGP general scanning");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_scan (AFI_IP, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_scan (AFI_IP6, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-05-07 18:52:52 +02:00
|
|
|
|
|
|
|
/* BGP own address structure */
|
|
|
|
struct bgp_addr
|
|
|
|
{
|
|
|
|
struct in_addr addr;
|
|
|
|
int refcnt;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct hash *bgp_address_hash;
|
|
|
|
|
|
|
|
static void *
|
|
|
|
bgp_address_hash_alloc (void *p)
|
|
|
|
{
|
|
|
|
struct in_addr *val = p;
|
|
|
|
struct bgp_addr *addr;
|
|
|
|
|
|
|
|
addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
|
|
|
|
addr->refcnt = 0;
|
|
|
|
addr->addr.s_addr = val->s_addr;
|
|
|
|
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
bgp_address_hash_key_make (void *p)
|
|
|
|
{
|
|
|
|
const struct bgp_addr *addr = p;
|
|
|
|
|
|
|
|
return jhash_1word(addr->addr.s_addr, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
bgp_address_hash_cmp (const void *p1, const void *p2)
|
|
|
|
{
|
|
|
|
const struct bgp_addr *addr1 = p1;
|
|
|
|
const struct bgp_addr *addr2 = p2;
|
|
|
|
|
|
|
|
return addr1->addr.s_addr == addr2->addr.s_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bgp_address_init (void)
|
|
|
|
{
|
|
|
|
bgp_address_hash = hash_create (bgp_address_hash_key_make,
|
|
|
|
bgp_address_hash_cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bgp_address_add (struct prefix *p)
|
|
|
|
{
|
|
|
|
struct bgp_addr tmp;
|
|
|
|
struct bgp_addr *addr;
|
|
|
|
|
|
|
|
tmp.addr = p->u.prefix4;
|
|
|
|
|
|
|
|
addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
|
|
|
|
addr->refcnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bgp_address_del (struct prefix *p)
|
|
|
|
{
|
|
|
|
struct bgp_addr tmp;
|
|
|
|
struct bgp_addr *addr;
|
|
|
|
|
|
|
|
tmp.addr = p->u.prefix4;
|
|
|
|
|
|
|
|
addr = hash_lookup (bgp_address_hash, &tmp);
|
2013-03-11 13:38:31 +01:00
|
|
|
/* may have been deleted earlier by bgp_interface_down() */
|
|
|
|
if (addr == NULL)
|
|
|
|
return;
|
|
|
|
|
2012-05-07 18:52:52 +02:00
|
|
|
addr->refcnt--;
|
|
|
|
|
|
|
|
if (addr->refcnt == 0)
|
|
|
|
{
|
|
|
|
hash_release (bgp_address_hash, addr);
|
|
|
|
XFREE (MTYPE_BGP_ADDR, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
struct bgp_connected_ref
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
unsigned int refcnt;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
bgp_connected_add (struct connected *ifc)
|
|
|
|
{
|
|
|
|
struct prefix p;
|
|
|
|
struct prefix *addr;
|
|
|
|
struct interface *ifp;
|
|
|
|
struct bgp_node *rn;
|
2004-11-09 02:54:03 +01:00
|
|
|
struct bgp_connected_ref *bc;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
ifp = ifc->ifp;
|
|
|
|
|
|
|
|
if (! ifp)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (if_is_loopback (ifp))
|
|
|
|
return;
|
|
|
|
|
|
|
|
addr = ifc->address;
|
|
|
|
|
|
|
|
if (addr->family == AF_INET)
|
|
|
|
{
|
[PtP over ethernet] New peer flag allows much more addressing flexibility
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating
whether a peer address has been configured. Comment now shows
the new interpretation of the destination addr: if ZEBRA_IFA_PEER
is set, then it must contain the destination address, otherwise
it may contain the broadcast address or be NULL.
(CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete
macros that were specific to IPv4 and not fully general.
(CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag.
(CONNECTED_PREFIX) New macro giving the prefix to insert into
the RIB: if CONNECTED_PEER, then use the destination (peer) address,
else use the address field.
(CONNECTED_ID) New macro to come up with an identifying address
for the struct connected.
* if.c: (if_lookup_address, connected_lookup_address) Streamline
logic with new CONNECTED_PREFIX macro.
* prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros
for better performance than the general prefix_copy function.
* zclient.c: (zebra_interface_address_read) For non-null destination
addresses, set prefixlen to equal the address prefixlen. This
is needed to get the new CONNECTED_PREFIX macro to work properly.
* connected.c: (connected_up_ipv4, connected_down_ipv4,
connected_up_ipv6, connected_down_ipv6) Simplify logic using the
new CONNECTED_PREFIX macro.
(connected_add_ipv4) Set prefixlen in destination addresses (required
by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead
of testing for IFF_POINTOPOINT. Delete invalid warning message.
Warn about cases where the ZEBRA_IFA_PEER is set but no
destination address has been supplied (and turn off the flag).
(connected_add_ipv6) Add new flags argument so callers may set
the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies
IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning.
Set prefixlen in destination address so CONNECTED_PREFIX will work.
* connected.h: (connected_add_ipv6) Add new flags argument so
callers may set the ZEBRA_IFA_PEER flag.
* interface.c: (connected_dump_vty) Use CONNECTED_PEER macro
to decide whether the destination address is a peer or broadcast
address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT).
* if_ioctl.c: (if_getaddrs) Instead of setting a peer address
only when the IFF_POINTOPOINT is set, we now accept a peer
address whenever it is available and not the same as the local
address. Otherwise (no peer address assigned), we check
for a broadcast address (regardless of the IFF_BROADCAST flag).
And must now pass a flags value of ZEBRA_IFA_PEER to
connected_add_ipv4 when a peer address is assigned.
The same new logic is used with the IPv6 code as well (and we
pass the new flags argument to connected_add_ipv6).
(if_get_addr) Do not bother to check IFF_POINTOPOINT: just
issue the SIOCGIFDSTADDR ioctl and see if we get back
a peer address not matching the local address (and set
the ZEBRA_IFA_PEER in that case). If there's no peer address,
try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set.
* if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl
without bothering to check the IFF_POINTOPOINT flag. And if
no peer address was found, just try the SIOCGLIFBRDADDR ioctl
without checking the IFF_BROADCAST flag. Call connected_add_ipv4
and connected_add_ipv6 with appropriate flags.
* if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to
connected_add_ipv6.
* kernel_socket.c: (ifam_read) Must pass new flags argument to
connected_add_ipv6.
* rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2
to determine local and possible peer address (so there's no longer
a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately.
Pass new flags argument to connected_add_ipv6.
(netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast
to determine whether the connected destination address is a
broadcast address.
* bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete)
Simplify logic by using new CONNECTED_PREFIX macro.
* ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix,
ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX
macro, both options collapse into the same code.
* ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new
CONNECTED_ID macro.
(ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro
instead of testing the IFF_POINTOPOINT flag.
* ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro
instead of testing with if_is_pointopoint. And add commented-out
code to implement alternative (in my opinion) more elegant behavior
that has no special-case treatment for PtP addresses.
(ospf_network_run) Use new CONNECTED_ID macro to simplify logic.
* rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID
macro to simplify logic.
(rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does
not give a useful result if prefixlen is 32 (we require a peer
address in such cases).
* ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
|
|
|
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
2002-12-13 21:15:29 +01:00
|
|
|
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
|
|
|
|
|
|
|
|
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
|
|
|
|
return;
|
|
|
|
|
2012-05-07 18:52:52 +02:00
|
|
|
bgp_address_add (addr);
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
bc = rn->info;
|
|
|
|
bc->refcnt++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-27 18:28:55 +02:00
|
|
|
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
|
2002-12-13 21:15:29 +01:00
|
|
|
bc->refcnt = 1;
|
|
|
|
rn->info = bc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef HAVE_IPV6
|
[PtP over ethernet] New peer flag allows much more addressing flexibility
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating
whether a peer address has been configured. Comment now shows
the new interpretation of the destination addr: if ZEBRA_IFA_PEER
is set, then it must contain the destination address, otherwise
it may contain the broadcast address or be NULL.
(CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete
macros that were specific to IPv4 and not fully general.
(CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag.
(CONNECTED_PREFIX) New macro giving the prefix to insert into
the RIB: if CONNECTED_PEER, then use the destination (peer) address,
else use the address field.
(CONNECTED_ID) New macro to come up with an identifying address
for the struct connected.
* if.c: (if_lookup_address, connected_lookup_address) Streamline
logic with new CONNECTED_PREFIX macro.
* prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros
for better performance than the general prefix_copy function.
* zclient.c: (zebra_interface_address_read) For non-null destination
addresses, set prefixlen to equal the address prefixlen. This
is needed to get the new CONNECTED_PREFIX macro to work properly.
* connected.c: (connected_up_ipv4, connected_down_ipv4,
connected_up_ipv6, connected_down_ipv6) Simplify logic using the
new CONNECTED_PREFIX macro.
(connected_add_ipv4) Set prefixlen in destination addresses (required
by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead
of testing for IFF_POINTOPOINT. Delete invalid warning message.
Warn about cases where the ZEBRA_IFA_PEER is set but no
destination address has been supplied (and turn off the flag).
(connected_add_ipv6) Add new flags argument so callers may set
the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies
IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning.
Set prefixlen in destination address so CONNECTED_PREFIX will work.
* connected.h: (connected_add_ipv6) Add new flags argument so
callers may set the ZEBRA_IFA_PEER flag.
* interface.c: (connected_dump_vty) Use CONNECTED_PEER macro
to decide whether the destination address is a peer or broadcast
address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT).
* if_ioctl.c: (if_getaddrs) Instead of setting a peer address
only when the IFF_POINTOPOINT is set, we now accept a peer
address whenever it is available and not the same as the local
address. Otherwise (no peer address assigned), we check
for a broadcast address (regardless of the IFF_BROADCAST flag).
And must now pass a flags value of ZEBRA_IFA_PEER to
connected_add_ipv4 when a peer address is assigned.
The same new logic is used with the IPv6 code as well (and we
pass the new flags argument to connected_add_ipv6).
(if_get_addr) Do not bother to check IFF_POINTOPOINT: just
issue the SIOCGIFDSTADDR ioctl and see if we get back
a peer address not matching the local address (and set
the ZEBRA_IFA_PEER in that case). If there's no peer address,
try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set.
* if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl
without bothering to check the IFF_POINTOPOINT flag. And if
no peer address was found, just try the SIOCGLIFBRDADDR ioctl
without checking the IFF_BROADCAST flag. Call connected_add_ipv4
and connected_add_ipv6 with appropriate flags.
* if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to
connected_add_ipv6.
* kernel_socket.c: (ifam_read) Must pass new flags argument to
connected_add_ipv6.
* rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2
to determine local and possible peer address (so there's no longer
a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately.
Pass new flags argument to connected_add_ipv6.
(netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast
to determine whether the connected destination address is a
broadcast address.
* bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete)
Simplify logic by using new CONNECTED_PREFIX macro.
* ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix,
ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX
macro, both options collapse into the same code.
* ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new
CONNECTED_ID macro.
(ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro
instead of testing the IFF_POINTOPOINT flag.
* ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro
instead of testing with if_is_pointopoint. And add commented-out
code to implement alternative (in my opinion) more elegant behavior
that has no special-case treatment for PtP addresses.
(ospf_network_run) Use new CONNECTED_ID macro to simplify logic.
* rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID
macro to simplify logic.
(rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does
not give a useful result if prefixlen is 32 (we require a peer
address in such cases).
* ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
|
|
|
else if (addr->family == AF_INET6)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
[PtP over ethernet] New peer flag allows much more addressing flexibility
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating
whether a peer address has been configured. Comment now shows
the new interpretation of the destination addr: if ZEBRA_IFA_PEER
is set, then it must contain the destination address, otherwise
it may contain the broadcast address or be NULL.
(CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete
macros that were specific to IPv4 and not fully general.
(CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag.
(CONNECTED_PREFIX) New macro giving the prefix to insert into
the RIB: if CONNECTED_PEER, then use the destination (peer) address,
else use the address field.
(CONNECTED_ID) New macro to come up with an identifying address
for the struct connected.
* if.c: (if_lookup_address, connected_lookup_address) Streamline
logic with new CONNECTED_PREFIX macro.
* prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros
for better performance than the general prefix_copy function.
* zclient.c: (zebra_interface_address_read) For non-null destination
addresses, set prefixlen to equal the address prefixlen. This
is needed to get the new CONNECTED_PREFIX macro to work properly.
* connected.c: (connected_up_ipv4, connected_down_ipv4,
connected_up_ipv6, connected_down_ipv6) Simplify logic using the
new CONNECTED_PREFIX macro.
(connected_add_ipv4) Set prefixlen in destination addresses (required
by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead
of testing for IFF_POINTOPOINT. Delete invalid warning message.
Warn about cases where the ZEBRA_IFA_PEER is set but no
destination address has been supplied (and turn off the flag).
(connected_add_ipv6) Add new flags argument so callers may set
the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies
IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning.
Set prefixlen in destination address so CONNECTED_PREFIX will work.
* connected.h: (connected_add_ipv6) Add new flags argument so
callers may set the ZEBRA_IFA_PEER flag.
* interface.c: (connected_dump_vty) Use CONNECTED_PEER macro
to decide whether the destination address is a peer or broadcast
address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT).
* if_ioctl.c: (if_getaddrs) Instead of setting a peer address
only when the IFF_POINTOPOINT is set, we now accept a peer
address whenever it is available and not the same as the local
address. Otherwise (no peer address assigned), we check
for a broadcast address (regardless of the IFF_BROADCAST flag).
And must now pass a flags value of ZEBRA_IFA_PEER to
connected_add_ipv4 when a peer address is assigned.
The same new logic is used with the IPv6 code as well (and we
pass the new flags argument to connected_add_ipv6).
(if_get_addr) Do not bother to check IFF_POINTOPOINT: just
issue the SIOCGIFDSTADDR ioctl and see if we get back
a peer address not matching the local address (and set
the ZEBRA_IFA_PEER in that case). If there's no peer address,
try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set.
* if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl
without bothering to check the IFF_POINTOPOINT flag. And if
no peer address was found, just try the SIOCGLIFBRDADDR ioctl
without checking the IFF_BROADCAST flag. Call connected_add_ipv4
and connected_add_ipv6 with appropriate flags.
* if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to
connected_add_ipv6.
* kernel_socket.c: (ifam_read) Must pass new flags argument to
connected_add_ipv6.
* rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2
to determine local and possible peer address (so there's no longer
a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately.
Pass new flags argument to connected_add_ipv6.
(netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast
to determine whether the connected destination address is a
broadcast address.
* bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete)
Simplify logic by using new CONNECTED_PREFIX macro.
* ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix,
ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX
macro, both options collapse into the same code.
* ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new
CONNECTED_ID macro.
(ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro
instead of testing the IFF_POINTOPOINT flag.
* ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro
instead of testing with if_is_pointopoint. And add commented-out
code to implement alternative (in my opinion) more elegant behavior
that has no special-case treatment for PtP addresses.
(ospf_network_run) Use new CONNECTED_ID macro to simplify logic.
* rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID
macro to simplify logic.
(rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does
not give a useful result if prefixlen is 32 (we require a peer
address in such cases).
* ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
|
|
|
PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
|
2002-12-13 21:15:29 +01:00
|
|
|
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
|
|
|
|
return;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
bc = rn->info;
|
|
|
|
bc->refcnt++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-27 18:28:55 +02:00
|
|
|
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
|
2002-12-13 21:15:29 +01:00
|
|
|
bc->refcnt = 1;
|
|
|
|
rn->info = bc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bgp_connected_delete (struct connected *ifc)
|
|
|
|
{
|
|
|
|
struct prefix p;
|
|
|
|
struct prefix *addr;
|
|
|
|
struct interface *ifp;
|
|
|
|
struct bgp_node *rn;
|
2004-11-09 02:54:03 +01:00
|
|
|
struct bgp_connected_ref *bc;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
ifp = ifc->ifp;
|
|
|
|
|
|
|
|
if (if_is_loopback (ifp))
|
|
|
|
return;
|
|
|
|
|
|
|
|
addr = ifc->address;
|
|
|
|
|
|
|
|
if (addr->family == AF_INET)
|
|
|
|
{
|
[PtP over ethernet] New peer flag allows much more addressing flexibility
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating
whether a peer address has been configured. Comment now shows
the new interpretation of the destination addr: if ZEBRA_IFA_PEER
is set, then it must contain the destination address, otherwise
it may contain the broadcast address or be NULL.
(CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete
macros that were specific to IPv4 and not fully general.
(CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag.
(CONNECTED_PREFIX) New macro giving the prefix to insert into
the RIB: if CONNECTED_PEER, then use the destination (peer) address,
else use the address field.
(CONNECTED_ID) New macro to come up with an identifying address
for the struct connected.
* if.c: (if_lookup_address, connected_lookup_address) Streamline
logic with new CONNECTED_PREFIX macro.
* prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros
for better performance than the general prefix_copy function.
* zclient.c: (zebra_interface_address_read) For non-null destination
addresses, set prefixlen to equal the address prefixlen. This
is needed to get the new CONNECTED_PREFIX macro to work properly.
* connected.c: (connected_up_ipv4, connected_down_ipv4,
connected_up_ipv6, connected_down_ipv6) Simplify logic using the
new CONNECTED_PREFIX macro.
(connected_add_ipv4) Set prefixlen in destination addresses (required
by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead
of testing for IFF_POINTOPOINT. Delete invalid warning message.
Warn about cases where the ZEBRA_IFA_PEER is set but no
destination address has been supplied (and turn off the flag).
(connected_add_ipv6) Add new flags argument so callers may set
the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies
IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning.
Set prefixlen in destination address so CONNECTED_PREFIX will work.
* connected.h: (connected_add_ipv6) Add new flags argument so
callers may set the ZEBRA_IFA_PEER flag.
* interface.c: (connected_dump_vty) Use CONNECTED_PEER macro
to decide whether the destination address is a peer or broadcast
address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT).
* if_ioctl.c: (if_getaddrs) Instead of setting a peer address
only when the IFF_POINTOPOINT is set, we now accept a peer
address whenever it is available and not the same as the local
address. Otherwise (no peer address assigned), we check
for a broadcast address (regardless of the IFF_BROADCAST flag).
And must now pass a flags value of ZEBRA_IFA_PEER to
connected_add_ipv4 when a peer address is assigned.
The same new logic is used with the IPv6 code as well (and we
pass the new flags argument to connected_add_ipv6).
(if_get_addr) Do not bother to check IFF_POINTOPOINT: just
issue the SIOCGIFDSTADDR ioctl and see if we get back
a peer address not matching the local address (and set
the ZEBRA_IFA_PEER in that case). If there's no peer address,
try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set.
* if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl
without bothering to check the IFF_POINTOPOINT flag. And if
no peer address was found, just try the SIOCGLIFBRDADDR ioctl
without checking the IFF_BROADCAST flag. Call connected_add_ipv4
and connected_add_ipv6 with appropriate flags.
* if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to
connected_add_ipv6.
* kernel_socket.c: (ifam_read) Must pass new flags argument to
connected_add_ipv6.
* rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2
to determine local and possible peer address (so there's no longer
a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately.
Pass new flags argument to connected_add_ipv6.
(netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast
to determine whether the connected destination address is a
broadcast address.
* bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete)
Simplify logic by using new CONNECTED_PREFIX macro.
* ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix,
ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX
macro, both options collapse into the same code.
* ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new
CONNECTED_ID macro.
(ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro
instead of testing the IFF_POINTOPOINT flag.
* ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro
instead of testing with if_is_pointopoint. And add commented-out
code to implement alternative (in my opinion) more elegant behavior
that has no special-case treatment for PtP addresses.
(ospf_network_run) Use new CONNECTED_ID macro to simplify logic.
* rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID
macro to simplify logic.
(rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does
not give a useful result if prefixlen is 32 (we require a peer
address in such cases).
* ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
|
|
|
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
2002-12-13 21:15:29 +01:00
|
|
|
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
|
|
|
|
|
|
|
|
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
|
|
|
|
return;
|
|
|
|
|
2012-05-07 18:52:52 +02:00
|
|
|
bgp_address_del (addr);
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (! rn)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bc = rn->info;
|
|
|
|
bc->refcnt--;
|
|
|
|
if (bc->refcnt == 0)
|
|
|
|
{
|
2010-07-27 18:28:55 +02:00
|
|
|
XFREE (MTYPE_BGP_CONN, bc);
|
2002-12-13 21:15:29 +01:00
|
|
|
rn->info = NULL;
|
|
|
|
}
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
}
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
else if (addr->family == AF_INET6)
|
|
|
|
{
|
[PtP over ethernet] New peer flag allows much more addressing flexibility
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating
whether a peer address has been configured. Comment now shows
the new interpretation of the destination addr: if ZEBRA_IFA_PEER
is set, then it must contain the destination address, otherwise
it may contain the broadcast address or be NULL.
(CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete
macros that were specific to IPv4 and not fully general.
(CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag.
(CONNECTED_PREFIX) New macro giving the prefix to insert into
the RIB: if CONNECTED_PEER, then use the destination (peer) address,
else use the address field.
(CONNECTED_ID) New macro to come up with an identifying address
for the struct connected.
* if.c: (if_lookup_address, connected_lookup_address) Streamline
logic with new CONNECTED_PREFIX macro.
* prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros
for better performance than the general prefix_copy function.
* zclient.c: (zebra_interface_address_read) For non-null destination
addresses, set prefixlen to equal the address prefixlen. This
is needed to get the new CONNECTED_PREFIX macro to work properly.
* connected.c: (connected_up_ipv4, connected_down_ipv4,
connected_up_ipv6, connected_down_ipv6) Simplify logic using the
new CONNECTED_PREFIX macro.
(connected_add_ipv4) Set prefixlen in destination addresses (required
by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead
of testing for IFF_POINTOPOINT. Delete invalid warning message.
Warn about cases where the ZEBRA_IFA_PEER is set but no
destination address has been supplied (and turn off the flag).
(connected_add_ipv6) Add new flags argument so callers may set
the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies
IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning.
Set prefixlen in destination address so CONNECTED_PREFIX will work.
* connected.h: (connected_add_ipv6) Add new flags argument so
callers may set the ZEBRA_IFA_PEER flag.
* interface.c: (connected_dump_vty) Use CONNECTED_PEER macro
to decide whether the destination address is a peer or broadcast
address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT).
* if_ioctl.c: (if_getaddrs) Instead of setting a peer address
only when the IFF_POINTOPOINT is set, we now accept a peer
address whenever it is available and not the same as the local
address. Otherwise (no peer address assigned), we check
for a broadcast address (regardless of the IFF_BROADCAST flag).
And must now pass a flags value of ZEBRA_IFA_PEER to
connected_add_ipv4 when a peer address is assigned.
The same new logic is used with the IPv6 code as well (and we
pass the new flags argument to connected_add_ipv6).
(if_get_addr) Do not bother to check IFF_POINTOPOINT: just
issue the SIOCGIFDSTADDR ioctl and see if we get back
a peer address not matching the local address (and set
the ZEBRA_IFA_PEER in that case). If there's no peer address,
try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set.
* if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl
without bothering to check the IFF_POINTOPOINT flag. And if
no peer address was found, just try the SIOCGLIFBRDADDR ioctl
without checking the IFF_BROADCAST flag. Call connected_add_ipv4
and connected_add_ipv6 with appropriate flags.
* if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to
connected_add_ipv6.
* kernel_socket.c: (ifam_read) Must pass new flags argument to
connected_add_ipv6.
* rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2
to determine local and possible peer address (so there's no longer
a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately.
Pass new flags argument to connected_add_ipv6.
(netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast
to determine whether the connected destination address is a
broadcast address.
* bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete)
Simplify logic by using new CONNECTED_PREFIX macro.
* ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix,
ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX
macro, both options collapse into the same code.
* ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new
CONNECTED_ID macro.
(ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX
macro.
* ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro
instead of testing the IFF_POINTOPOINT flag.
* ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro
instead of testing with if_is_pointopoint. And add commented-out
code to implement alternative (in my opinion) more elegant behavior
that has no special-case treatment for PtP addresses.
(ospf_network_run) Use new CONNECTED_ID macro to simplify logic.
* rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID
macro to simplify logic.
(rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does
not give a useful result if prefixlen is 32 (we require a peer
address in such cases).
* ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
|
|
|
PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
|
2002-12-13 21:15:29 +01:00
|
|
|
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
|
|
|
|
return;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (! rn)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bc = rn->info;
|
|
|
|
bc->refcnt--;
|
|
|
|
if (bc->refcnt == 0)
|
|
|
|
{
|
2010-07-27 18:28:55 +02:00
|
|
|
XFREE (MTYPE_BGP_CONN, bc);
|
2002-12-13 21:15:29 +01:00
|
|
|
rn->info = NULL;
|
|
|
|
}
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
bgp_unlock_node (rn);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-05-07 18:52:52 +02:00
|
|
|
bgp_nexthop_self (struct attr *attr)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2012-05-07 18:52:52 +02:00
|
|
|
struct bgp_addr tmp, *addr;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2012-05-07 18:52:52 +02:00
|
|
|
tmp.addr = attr->nexthop;
|
|
|
|
|
|
|
|
addr = hash_lookup (bgp_address_hash, &tmp);
|
|
|
|
if (addr)
|
|
|
|
return 1;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2005-06-28 14:44:16 +02:00
|
|
|
static struct bgp_nexthop_cache *
|
2009-02-09 19:14:16 +01:00
|
|
|
zlookup_read (void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct stream *s;
|
2006-01-17 18:33:46 +01:00
|
|
|
uint16_t length;
|
|
|
|
u_char marker;
|
|
|
|
u_char version;
|
|
|
|
uint16_t command;
|
2002-12-13 21:15:29 +01:00
|
|
|
int nbytes;
|
|
|
|
struct in_addr raddr;
|
2006-01-17 18:33:46 +01:00
|
|
|
uint32_t metric;
|
2002-12-13 21:15:29 +01:00
|
|
|
int i;
|
|
|
|
u_char nexthop_num;
|
|
|
|
struct nexthop *nexthop;
|
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
|
|
|
|
s = zlookup->ibuf;
|
|
|
|
stream_reset (s);
|
|
|
|
|
|
|
|
nbytes = stream_read (s, zlookup->sock, 2);
|
|
|
|
length = stream_getw (s);
|
|
|
|
|
|
|
|
nbytes = stream_read (s, zlookup->sock, length - 2);
|
2006-01-17 18:33:46 +01:00
|
|
|
marker = stream_getc (s);
|
|
|
|
version = stream_getc (s);
|
|
|
|
|
|
|
|
if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
|
|
|
|
{
|
|
|
|
zlog_err("%s: socket %d version mismatch, marker %d, version %d",
|
|
|
|
__func__, zlookup->sock, marker, version);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
command = stream_getw (s);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
raddr.s_addr = stream_get_ipv4 (s);
|
|
|
|
metric = stream_getl (s);
|
|
|
|
nexthop_num = stream_getc (s);
|
|
|
|
|
|
|
|
if (nexthop_num)
|
|
|
|
{
|
|
|
|
bnc = bnc_new ();
|
|
|
|
bnc->valid = 1;
|
|
|
|
bnc->metric = metric;
|
|
|
|
bnc->nexthop_num = nexthop_num;
|
|
|
|
|
|
|
|
for (i = 0; i < nexthop_num; i++)
|
|
|
|
{
|
2008-08-18 23:13:29 +02:00
|
|
|
nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
|
2002-12-13 21:15:29 +01:00
|
|
|
nexthop->type = stream_getc (s);
|
|
|
|
switch (nexthop->type)
|
|
|
|
{
|
|
|
|
case ZEBRA_NEXTHOP_IPV4:
|
|
|
|
nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
|
|
|
|
break;
|
2013-05-25 16:01:35 +02:00
|
|
|
case ZEBRA_NEXTHOP_IPV4_IFINDEX:
|
|
|
|
nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
|
|
|
|
nexthop->ifindex = stream_getl (s);
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
case ZEBRA_NEXTHOP_IFINDEX:
|
|
|
|
case ZEBRA_NEXTHOP_IFNAME:
|
|
|
|
nexthop->ifindex = stream_getl (s);
|
|
|
|
break;
|
2004-03-04 18:45:00 +01:00
|
|
|
default:
|
|
|
|
/* do nothing */
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
bnc_nexthop_add (bnc, nexthop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return bnc;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bgp_nexthop_cache *
|
|
|
|
zlookup_query (struct in_addr addr)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct stream *s;
|
|
|
|
|
|
|
|
/* Check socket. */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
s = zlookup->obuf;
|
|
|
|
stream_reset (s);
|
2006-01-17 18:33:46 +01:00
|
|
|
zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
|
2002-12-13 21:15:29 +01:00
|
|
|
stream_put_in_addr (s, &addr);
|
2006-01-17 18:33:46 +01:00
|
|
|
|
|
|
|
stream_putw_at (s, 0, stream_get_endp (s));
|
|
|
|
|
|
|
|
ret = writen (zlookup->sock, s->data, stream_get_endp (s));
|
2002-12-13 21:15:29 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
zlog_err ("can't write to zlookup->sock");
|
|
|
|
close (zlookup->sock);
|
|
|
|
zlookup->sock = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
zlog_err ("zlookup->sock connection closed");
|
|
|
|
close (zlookup->sock);
|
|
|
|
zlookup->sock = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return zlookup_read ();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
2005-06-28 14:44:16 +02:00
|
|
|
static struct bgp_nexthop_cache *
|
2009-02-09 19:14:16 +01:00
|
|
|
zlookup_read_ipv6 (void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct stream *s;
|
2006-01-17 18:33:46 +01:00
|
|
|
uint16_t length;
|
|
|
|
u_char version, marker;
|
|
|
|
uint16_t command;
|
2002-12-13 21:15:29 +01:00
|
|
|
int nbytes;
|
|
|
|
struct in6_addr raddr;
|
2006-01-17 18:33:46 +01:00
|
|
|
uint32_t metric;
|
2002-12-13 21:15:29 +01:00
|
|
|
int i;
|
|
|
|
u_char nexthop_num;
|
|
|
|
struct nexthop *nexthop;
|
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
|
|
|
|
s = zlookup->ibuf;
|
|
|
|
stream_reset (s);
|
|
|
|
|
|
|
|
nbytes = stream_read (s, zlookup->sock, 2);
|
|
|
|
length = stream_getw (s);
|
|
|
|
|
|
|
|
nbytes = stream_read (s, zlookup->sock, length - 2);
|
2006-01-17 18:33:46 +01:00
|
|
|
marker = stream_getc (s);
|
|
|
|
version = stream_getc (s);
|
|
|
|
|
|
|
|
if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
|
|
|
|
{
|
|
|
|
zlog_err("%s: socket %d version mismatch, marker %d, version %d",
|
|
|
|
__func__, zlookup->sock, marker, version);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
command = stream_getw (s);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
stream_get (&raddr, s, 16);
|
|
|
|
|
|
|
|
metric = stream_getl (s);
|
|
|
|
nexthop_num = stream_getc (s);
|
|
|
|
|
|
|
|
if (nexthop_num)
|
|
|
|
{
|
|
|
|
bnc = bnc_new ();
|
|
|
|
bnc->valid = 1;
|
|
|
|
bnc->metric = metric;
|
|
|
|
bnc->nexthop_num = nexthop_num;
|
|
|
|
|
|
|
|
for (i = 0; i < nexthop_num; i++)
|
|
|
|
{
|
2008-08-18 23:13:29 +02:00
|
|
|
nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
|
2002-12-13 21:15:29 +01:00
|
|
|
nexthop->type = stream_getc (s);
|
|
|
|
switch (nexthop->type)
|
|
|
|
{
|
|
|
|
case ZEBRA_NEXTHOP_IPV6:
|
|
|
|
stream_get (&nexthop->gate.ipv6, s, 16);
|
|
|
|
break;
|
|
|
|
case ZEBRA_NEXTHOP_IPV6_IFINDEX:
|
|
|
|
case ZEBRA_NEXTHOP_IPV6_IFNAME:
|
|
|
|
stream_get (&nexthop->gate.ipv6, s, 16);
|
|
|
|
nexthop->ifindex = stream_getl (s);
|
|
|
|
break;
|
|
|
|
case ZEBRA_NEXTHOP_IFINDEX:
|
|
|
|
case ZEBRA_NEXTHOP_IFNAME:
|
|
|
|
nexthop->ifindex = stream_getl (s);
|
|
|
|
break;
|
2004-03-04 18:45:00 +01:00
|
|
|
default:
|
|
|
|
/* do nothing */
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
bnc_nexthop_add (bnc, nexthop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return bnc;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bgp_nexthop_cache *
|
|
|
|
zlookup_query_ipv6 (struct in6_addr *addr)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct stream *s;
|
|
|
|
|
|
|
|
/* Check socket. */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
s = zlookup->obuf;
|
|
|
|
stream_reset (s);
|
2006-01-17 18:33:46 +01:00
|
|
|
zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
|
2002-12-13 21:15:29 +01:00
|
|
|
stream_put (s, addr, 16);
|
2006-01-17 18:33:46 +01:00
|
|
|
stream_putw_at (s, 0, stream_get_endp (s));
|
|
|
|
|
|
|
|
ret = writen (zlookup->sock, s->data, stream_get_endp (s));
|
2002-12-13 21:15:29 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
zlog_err ("can't write to zlookup->sock");
|
|
|
|
close (zlookup->sock);
|
|
|
|
zlookup->sock = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
zlog_err ("zlookup->sock connection closed");
|
|
|
|
close (zlookup->sock);
|
|
|
|
zlookup->sock = -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return zlookup_read_ipv6 ();
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
2005-06-28 14:44:16 +02:00
|
|
|
static int
|
|
|
|
bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
|
|
|
|
struct in_addr *igpnexthop)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct stream *s;
|
|
|
|
int ret;
|
2006-01-17 18:33:46 +01:00
|
|
|
u_int16_t length, command;
|
|
|
|
u_char version, marker;
|
2002-12-13 21:15:29 +01:00
|
|
|
int nbytes;
|
|
|
|
struct in_addr addr;
|
|
|
|
struct in_addr nexthop;
|
|
|
|
u_int32_t metric = 0;
|
|
|
|
u_char nexthop_num;
|
|
|
|
u_char nexthop_type;
|
|
|
|
|
|
|
|
/* If lookup connection is not available return valid. */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
{
|
|
|
|
if (igpmetric)
|
|
|
|
*igpmetric = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send query to the lookup connection */
|
|
|
|
s = zlookup->obuf;
|
|
|
|
stream_reset (s);
|
2006-01-17 18:33:46 +01:00
|
|
|
zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
stream_putc (s, p->prefixlen);
|
|
|
|
stream_put_in_addr (s, &p->u.prefix4);
|
2006-01-17 18:33:46 +01:00
|
|
|
|
|
|
|
stream_putw_at (s, 0, stream_get_endp (s));
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Write the packet. */
|
2006-01-17 18:33:46 +01:00
|
|
|
ret = writen (zlookup->sock, s->data, stream_get_endp (s));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
zlog_err ("can't write to zlookup->sock");
|
|
|
|
close (zlookup->sock);
|
|
|
|
zlookup->sock = -1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
zlog_err ("zlookup->sock connection closed");
|
|
|
|
close (zlookup->sock);
|
|
|
|
zlookup->sock = -1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get result. */
|
|
|
|
stream_reset (s);
|
|
|
|
|
|
|
|
/* Fetch length. */
|
|
|
|
nbytes = stream_read (s, zlookup->sock, 2);
|
|
|
|
length = stream_getw (s);
|
|
|
|
|
|
|
|
/* Fetch whole data. */
|
|
|
|
nbytes = stream_read (s, zlookup->sock, length - 2);
|
2006-01-17 18:33:46 +01:00
|
|
|
marker = stream_getc (s);
|
|
|
|
version = stream_getc (s);
|
|
|
|
|
|
|
|
if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
|
|
|
|
{
|
|
|
|
zlog_err("%s: socket %d version mismatch, marker %d, version %d",
|
|
|
|
__func__, zlookup->sock, marker, version);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
command = stream_getw (s);
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
addr.s_addr = stream_get_ipv4 (s);
|
|
|
|
metric = stream_getl (s);
|
|
|
|
nexthop_num = stream_getc (s);
|
|
|
|
|
|
|
|
/* Set IGP metric value. */
|
|
|
|
if (igpmetric)
|
|
|
|
*igpmetric = metric;
|
|
|
|
|
|
|
|
/* If there is nexthop then this is active route. */
|
|
|
|
if (nexthop_num)
|
|
|
|
{
|
|
|
|
nexthop.s_addr = 0;
|
|
|
|
nexthop_type = stream_getc (s);
|
2013-05-25 16:01:36 +02:00
|
|
|
switch (nexthop_type)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2013-05-25 16:01:36 +02:00
|
|
|
case ZEBRA_NEXTHOP_IPV4:
|
2002-12-13 21:15:29 +01:00
|
|
|
nexthop.s_addr = stream_get_ipv4 (s);
|
2013-05-25 16:01:36 +02:00
|
|
|
break;
|
|
|
|
case ZEBRA_NEXTHOP_IPV4_IFINDEX:
|
|
|
|
nexthop.s_addr = stream_get_ipv4 (s);
|
|
|
|
/* ifindex */ (void)stream_getl (s);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* do nothing */
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2013-05-25 16:01:36 +02:00
|
|
|
*igpnexthop = nexthop;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Scan all configured BGP route then check the route exists in IGP or
|
|
|
|
not. */
|
2005-06-28 14:44:16 +02:00
|
|
|
static int
|
2002-12-13 21:15:29 +01:00
|
|
|
bgp_import (struct thread *t)
|
|
|
|
{
|
|
|
|
struct bgp *bgp;
|
|
|
|
struct bgp_node *rn;
|
|
|
|
struct bgp_static *bgp_static;
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *node, *nnode;
|
2002-12-13 21:15:29 +01:00
|
|
|
int valid;
|
|
|
|
u_int32_t metric;
|
|
|
|
struct in_addr nexthop;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
|
|
|
|
bgp_import_thread =
|
|
|
|
thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
|
|
|
|
|
2005-02-01 21:13:16 +01:00
|
|
|
if (BGP_DEBUG (events, EVENTS))
|
|
|
|
zlog_debug ("Import timer expired.");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
|
2003-04-28 19:11:02 +02:00
|
|
|
{
|
|
|
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
|
|
|
for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
|
|
|
|
for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
|
|
|
|
rn = bgp_route_next (rn))
|
|
|
|
if ((bgp_static = rn->info) != NULL)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2003-04-28 19:11:02 +02:00
|
|
|
if (bgp_static->backdoor)
|
|
|
|
continue;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2003-04-28 19:11:02 +02:00
|
|
|
valid = bgp_static->valid;
|
|
|
|
metric = bgp_static->igpmetric;
|
|
|
|
nexthop = bgp_static->igpnexthop;
|
|
|
|
|
|
|
|
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
|
|
|
|
&& afi == AFI_IP && safi == SAFI_UNICAST)
|
|
|
|
bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
|
|
|
|
&bgp_static->igpnexthop);
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2003-04-28 19:11:02 +02:00
|
|
|
{
|
|
|
|
bgp_static->valid = 1;
|
|
|
|
bgp_static->igpmetric = 0;
|
|
|
|
bgp_static->igpnexthop.s_addr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bgp_static->valid != valid)
|
|
|
|
{
|
|
|
|
if (bgp_static->valid)
|
|
|
|
bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
|
|
|
|
else
|
|
|
|
bgp_static_withdraw (bgp, &rn->p, afi, safi);
|
|
|
|
}
|
|
|
|
else if (bgp_static->valid)
|
|
|
|
{
|
|
|
|
if (bgp_static->igpmetric != metric
|
|
|
|
|| bgp_static->igpnexthop.s_addr != nexthop.s_addr
|
|
|
|
|| bgp_static->rmap.name)
|
|
|
|
bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2003-04-28 19:11:02 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect to zebra for nexthop lookup. */
|
2005-06-28 14:44:16 +02:00
|
|
|
static int
|
2002-12-13 21:15:29 +01:00
|
|
|
zlookup_connect (struct thread *t)
|
|
|
|
{
|
|
|
|
struct zclient *zlookup;
|
|
|
|
|
|
|
|
zlookup = THREAD_ARG (t);
|
|
|
|
zlookup->t_connect = NULL;
|
|
|
|
|
|
|
|
if (zlookup->sock != -1)
|
|
|
|
return 0;
|
|
|
|
|
2011-11-25 15:51:48 +01:00
|
|
|
if (zclient_socket_connect (zlookup) < 0)
|
2002-12-13 21:15:29 +01:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check specified multiaccess next-hop. */
|
|
|
|
int
|
|
|
|
bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
|
|
|
|
{
|
|
|
|
struct bgp_node *rn1;
|
|
|
|
struct bgp_node *rn2;
|
|
|
|
struct prefix p1;
|
|
|
|
struct prefix p2;
|
|
|
|
struct in_addr addr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = inet_aton (peer, &addr);
|
|
|
|
if (! ret)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
memset (&p1, 0, sizeof (struct prefix));
|
|
|
|
p1.family = AF_INET;
|
|
|
|
p1.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
p1.u.prefix4 = nexthop;
|
|
|
|
memset (&p2, 0, sizeof (struct prefix));
|
|
|
|
p2.family = AF_INET;
|
|
|
|
p2.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
p2.u.prefix4 = addr;
|
|
|
|
|
|
|
|
/* If bgp scan is not enabled, return invalid. */
|
|
|
|
if (zlookup->sock < 0)
|
|
|
|
return 0;
|
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (! rn1)
|
|
|
|
return 0;
|
2010-07-27 18:28:55 +02:00
|
|
|
bgp_unlock_node (rn1);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-11-09 02:54:03 +01:00
|
|
|
rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
|
2002-12-13 21:15:29 +01:00
|
|
|
if (! rn2)
|
|
|
|
return 0;
|
2010-07-27 18:28:55 +02:00
|
|
|
bgp_unlock_node (rn2);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2010-07-27 18:28:55 +02:00
|
|
|
/* This is safe, even with above unlocks, since we are just
|
|
|
|
comparing pointers to the objects, not the objects themselves. */
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn1 == rn2)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (bgp_scan_time,
|
|
|
|
bgp_scan_time_cmd,
|
|
|
|
"bgp scan-time <5-60>",
|
|
|
|
"BGP specific commands\n"
|
|
|
|
"Configure background scanner interval\n"
|
|
|
|
"Scanner interval (seconds)\n")
|
|
|
|
{
|
|
|
|
bgp_scan_interval = atoi (argv[0]);
|
|
|
|
|
|
|
|
if (bgp_scan_thread)
|
|
|
|
{
|
|
|
|
thread_cancel (bgp_scan_thread);
|
|
|
|
bgp_scan_thread =
|
2004-11-09 02:54:03 +01:00
|
|
|
thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_bgp_scan_time,
|
|
|
|
no_bgp_scan_time_cmd,
|
|
|
|
"no bgp scan-time",
|
|
|
|
NO_STR
|
|
|
|
"BGP specific commands\n"
|
|
|
|
"Configure background scanner interval\n")
|
|
|
|
{
|
|
|
|
bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
|
|
|
|
|
|
|
|
if (bgp_scan_thread)
|
|
|
|
{
|
|
|
|
thread_cancel (bgp_scan_thread);
|
|
|
|
bgp_scan_thread =
|
2004-11-09 02:54:03 +01:00
|
|
|
thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
ALIAS (no_bgp_scan_time,
|
|
|
|
no_bgp_scan_time_val_cmd,
|
|
|
|
"no bgp scan-time <5-60>",
|
|
|
|
NO_STR
|
|
|
|
"BGP specific commands\n"
|
|
|
|
"Configure background scanner interval\n"
|
|
|
|
"Scanner interval (seconds)\n")
|
|
|
|
|
2011-08-05 19:47:08 +02:00
|
|
|
static int
|
|
|
|
show_ip_bgp_scan_tables (struct vty *vty, const char detail)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
2011-08-05 19:47:08 +02:00
|
|
|
char buf[INET6_ADDRSTRLEN];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (bgp_scan_thread)
|
|
|
|
vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
|
|
|
|
else
|
|
|
|
vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
|
|
|
|
vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
#if BGP_SCAN_NEXTHOP
|
2002-12-13 21:15:29 +01:00
|
|
|
vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
|
2004-11-09 02:54:03 +01:00
|
|
|
for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
|
2002-12-13 21:15:29 +01:00
|
|
|
if ((bnc = rn->info) != NULL)
|
|
|
|
{
|
|
|
|
if (bnc->valid)
|
2011-08-05 19:47:08 +02:00
|
|
|
{
|
2002-12-13 21:15:29 +01:00
|
|
|
vty_out (vty, " %s valid [IGP metric %d]%s",
|
2011-08-05 19:47:08 +02:00
|
|
|
inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
|
|
|
|
if (detail)
|
|
|
|
for (i = 0; i < bnc->nexthop_num; i++)
|
2011-08-09 12:42:58 +02:00
|
|
|
switch (bnc->nexthop[i].type)
|
|
|
|
{
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
|
|
|
break;
|
2013-05-25 16:01:35 +02:00
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
|
|
|
vty_out (vty, " gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN));
|
|
|
|
vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
|
|
|
|
break;
|
2011-08-09 12:42:58 +02:00
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
|
|
|
|
}
|
2011-08-05 19:47:08 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
|
|
|
vty_out (vty, " %s invalid%s",
|
2011-08-05 19:47:08 +02:00
|
|
|
inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
{
|
2004-11-09 02:54:03 +01:00
|
|
|
for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
|
|
|
|
rn;
|
|
|
|
rn = bgp_route_next (rn))
|
2002-12-13 21:15:29 +01:00
|
|
|
if ((bnc = rn->info) != NULL)
|
|
|
|
{
|
|
|
|
if (bnc->valid)
|
2011-08-05 19:47:08 +02:00
|
|
|
{
|
2002-12-13 21:15:29 +01:00
|
|
|
vty_out (vty, " %s valid [IGP metric %d]%s",
|
2011-08-05 19:47:08 +02:00
|
|
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
2002-12-13 21:15:29 +01:00
|
|
|
bnc->metric, VTY_NEWLINE);
|
2011-08-05 19:47:08 +02:00
|
|
|
if (detail)
|
|
|
|
for (i = 0; i < bnc->nexthop_num; i++)
|
2011-08-09 12:42:58 +02:00
|
|
|
switch (bnc->nexthop[i].type)
|
|
|
|
{
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
|
|
|
|
}
|
2011-08-05 19:47:08 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
|
|
|
vty_out (vty, " %s invalid%s",
|
2011-08-05 19:47:08 +02:00
|
|
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
2002-12-13 21:15:29 +01:00
|
|
|
VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
2015-05-20 02:40:34 +02:00
|
|
|
#else
|
|
|
|
vty_out (vty, "BGP next-hop tracking is on%s", VTY_NEWLINE);
|
|
|
|
#endif
|
2002-12-13 21:15:29 +01:00
|
|
|
vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
|
2004-11-09 02:54:03 +01:00
|
|
|
for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
|
|
|
|
rn;
|
|
|
|
rn = bgp_route_next (rn))
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn->info != NULL)
|
|
|
|
vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
|
|
|
|
VTY_NEWLINE);
|
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
{
|
2004-11-09 02:54:03 +01:00
|
|
|
for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
|
|
|
|
rn;
|
|
|
|
rn = bgp_route_next (rn))
|
2002-12-13 21:15:29 +01:00
|
|
|
if (rn->info != NULL)
|
|
|
|
vty_out (vty, " %s/%d%s",
|
2011-08-05 19:47:08 +02:00
|
|
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
2002-12-13 21:15:29 +01:00
|
|
|
rn->p.prefixlen,
|
|
|
|
VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
static int
|
|
|
|
show_ip_bgp_nexthop_table (struct vty *vty, int detail)
|
|
|
|
{
|
|
|
|
struct bgp_node *rn;
|
|
|
|
struct bgp_nexthop_cache *bnc;
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
time_t tbuf;
|
|
|
|
u_char i;
|
|
|
|
|
|
|
|
vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
|
|
|
|
for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
|
|
|
|
if ((bnc = rn->info) != NULL)
|
|
|
|
{
|
|
|
|
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
|
|
|
|
{
|
|
|
|
vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
|
|
|
|
inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
|
|
|
|
bnc->metric, bnc->path_count, VTY_NEWLINE);
|
|
|
|
if (detail)
|
|
|
|
for (i = 0; i < bnc->nexthop_num; i++)
|
|
|
|
switch (bnc->nexthop[i].type)
|
|
|
|
{
|
|
|
|
case NEXTHOP_TYPE_IPV4:
|
|
|
|
vty_out (vty, " gate %s%s",
|
|
|
|
inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf,
|
|
|
|
INET6_ADDRSTRLEN), VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
vty_out (vty, " if %s%s",
|
|
|
|
ifindex2ifname(bnc->nexthop[i].ifindex), VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
|
|
|
vty_out (vty, " gate %s, if %s%s",
|
|
|
|
inet_ntop(AF_INET, &bnc->nexthop[i].gate.ipv4, buf,
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
ifindex2ifname(bnc->nexthop[i].ifindex), VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vty_out (vty, " invalid nexthop type %u%s",
|
|
|
|
bnc->nexthop[i].type, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vty_out (vty, " %s invalid%s",
|
|
|
|
inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
|
|
|
#ifdef HAVE_CLOCK_MONOTONIC
|
|
|
|
tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
|
|
|
|
vty_out (vty, " Last update: %s", ctime(&tbuf));
|
|
|
|
#else
|
|
|
|
vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
|
|
|
|
#endif /* HAVE_CLOCK_MONOTONIC */
|
|
|
|
|
|
|
|
vty_out(vty, "%s", VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
{
|
|
|
|
for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
|
|
|
|
rn;
|
|
|
|
rn = bgp_route_next (rn))
|
|
|
|
if ((bnc = rn->info) != NULL)
|
|
|
|
{
|
|
|
|
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
|
|
|
|
{
|
|
|
|
vty_out (vty, " %s valid [IGP metric %d]%s",
|
|
|
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
bnc->metric, VTY_NEWLINE);
|
|
|
|
if (detail)
|
|
|
|
for (i = 0; i < bnc->nexthop_num; i++)
|
|
|
|
switch (bnc->nexthop[i].type)
|
|
|
|
{
|
|
|
|
case NEXTHOP_TYPE_IPV6:
|
|
|
|
vty_out (vty, " gate %s%s",
|
|
|
|
inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6,
|
|
|
|
buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
|
|
|
vty_out(vty, " gate %s, if %s%s",
|
|
|
|
inet_ntop(AF_INET6, &bnc->nexthop[i].gate.ipv6, buf,
|
|
|
|
INET6_ADDRSTRLEN),
|
|
|
|
ifindex2ifname(bnc->nexthop[i].ifindex),
|
|
|
|
VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
case NEXTHOP_TYPE_IFINDEX:
|
|
|
|
vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex,
|
|
|
|
VTY_NEWLINE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vty_out (vty, " invalid nexthop type %u%s",
|
|
|
|
bnc->nexthop[i].type, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vty_out (vty, " %s invalid%s",
|
|
|
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
|
|
|
VTY_NEWLINE);
|
|
|
|
#ifdef HAVE_CLOCK_MONOTONIC
|
|
|
|
tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
|
|
|
|
vty_out (vty, " Last update: %s", ctime(&tbuf));
|
|
|
|
#else
|
|
|
|
vty_out (vty, " Last update: %s", ctime(&bnc->uptime));
|
|
|
|
#endif /* HAVE_CLOCK_MONOTONIC */
|
|
|
|
|
|
|
|
vty_out(vty, "%s", VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-08-05 19:47:08 +02:00
|
|
|
DEFUN (show_ip_bgp_scan,
|
|
|
|
show_ip_bgp_scan_cmd,
|
|
|
|
"show ip bgp scan",
|
|
|
|
SHOW_STR
|
|
|
|
IP_STR
|
|
|
|
BGP_STR
|
|
|
|
"BGP scan status\n")
|
|
|
|
{
|
|
|
|
return show_ip_bgp_scan_tables (vty, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (show_ip_bgp_scan_detail,
|
|
|
|
show_ip_bgp_scan_detail_cmd,
|
|
|
|
"show ip bgp scan detail",
|
|
|
|
SHOW_STR
|
|
|
|
IP_STR
|
|
|
|
BGP_STR
|
|
|
|
"BGP scan status\n"
|
|
|
|
"More detailed output\n")
|
|
|
|
{
|
|
|
|
return show_ip_bgp_scan_tables (vty, 1);
|
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:34 +02:00
|
|
|
DEFUN (show_ip_bgp_nexthop,
|
|
|
|
show_ip_bgp_nexthop_cmd,
|
|
|
|
"show ip bgp nexthop",
|
|
|
|
SHOW_STR
|
|
|
|
IP_STR
|
|
|
|
BGP_STR
|
|
|
|
"BGP nexthop table\n")
|
|
|
|
{
|
|
|
|
return show_ip_bgp_nexthop_table (vty, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (show_ip_bgp_nexthop_detail,
|
|
|
|
show_ip_bgp_nexthop_detail_cmd,
|
|
|
|
"show ip bgp nexthop detail",
|
|
|
|
SHOW_STR
|
|
|
|
IP_STR
|
|
|
|
BGP_STR
|
|
|
|
"BGP nexthop table\n")
|
|
|
|
{
|
|
|
|
return show_ip_bgp_nexthop_table (vty, 1);
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
int
|
|
|
|
bgp_config_write_scan_time (struct vty *vty)
|
|
|
|
{
|
|
|
|
if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
|
|
|
|
vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-02-09 19:14:16 +01:00
|
|
|
bgp_scan_init (void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
zlookup = zclient_new ();
|
|
|
|
zlookup->sock = -1;
|
|
|
|
zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
|
|
|
|
|
|
|
|
bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
|
|
|
|
bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
|
|
|
|
|
2006-02-21 02:09:01 +01:00
|
|
|
cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
|
|
|
|
cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2006-02-21 02:09:01 +01:00
|
|
|
bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
2006-02-21 02:09:01 +01:00
|
|
|
cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
|
|
|
|
cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
|
2006-02-21 02:09:01 +01:00
|
|
|
bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
|
2002-12-13 21:15:29 +01:00
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
|
|
/* Make BGP scan thread. */
|
2004-11-09 02:54:03 +01:00
|
|
|
bgp_scan_thread = thread_add_timer (master, bgp_scan_timer,
|
|
|
|
NULL, bgp_scan_interval);
|
2003-04-28 19:11:02 +02:00
|
|
|
/* Make BGP import there. */
|
|
|
|
bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
install_element (BGP_NODE, &bgp_scan_time_cmd);
|
|
|
|
install_element (BGP_NODE, &no_bgp_scan_time_cmd);
|
|
|
|
install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
|
|
|
|
install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
|
2011-08-05 19:47:08 +02:00
|
|
|
install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
|
2015-05-20 02:40:34 +02:00
|
|
|
install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
|
|
|
|
install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
|
2008-08-23 15:27:06 +02:00
|
|
|
install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
|
2002-12-13 21:15:29 +01:00
|
|
|
install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
|
2015-05-20 02:40:34 +02:00
|
|
|
install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
|
|
|
|
install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
|
2011-08-05 19:47:08 +02:00
|
|
|
install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
[bgpd] Stability fixes including bugs 397, 492
I've spent the last several weeks working on stability fixes to bgpd.
These patches fix all of the numerous crashes, assertion failures, memory
leaks and memory stomping I could find. Valgrind was used extensively.
Added new function bgp_exit() to help catch problems. If "debug bgp" is
configured and bgpd exits with status of 0, statistics on remaining
lib/memory.c allocations are printed to stderr. It is my hope that other
developers will use this to stay on top of memory issues.
Example questionable exit:
bgpd: memstats: Current memory utilization in module LIB:
bgpd: memstats: Link List : 6
bgpd: memstats: Link Node : 5
bgpd: memstats: Hash : 8
bgpd: memstats: Hash Bucket : 2
bgpd: memstats: Hash Index : 8
bgpd: memstats: Work queue : 3
bgpd: memstats: Work queue item : 2
bgpd: memstats: Work queue name string : 3
bgpd: memstats: Current memory utilization in module BGP:
bgpd: memstats: BGP instance : 1
bgpd: memstats: BGP peer : 1
bgpd: memstats: BGP peer hostname : 1
bgpd: memstats: BGP attribute : 1
bgpd: memstats: BGP extra attributes : 1
bgpd: memstats: BGP aspath : 1
bgpd: memstats: BGP aspath str : 1
bgpd: memstats: BGP table : 24
bgpd: memstats: BGP node : 1
bgpd: memstats: BGP route : 1
bgpd: memstats: BGP synchronise : 8
bgpd: memstats: BGP Process queue : 1
bgpd: memstats: BGP node clear queue : 1
bgpd: memstats: NOTE: If configuration exists, utilization may be expected.
Example clean exit:
bgpd: memstats: No remaining tracked memory utilization.
This patch fixes bug #397: "Invalid free in bgp_announce_check()".
This patch fixes bug #492: "SIGBUS in bgpd/bgp_route.c:
bgp_clear_route_node()".
My apologies for not separating out these changes into individual patches.
The complexity of doing so boggled what is left of my brain. I hope this
is all still useful to the community.
This code has been production tested, in non-route-server-client mode, on
a linux 32-bit box and a 64-bit box.
Release/reset functions, used by bgp_exit(), added to:
bgpd/bgp_attr.c,h
bgpd/bgp_community.c,h
bgpd/bgp_dump.c,h
bgpd/bgp_ecommunity.c,h
bgpd/bgp_filter.c,h
bgpd/bgp_nexthop.c,h
bgpd/bgp_route.c,h
lib/routemap.c,h
File by file analysis:
* bgpd/bgp_aspath.c: Prevent re-use of ashash after it is released.
* bgpd/bgp_attr.c: #if removed uncalled cluster_dup().
* bgpd/bgp_clist.c,h: Allow community_list_terminate() to be called from
bgp_exit().
* bgpd/bgp_filter.c: Fix aslist->name use without allocation check, and
also fix memory leak.
* bgpd/bgp_main.c: Created bgp_exit() exit routine. This function frees
allocations made as part of bgpd initialization and, to some extent,
configuration. If "debug bgp" is configured, memory stats are printed
as described above.
* bgpd/bgp_nexthop.c: zclient_new() already allocates stream for
ibuf/obuf, so bgp_scan_init() shouldn't do it too. Also, made it so
zlookup is global so bgp_exit() can use it.
* bgpd/bgp_packet.c: bgp_capability_msg_parse() call to bgp_clear_route()
adjusted to use new BGP_CLEAR_ROUTE_NORMAL flag.
* bgpd/bgp_route.h: Correct reference counter "lock" to be signed.
bgp_clear_route() now accepts a bgp_clear_route_type of either
BGP_CLEAR_ROUTE_NORMAL or BGP_CLEAR_ROUTE_MY_RSCLIENT.
* bgpd/bgp_route.c:
- bgp_process_rsclient(): attr was being zero'ed and then
bgp_attr_extra_free() was being called with it, even though it was
never filled with valid data.
- bgp_process_rsclient(): Make sure rsclient->group is not NULL before
use.
- bgp_processq_del(): Add call to bgp_table_unlock().
- bgp_process(): Add call to bgp_table_lock().
- bgp_update_rsclient(): memset clearing of new_attr not needed since
declarationw with "= { 0 }" does it. memset was already commented
out.
- bgp_update_rsclient(): Fix screwed up misleading indentation.
- bgp_withdraw_rsclient(): Fix screwed up misleading indentation.
- bgp_clear_route_node(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_node_queue_del(): Add call to bgp_table_unlock() and also
free struct bgp_clear_node_queue used for work item.
- bgp_clear_node_complete(): Do peer_unlock() after BGP_EVENT_ADD() in
case peer is released by peer_unlock() call.
- bgp_clear_route_table(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT. Use
struct bgp_clear_node_queue to supply data to worker. Add call to
bgp_table_lock().
- bgp_clear_route(): Add support for BGP_CLEAR_ROUTE_NORMAL or
BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_route_all(): Use BGP_CLEAR_ROUTE_NORMAL.
Bug 397 fixes:
- bgp_default_originate()
- bgp_announce_table()
* bgpd/bgp_table.h:
- struct bgp_table: Added reference count. Changed type of owner to be
"struct peer *" rather than "void *".
- struct bgp_node: Correct reference counter "lock" to be signed.
* bgpd/bgp_table.c:
- Added bgp_table reference counting.
- bgp_table_free(): Fixed cleanup code. Call peer_unlock() on owner if
set.
- bgp_unlock_node(): Added assertion.
- bgp_node_get(): Added call to bgp_lock_node() to code path that it was
missing from.
* bgpd/bgp_vty.c:
- peer_rsclient_set_vty(): Call peer_lock() as part of peer assignment
to owner. Handle failure gracefully.
- peer_rsclient_unset_vty(): Add call to bgp_clear_route() with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
* bgpd/bgp_zebra.c: Made it so zclient is global so bgp_exit() can use it.
* bgpd/bgpd.c:
- peer_lock(): Allow to be called when status is "Deleted".
- peer_deactivate(): Supply BGP_CLEAR_ROUTE_NORMAL purpose to
bgp_clear_route() call.
- peer_delete(): Common variable listnode pn. Fix bug in which rsclient
was only dealt with if not part of a peer group. Call
bgp_clear_route() for rsclient, if appropriate, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- peer_group_get(): Use XSTRDUP() instead of strdup() for conf->host.
- peer_group_bind(): Call bgp_clear_route() for rsclient, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- bgp_create(): Use XSTRDUP() instead of strdup() for peer_self->host.
- bgp_delete(): Delete peers before groups, rather than after. And then
rather than deleting rsclients, verify that there are none at this
point.
- bgp_unlock(): Add assertion.
- bgp_free(): Call bgp_table_finish() rather than doing XFREE() itself.
* lib/command.c,h: Compiler warning fixes. Add cmd_terminate(). Fixed
massive leak in install_element() in which cmd_make_descvec() was being
called more than once for the same cmd->strvec/string/doc.
* lib/log.c: Make closezlog() check fp before calling fclose().
* lib/memory.c: Catch when alloc count goes negative by using signed
counts. Correct #endif comment. Add log_memstats_stderr().
* lib/memory.h: Add log_memstats_stderr().
* lib/thread.c: thread->funcname was being accessed in thread_call() after
it had been freed. Rearranged things so that thread_call() frees
funcname. Also made it so thread_master_free() cleans up cpu_record.
* lib/vty.c,h: Use global command_cr. Add vty_terminate().
* lib/zclient.c,h: Re-enable zclient_free().
2009-07-18 07:44:03 +02:00
|
|
|
|
|
|
|
void
|
|
|
|
bgp_scan_finish (void)
|
|
|
|
{
|
2010-07-27 18:28:55 +02:00
|
|
|
/* Only the current one needs to be reset. */
|
|
|
|
bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
|
|
|
|
|
[bgpd] Stability fixes including bugs 397, 492
I've spent the last several weeks working on stability fixes to bgpd.
These patches fix all of the numerous crashes, assertion failures, memory
leaks and memory stomping I could find. Valgrind was used extensively.
Added new function bgp_exit() to help catch problems. If "debug bgp" is
configured and bgpd exits with status of 0, statistics on remaining
lib/memory.c allocations are printed to stderr. It is my hope that other
developers will use this to stay on top of memory issues.
Example questionable exit:
bgpd: memstats: Current memory utilization in module LIB:
bgpd: memstats: Link List : 6
bgpd: memstats: Link Node : 5
bgpd: memstats: Hash : 8
bgpd: memstats: Hash Bucket : 2
bgpd: memstats: Hash Index : 8
bgpd: memstats: Work queue : 3
bgpd: memstats: Work queue item : 2
bgpd: memstats: Work queue name string : 3
bgpd: memstats: Current memory utilization in module BGP:
bgpd: memstats: BGP instance : 1
bgpd: memstats: BGP peer : 1
bgpd: memstats: BGP peer hostname : 1
bgpd: memstats: BGP attribute : 1
bgpd: memstats: BGP extra attributes : 1
bgpd: memstats: BGP aspath : 1
bgpd: memstats: BGP aspath str : 1
bgpd: memstats: BGP table : 24
bgpd: memstats: BGP node : 1
bgpd: memstats: BGP route : 1
bgpd: memstats: BGP synchronise : 8
bgpd: memstats: BGP Process queue : 1
bgpd: memstats: BGP node clear queue : 1
bgpd: memstats: NOTE: If configuration exists, utilization may be expected.
Example clean exit:
bgpd: memstats: No remaining tracked memory utilization.
This patch fixes bug #397: "Invalid free in bgp_announce_check()".
This patch fixes bug #492: "SIGBUS in bgpd/bgp_route.c:
bgp_clear_route_node()".
My apologies for not separating out these changes into individual patches.
The complexity of doing so boggled what is left of my brain. I hope this
is all still useful to the community.
This code has been production tested, in non-route-server-client mode, on
a linux 32-bit box and a 64-bit box.
Release/reset functions, used by bgp_exit(), added to:
bgpd/bgp_attr.c,h
bgpd/bgp_community.c,h
bgpd/bgp_dump.c,h
bgpd/bgp_ecommunity.c,h
bgpd/bgp_filter.c,h
bgpd/bgp_nexthop.c,h
bgpd/bgp_route.c,h
lib/routemap.c,h
File by file analysis:
* bgpd/bgp_aspath.c: Prevent re-use of ashash after it is released.
* bgpd/bgp_attr.c: #if removed uncalled cluster_dup().
* bgpd/bgp_clist.c,h: Allow community_list_terminate() to be called from
bgp_exit().
* bgpd/bgp_filter.c: Fix aslist->name use without allocation check, and
also fix memory leak.
* bgpd/bgp_main.c: Created bgp_exit() exit routine. This function frees
allocations made as part of bgpd initialization and, to some extent,
configuration. If "debug bgp" is configured, memory stats are printed
as described above.
* bgpd/bgp_nexthop.c: zclient_new() already allocates stream for
ibuf/obuf, so bgp_scan_init() shouldn't do it too. Also, made it so
zlookup is global so bgp_exit() can use it.
* bgpd/bgp_packet.c: bgp_capability_msg_parse() call to bgp_clear_route()
adjusted to use new BGP_CLEAR_ROUTE_NORMAL flag.
* bgpd/bgp_route.h: Correct reference counter "lock" to be signed.
bgp_clear_route() now accepts a bgp_clear_route_type of either
BGP_CLEAR_ROUTE_NORMAL or BGP_CLEAR_ROUTE_MY_RSCLIENT.
* bgpd/bgp_route.c:
- bgp_process_rsclient(): attr was being zero'ed and then
bgp_attr_extra_free() was being called with it, even though it was
never filled with valid data.
- bgp_process_rsclient(): Make sure rsclient->group is not NULL before
use.
- bgp_processq_del(): Add call to bgp_table_unlock().
- bgp_process(): Add call to bgp_table_lock().
- bgp_update_rsclient(): memset clearing of new_attr not needed since
declarationw with "= { 0 }" does it. memset was already commented
out.
- bgp_update_rsclient(): Fix screwed up misleading indentation.
- bgp_withdraw_rsclient(): Fix screwed up misleading indentation.
- bgp_clear_route_node(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_node_queue_del(): Add call to bgp_table_unlock() and also
free struct bgp_clear_node_queue used for work item.
- bgp_clear_node_complete(): Do peer_unlock() after BGP_EVENT_ADD() in
case peer is released by peer_unlock() call.
- bgp_clear_route_table(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT. Use
struct bgp_clear_node_queue to supply data to worker. Add call to
bgp_table_lock().
- bgp_clear_route(): Add support for BGP_CLEAR_ROUTE_NORMAL or
BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_route_all(): Use BGP_CLEAR_ROUTE_NORMAL.
Bug 397 fixes:
- bgp_default_originate()
- bgp_announce_table()
* bgpd/bgp_table.h:
- struct bgp_table: Added reference count. Changed type of owner to be
"struct peer *" rather than "void *".
- struct bgp_node: Correct reference counter "lock" to be signed.
* bgpd/bgp_table.c:
- Added bgp_table reference counting.
- bgp_table_free(): Fixed cleanup code. Call peer_unlock() on owner if
set.
- bgp_unlock_node(): Added assertion.
- bgp_node_get(): Added call to bgp_lock_node() to code path that it was
missing from.
* bgpd/bgp_vty.c:
- peer_rsclient_set_vty(): Call peer_lock() as part of peer assignment
to owner. Handle failure gracefully.
- peer_rsclient_unset_vty(): Add call to bgp_clear_route() with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
* bgpd/bgp_zebra.c: Made it so zclient is global so bgp_exit() can use it.
* bgpd/bgpd.c:
- peer_lock(): Allow to be called when status is "Deleted".
- peer_deactivate(): Supply BGP_CLEAR_ROUTE_NORMAL purpose to
bgp_clear_route() call.
- peer_delete(): Common variable listnode pn. Fix bug in which rsclient
was only dealt with if not part of a peer group. Call
bgp_clear_route() for rsclient, if appropriate, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- peer_group_get(): Use XSTRDUP() instead of strdup() for conf->host.
- peer_group_bind(): Call bgp_clear_route() for rsclient, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- bgp_create(): Use XSTRDUP() instead of strdup() for peer_self->host.
- bgp_delete(): Delete peers before groups, rather than after. And then
rather than deleting rsclients, verify that there are none at this
point.
- bgp_unlock(): Add assertion.
- bgp_free(): Call bgp_table_finish() rather than doing XFREE() itself.
* lib/command.c,h: Compiler warning fixes. Add cmd_terminate(). Fixed
massive leak in install_element() in which cmd_make_descvec() was being
called more than once for the same cmd->strvec/string/doc.
* lib/log.c: Make closezlog() check fp before calling fclose().
* lib/memory.c: Catch when alloc count goes negative by using signed
counts. Correct #endif comment. Add log_memstats_stderr().
* lib/memory.h: Add log_memstats_stderr().
* lib/thread.c: thread->funcname was being accessed in thread_call() after
it had been freed. Rearranged things so that thread_call() frees
funcname. Also made it so thread_master_free() cleans up cpu_record.
* lib/vty.c,h: Use global command_cr. Add vty_terminate().
* lib/zclient.c,h: Re-enable zclient_free().
2009-07-18 07:44:03 +02:00
|
|
|
bgp_table_unlock (cache1_table[AFI_IP]);
|
|
|
|
cache1_table[AFI_IP] = NULL;
|
|
|
|
|
|
|
|
bgp_table_unlock (cache2_table[AFI_IP]);
|
|
|
|
cache2_table[AFI_IP] = NULL;
|
|
|
|
|
|
|
|
bgp_table_unlock (bgp_connected_table[AFI_IP]);
|
|
|
|
bgp_connected_table[AFI_IP] = NULL;
|
|
|
|
|
|
|
|
#ifdef HAVE_IPV6
|
2010-07-27 18:28:55 +02:00
|
|
|
/* Only the current one needs to be reset. */
|
|
|
|
bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
|
|
|
|
|
[bgpd] Stability fixes including bugs 397, 492
I've spent the last several weeks working on stability fixes to bgpd.
These patches fix all of the numerous crashes, assertion failures, memory
leaks and memory stomping I could find. Valgrind was used extensively.
Added new function bgp_exit() to help catch problems. If "debug bgp" is
configured and bgpd exits with status of 0, statistics on remaining
lib/memory.c allocations are printed to stderr. It is my hope that other
developers will use this to stay on top of memory issues.
Example questionable exit:
bgpd: memstats: Current memory utilization in module LIB:
bgpd: memstats: Link List : 6
bgpd: memstats: Link Node : 5
bgpd: memstats: Hash : 8
bgpd: memstats: Hash Bucket : 2
bgpd: memstats: Hash Index : 8
bgpd: memstats: Work queue : 3
bgpd: memstats: Work queue item : 2
bgpd: memstats: Work queue name string : 3
bgpd: memstats: Current memory utilization in module BGP:
bgpd: memstats: BGP instance : 1
bgpd: memstats: BGP peer : 1
bgpd: memstats: BGP peer hostname : 1
bgpd: memstats: BGP attribute : 1
bgpd: memstats: BGP extra attributes : 1
bgpd: memstats: BGP aspath : 1
bgpd: memstats: BGP aspath str : 1
bgpd: memstats: BGP table : 24
bgpd: memstats: BGP node : 1
bgpd: memstats: BGP route : 1
bgpd: memstats: BGP synchronise : 8
bgpd: memstats: BGP Process queue : 1
bgpd: memstats: BGP node clear queue : 1
bgpd: memstats: NOTE: If configuration exists, utilization may be expected.
Example clean exit:
bgpd: memstats: No remaining tracked memory utilization.
This patch fixes bug #397: "Invalid free in bgp_announce_check()".
This patch fixes bug #492: "SIGBUS in bgpd/bgp_route.c:
bgp_clear_route_node()".
My apologies for not separating out these changes into individual patches.
The complexity of doing so boggled what is left of my brain. I hope this
is all still useful to the community.
This code has been production tested, in non-route-server-client mode, on
a linux 32-bit box and a 64-bit box.
Release/reset functions, used by bgp_exit(), added to:
bgpd/bgp_attr.c,h
bgpd/bgp_community.c,h
bgpd/bgp_dump.c,h
bgpd/bgp_ecommunity.c,h
bgpd/bgp_filter.c,h
bgpd/bgp_nexthop.c,h
bgpd/bgp_route.c,h
lib/routemap.c,h
File by file analysis:
* bgpd/bgp_aspath.c: Prevent re-use of ashash after it is released.
* bgpd/bgp_attr.c: #if removed uncalled cluster_dup().
* bgpd/bgp_clist.c,h: Allow community_list_terminate() to be called from
bgp_exit().
* bgpd/bgp_filter.c: Fix aslist->name use without allocation check, and
also fix memory leak.
* bgpd/bgp_main.c: Created bgp_exit() exit routine. This function frees
allocations made as part of bgpd initialization and, to some extent,
configuration. If "debug bgp" is configured, memory stats are printed
as described above.
* bgpd/bgp_nexthop.c: zclient_new() already allocates stream for
ibuf/obuf, so bgp_scan_init() shouldn't do it too. Also, made it so
zlookup is global so bgp_exit() can use it.
* bgpd/bgp_packet.c: bgp_capability_msg_parse() call to bgp_clear_route()
adjusted to use new BGP_CLEAR_ROUTE_NORMAL flag.
* bgpd/bgp_route.h: Correct reference counter "lock" to be signed.
bgp_clear_route() now accepts a bgp_clear_route_type of either
BGP_CLEAR_ROUTE_NORMAL or BGP_CLEAR_ROUTE_MY_RSCLIENT.
* bgpd/bgp_route.c:
- bgp_process_rsclient(): attr was being zero'ed and then
bgp_attr_extra_free() was being called with it, even though it was
never filled with valid data.
- bgp_process_rsclient(): Make sure rsclient->group is not NULL before
use.
- bgp_processq_del(): Add call to bgp_table_unlock().
- bgp_process(): Add call to bgp_table_lock().
- bgp_update_rsclient(): memset clearing of new_attr not needed since
declarationw with "= { 0 }" does it. memset was already commented
out.
- bgp_update_rsclient(): Fix screwed up misleading indentation.
- bgp_withdraw_rsclient(): Fix screwed up misleading indentation.
- bgp_clear_route_node(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_node_queue_del(): Add call to bgp_table_unlock() and also
free struct bgp_clear_node_queue used for work item.
- bgp_clear_node_complete(): Do peer_unlock() after BGP_EVENT_ADD() in
case peer is released by peer_unlock() call.
- bgp_clear_route_table(): Support BGP_CLEAR_ROUTE_MY_RSCLIENT. Use
struct bgp_clear_node_queue to supply data to worker. Add call to
bgp_table_lock().
- bgp_clear_route(): Add support for BGP_CLEAR_ROUTE_NORMAL or
BGP_CLEAR_ROUTE_MY_RSCLIENT.
- bgp_clear_route_all(): Use BGP_CLEAR_ROUTE_NORMAL.
Bug 397 fixes:
- bgp_default_originate()
- bgp_announce_table()
* bgpd/bgp_table.h:
- struct bgp_table: Added reference count. Changed type of owner to be
"struct peer *" rather than "void *".
- struct bgp_node: Correct reference counter "lock" to be signed.
* bgpd/bgp_table.c:
- Added bgp_table reference counting.
- bgp_table_free(): Fixed cleanup code. Call peer_unlock() on owner if
set.
- bgp_unlock_node(): Added assertion.
- bgp_node_get(): Added call to bgp_lock_node() to code path that it was
missing from.
* bgpd/bgp_vty.c:
- peer_rsclient_set_vty(): Call peer_lock() as part of peer assignment
to owner. Handle failure gracefully.
- peer_rsclient_unset_vty(): Add call to bgp_clear_route() with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
* bgpd/bgp_zebra.c: Made it so zclient is global so bgp_exit() can use it.
* bgpd/bgpd.c:
- peer_lock(): Allow to be called when status is "Deleted".
- peer_deactivate(): Supply BGP_CLEAR_ROUTE_NORMAL purpose to
bgp_clear_route() call.
- peer_delete(): Common variable listnode pn. Fix bug in which rsclient
was only dealt with if not part of a peer group. Call
bgp_clear_route() for rsclient, if appropriate, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- peer_group_get(): Use XSTRDUP() instead of strdup() for conf->host.
- peer_group_bind(): Call bgp_clear_route() for rsclient, and do so with
BGP_CLEAR_ROUTE_MY_RSCLIENT purpose.
- bgp_create(): Use XSTRDUP() instead of strdup() for peer_self->host.
- bgp_delete(): Delete peers before groups, rather than after. And then
rather than deleting rsclients, verify that there are none at this
point.
- bgp_unlock(): Add assertion.
- bgp_free(): Call bgp_table_finish() rather than doing XFREE() itself.
* lib/command.c,h: Compiler warning fixes. Add cmd_terminate(). Fixed
massive leak in install_element() in which cmd_make_descvec() was being
called more than once for the same cmd->strvec/string/doc.
* lib/log.c: Make closezlog() check fp before calling fclose().
* lib/memory.c: Catch when alloc count goes negative by using signed
counts. Correct #endif comment. Add log_memstats_stderr().
* lib/memory.h: Add log_memstats_stderr().
* lib/thread.c: thread->funcname was being accessed in thread_call() after
it had been freed. Rearranged things so that thread_call() frees
funcname. Also made it so thread_master_free() cleans up cpu_record.
* lib/vty.c,h: Use global command_cr. Add vty_terminate().
* lib/zclient.c,h: Re-enable zclient_free().
2009-07-18 07:44:03 +02:00
|
|
|
bgp_table_unlock (cache1_table[AFI_IP6]);
|
|
|
|
cache1_table[AFI_IP6] = NULL;
|
|
|
|
|
|
|
|
bgp_table_unlock (cache2_table[AFI_IP6]);
|
|
|
|
cache2_table[AFI_IP6] = NULL;
|
|
|
|
|
|
|
|
bgp_table_unlock (bgp_connected_table[AFI_IP6]);
|
|
|
|
bgp_connected_table[AFI_IP6] = NULL;
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
}
|