bgpd-nht-connected-route.patch

BGP: Use next hop tracking for connected routes too

And cleanup obsolete code in bgp_scan and bgp_import.
This commit is contained in:
Donald Sharp 2015-05-19 17:47:21 -07:00
parent 9f0ea7d4f2
commit fc9a856f70
14 changed files with 339 additions and 1168 deletions

View File

@ -1185,6 +1185,7 @@ int
bgp_start (struct peer *peer) bgp_start (struct peer *peer)
{ {
int status; int status;
int connected = 0;
bgp_peer_conf_if_to_su_update(peer); bgp_peer_conf_if_to_su_update(peer);
@ -1225,6 +1226,12 @@ bgp_start (struct peer *peer)
return 0; return 0;
} }
/* Register to be notified on peer up */
if ((peer->ttl == 1) || (peer->gtsm_hops == 1))
connected = 1;
bgp_find_or_add_nexthop(family2afi(peer->su.sa.sa_family), NULL, peer,
connected);
status = bgp_connect (peer); status = bgp_connect (peer);
switch (status) switch (status)
@ -1492,6 +1499,45 @@ bgp_ignore (struct peer *peer)
return 0; return 0;
} }
void
bgp_fsm_nht_update(struct peer *peer, int valid)
{
int ret = 0;
if (!peer)
return;
switch (peer->status)
{
case Idle:
if (valid)
BGP_EVENT_ADD(peer, BGP_Start);
break;
case Connect:
ret = bgp_connect_check(peer, 0);
if (!ret && valid)
{
BGP_TIMER_OFF(peer->t_connect);
BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
}
break;
case Active:
if (valid)
{
BGP_TIMER_OFF(peer->t_connect);
BGP_EVENT_ADD(peer, ConnectRetry_timer_expired);
}
case OpenSent:
case OpenConfirm:
case Established:
case Clearing:
case Deleted:
default:
break;
}
}
/* Finite State Machine structure */ /* Finite State Machine structure */
static const struct { static const struct {
int (*func) (struct peer *); int (*func) (struct peer *);

View File

@ -74,6 +74,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define BGP_MSEC_JITTER 10 #define BGP_MSEC_JITTER 10
/* Prototypes. */ /* Prototypes. */
extern void bgp_fsm_nht_update(struct peer *, int valid);
extern int bgp_event (struct thread *); extern int bgp_event (struct thread *);
extern int bgp_event_update (struct peer *, int event); extern int bgp_event_update (struct peer *, int event);
extern int bgp_stop (struct peer *peer); extern int bgp_stop (struct peer *peer);

View File

@ -227,7 +227,6 @@ bgp_exit (int status)
int *socket; int *socket;
struct interface *ifp; struct interface *ifp;
extern struct zclient *zclient; extern struct zclient *zclient;
extern struct zclient *zlookup;
/* it only makes sense for this to be called on a clean exit */ /* it only makes sense for this to be called on a clean exit */
assert (status == 0); assert (status == 0);
@ -266,9 +265,6 @@ bgp_exit (int status)
/* cleanup route maps */ /* cleanup route maps */
bgp_route_map_terminate(); bgp_route_map_terminate();
/* reverse bgp_scan_init */
bgp_scan_finish ();
/* reverse access_list_init */ /* reverse access_list_init */
access_list_add_hook (NULL); access_list_add_hook (NULL);
access_list_delete_hook (NULL); access_list_delete_hook (NULL);
@ -291,13 +287,14 @@ bgp_exit (int status)
vty_terminate (); vty_terminate ();
if (zclient) if (zclient)
zclient_free (zclient); zclient_free (zclient);
if (zlookup)
zclient_free (zlookup);
if (bgp_nexthop_buf) if (bgp_nexthop_buf)
stream_free (bgp_nexthop_buf); stream_free (bgp_nexthop_buf);
if (bgp_ifindices_buf) if (bgp_ifindices_buf)
stream_free (bgp_ifindices_buf); stream_free (bgp_ifindices_buf);
/* reverse bgp_scan_init */
bgp_scan_finish ();
/* reverse bgp_master_init */ /* reverse bgp_master_init */
if (master) if (master)
thread_master_free (master); thread_master_free (master);

File diff suppressed because it is too large Load Diff

View File

@ -25,21 +25,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "queue.h" #include "queue.h"
#include "prefix.h" #include "prefix.h"
#define BGP_SCAN_INTERVAL_DEFAULT 60
#define BGP_IMPORT_INTERVAL_DEFAULT 15
/* BGP nexthop cache value structure. */ /* BGP nexthop cache value structure. */
struct bgp_nexthop_cache struct bgp_nexthop_cache
{ {
/* This nexthop exists in IGP. */
u_char valid;
/* Nexthop is changed. */
u_char changed;
/* Nexthop is changed. */
u_char metricchanged;
/* IGP route's metric. */ /* IGP route's metric. */
u_int32_t metric; u_int32_t metric;
@ -51,24 +39,26 @@ struct bgp_nexthop_cache
#define BGP_NEXTHOP_VALID (1 << 0) #define BGP_NEXTHOP_VALID (1 << 0)
#define BGP_NEXTHOP_REGISTERED (1 << 1) #define BGP_NEXTHOP_REGISTERED (1 << 1)
#define BGP_NEXTHOP_CONNECTED (1 << 2)
#define BGP_NEXTHOP_PEER_NOTIFIED (1 << 3)
u_int16_t change_flags; u_int16_t change_flags;
#define BGP_NEXTHOP_CHANGED (1 << 0) #define BGP_NEXTHOP_CHANGED (1 << 0)
#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1) #define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
struct bgp_node *node; struct bgp_node *node;
void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_info) paths; LIST_HEAD(path_list, bgp_info) paths;
unsigned int path_count; unsigned int path_count;
}; };
extern void bgp_scan_init (void);
extern void bgp_scan_finish (void);
extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *, extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *,
int *, int *); int *, int *);
extern void bgp_connected_add (struct connected *c); extern void bgp_connected_add (struct connected *c);
extern void bgp_connected_delete (struct connected *c); extern void bgp_connected_delete (struct connected *c);
extern int bgp_multiaccess_check_v4 (struct in_addr, char *); extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *);
extern int bgp_config_write_scan_time (struct vty *); extern int bgp_config_write_scan_time (struct vty *);
extern int bgp_nexthop_onlink (afi_t, struct attr *); extern int bgp_nexthop_onlink (afi_t, struct attr *);
extern int bgp_nexthop_self (struct attr *); extern int bgp_nexthop_self (struct attr *);

View File

@ -50,19 +50,15 @@ static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
int keep); int keep);
int int
bgp_find_nexthop (struct bgp_info *path, int *changed, int *metricchanged) bgp_find_nexthop (struct bgp_info *path, int connected)
{ {
struct bgp_nexthop_cache *bnc = path->nexthop; struct bgp_nexthop_cache *bnc = path->nexthop;
if (!bnc) if (!bnc)
return 0; return 0;
if (changed) if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
*changed = CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED); return 0;
if (metricchanged)
*metricchanged = CHECK_FLAG(bnc->change_flags,
BGP_NEXTHOP_METRIC_CHANGED);
return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)); return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
} }
@ -77,7 +73,7 @@ bgp_unlink_nexthop (struct bgp_info *path)
path_nh_map(path, NULL, 0); path_nh_map(path, NULL, 0);
if (LIST_EMPTY(&(bnc->paths))) if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
{ {
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT))
{ {
@ -93,15 +89,34 @@ bgp_unlink_nexthop (struct bgp_info *path)
} }
int int
bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, int *changed, bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, struct peer *peer,
int *metricchanged) int connected)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_nexthop_cache *bnc; struct bgp_nexthop_cache *bnc;
struct prefix p; struct prefix p;
if (ri)
{
if (make_prefix(afi, ri, &p) < 0) if (make_prefix(afi, ri, &p) < 0)
return 1; return 1;
}
else if (peer)
{
if (afi == AFI_IP)
{
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = peer->su.sin.sin_addr;
}
else if (afi == AFI_IP6)
{
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
p.u.prefix6 = peer->su.sin6.sin6_addr;
}
}
rn = bgp_node_get (bgp_nexthop_cache_table[afi], &p); rn = bgp_node_get (bgp_nexthop_cache_table[afi], &p);
if (!rn->info) if (!rn->info)
@ -110,23 +125,27 @@ bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, int *changed,
rn->info = bnc; rn->info = bnc;
bnc->node = rn; bnc->node = rn;
bgp_lock_node(rn); bgp_lock_node(rn);
register_nexthop(bnc); if (connected)
SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
} }
bnc = rn->info; bnc = rn->info;
bgp_unlock_node (rn); bgp_unlock_node (rn);
if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
register_nexthop(bnc);
if (ri)
{
path_nh_map(ri, bnc, 1); path_nh_map(ri, bnc, 1);
if (changed)
*changed = CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED);
if (metricchanged)
*metricchanged = CHECK_FLAG(bnc->change_flags,
BGP_NEXTHOP_METRIC_CHANGED);
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
(bgp_info_extra_get(ri))->igpmetric = bnc->metric; (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
else if (ri->extra) else if (ri->extra)
ri->extra->igpmetric = 0; ri->extra->igpmetric = 0;
}
else if (peer)
bnc->nht_info = (void *)peer;
return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)); return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
} }
@ -265,6 +284,7 @@ bgp_parse_nexthop_update (void)
else else
{ {
bnc->flags &= ~BGP_NEXTHOP_VALID; bnc->flags &= ~BGP_NEXTHOP_VALID;
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
bnc_nexthop_free(bnc); bnc_nexthop_free(bnc);
bnc->nexthop = NULL; bnc->nexthop = NULL;
} }
@ -322,12 +342,21 @@ sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command)
/* Check socket. */ /* Check socket. */
if (!zclient || zclient->sock < 0) if (!zclient || zclient->sock < 0)
{
zlog_debug("%s: Can't send NH register, Zebra client not established",
__FUNCTION__);
return; return;
}
p = &(bnc->node->p); p = &(bnc->node->p);
s = zclient->obuf; s = zclient->obuf;
stream_reset (s); stream_reset (s);
zclient_create_header (s, command); zclient_create_header (s, command);
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
stream_putc(s, 1);
else
stream_putc(s, 0);
stream_putw(s, PREFIX_FAMILY(p)); stream_putw(s, PREFIX_FAMILY(p));
stream_putc(s, p->prefixlen); stream_putc(s, p->prefixlen);
switch (PREFIX_FAMILY(p)) switch (PREFIX_FAMILY(p))
@ -349,6 +378,11 @@ sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command)
/* TBD: handle the failure */ /* TBD: handle the failure */
if (ret < 0) if (ret < 0)
zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
if (command == ZEBRA_NEXTHOP_REGISTER)
SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
else if (command == ZEBRA_NEXTHOP_UNREGISTER)
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
return; return;
} }
@ -367,7 +401,6 @@ register_nexthop (struct bgp_nexthop_cache *bnc)
if (bnc->flags & BGP_NEXTHOP_REGISTERED) if (bnc->flags & BGP_NEXTHOP_REGISTERED)
return; return;
sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER); sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER);
SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
} }
/** /**
@ -385,7 +418,6 @@ unregister_nexthop (struct bgp_nexthop_cache *bnc)
return; return;
sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER); sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
} }
/** /**
@ -402,6 +434,7 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
struct bgp_info *path; struct bgp_info *path;
struct bgp *bgp = bgp_get_default(); struct bgp *bgp = bgp_get_default();
int afi; int afi;
struct peer *peer = (struct peer *)bnc->nht_info;
LIST_FOREACH(path, &(bnc->paths), nh_thread) LIST_FOREACH(path, &(bnc->paths), nh_thread)
{ {
@ -444,6 +477,15 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
bgp_process(bgp, rn, afi, SAFI_UNICAST); bgp_process(bgp, rn, afi, SAFI_UNICAST);
} }
if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))
{
if (BGP_DEBUG(nht, NHT))
zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host);
bgp_fsm_nht_update(peer, CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
}
RESET_FLAG(bnc->change_flags); RESET_FLAG(bnc->change_flags);
} }

View File

@ -31,12 +31,9 @@ extern void bgp_parse_nexthop_update();
* bgp_find_nexthop() - lookup the nexthop cache table for the bnc object * bgp_find_nexthop() - lookup the nexthop cache table for the bnc object
* ARGUMENTS: * ARGUMENTS:
* p - path for which the nexthop object is being looked up * p - path for which the nexthop object is being looked up
* c - output variable that stores whether the nexthop object has changed * connected - True if NH MUST be a connected route
* since last time.
* m - output variable that stores whether the nexthop metric has changed
* since last time.
*/ */
extern int bgp_find_nexthop(struct bgp_info *p, int *c, int *m); extern int bgp_find_nexthop(struct bgp_info *p, int connected);
/** /**
* bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc * bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc
@ -45,12 +42,11 @@ extern int bgp_find_nexthop(struct bgp_info *p, int *c, int *m);
* ARGUMENTS: * ARGUMENTS:
* a - afi: AFI_IP or AF_IP6 * a - afi: AFI_IP or AF_IP6
* p - path for which the nexthop object is being looked up * p - path for which the nexthop object is being looked up
* c - output variable that stores whether the nexthop object has changed * peer - The BGP peer associated with this NHT
* since last time. * connected - True if NH MUST be a connected route
* m - output variable that stores whether the nexthop metric has changed
* since last time.
*/ */
extern int bgp_find_or_add_nexthop(afi_t a, struct bgp_info *p, int *c, int *m); extern int bgp_find_or_add_nexthop(afi_t a, struct bgp_info *p,
struct peer *peer, int connected);
/** /**
* bgp_unlink_nexthop() - Unlink the nexthop object from the path structure. * bgp_unlink_nexthop() - Unlink the nexthop object from the path structure.

View File

@ -100,8 +100,8 @@ bgp_packet_delete (struct peer *peer)
} }
/* Check file descriptor whether connect is established. */ /* Check file descriptor whether connect is established. */
static void int
bgp_connect_check (struct peer *peer) bgp_connect_check (struct peer *peer, int change_state)
{ {
int status; int status;
socklen_t slen; socklen_t slen;
@ -120,20 +120,23 @@ bgp_connect_check (struct peer *peer)
{ {
zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect"); zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
BGP_EVENT_ADD (peer, TCP_fatal_error); BGP_EVENT_ADD (peer, TCP_fatal_error);
return; return -1;
} }
/* When status is 0 then TCP connection is established. */ /* When status is 0 then TCP connection is established. */
if (status == 0) if (status == 0)
{ {
BGP_EVENT_ADD (peer, TCP_connection_open); BGP_EVENT_ADD (peer, TCP_connection_open);
return 1;
} }
else else
{ {
if (BGP_DEBUG (events, EVENTS)) if (BGP_DEBUG (events, EVENTS))
plog_debug (peer->log, "%s [Event] Connect failed (%s)", plog_debug (peer->log, "%s [Event] Connect failed (%s)",
peer->host, safe_strerror (errno)); peer->host, safe_strerror (errno));
if (change_state)
BGP_EVENT_ADD (peer, TCP_connection_open_failed); BGP_EVENT_ADD (peer, TCP_connection_open_failed);
return 0;
} }
} }
@ -698,7 +701,7 @@ bgp_write (struct thread *thread)
/* For non-blocking IO check. */ /* For non-blocking IO check. */
if (peer->status == Connect) if (peer->status == Connect)
{ {
bgp_connect_check (peer); bgp_connect_check (peer, 1);
return 0; return 0;
} }
@ -2541,7 +2544,7 @@ bgp_read (struct thread *thread)
/* For non-blocking IO check. */ /* For non-blocking IO check. */
if (peer->status == Connect) if (peer->status == Connect)
{ {
bgp_connect_check (peer); bgp_connect_check (peer, 1);
goto done; goto done;
} }
else else

View File

@ -40,6 +40,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* Packet send and receive function prototypes. */ /* Packet send and receive function prototypes. */
extern int bgp_read (struct thread *); extern int bgp_read (struct thread *);
extern int bgp_write (struct thread *); extern int bgp_write (struct thread *);
extern int bgp_connect_check (struct peer *, int change_state);
extern void bgp_keepalive_send (struct peer *); extern void bgp_keepalive_send (struct peer *);
extern void bgp_open_send (struct peer *); extern void bgp_open_send (struct peer *);

View File

@ -55,7 +55,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_zebra.h" #include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_vty.h" #include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h" #include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_nht.c" #include "bgpd/bgp_nht.h"
/* Extern from bgp_dump.c */ /* Extern from bgp_dump.c */
extern const char *bgp_origin_str[]; extern const char *bgp_origin_str[];
@ -1064,7 +1064,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
|| (peer->sort == BGP_PEER_EBGP || (peer->sort == BGP_PEER_EBGP
&& bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) && (bgp_multiaccess_check_v4 (attr->nexthop, peer) == 0)))
{ {
/* Set IPv4 nexthop. */ /* Set IPv4 nexthop. */
if (p->family == AF_INET) if (p->family == AF_INET)
@ -2229,6 +2229,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
struct bgp_info *new; struct bgp_info *new;
const char *reason; const char *reason;
char buf[SU_ADDRSTRLEN]; char buf[SU_ADDRSTRLEN];
int connected = 0;
bgp = peer->bgp; bgp = peer->bgp;
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
@ -2306,17 +2307,6 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* IPv4 unicast next hop check. */ /* IPv4 unicast next hop check. */
if (afi == AFI_IP && safi == SAFI_UNICAST) if (afi == AFI_IP && safi == SAFI_UNICAST)
{ {
/* If the peer is EBGP and nexthop is not on connected route,
discard it. */
if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
&& ! bgp_nexthop_onlink (afi, &new_attr)
&& ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
{
reason = "non-connected next-hop;";
bgp_attr_flush (&new_attr);
goto filtered;
}
/* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop /* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop
must not be my own address. */ must not be my own address. */
if (new_attr.nexthop.s_addr == 0 if (new_attr.nexthop.s_addr == 0
@ -2443,18 +2433,27 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
} }
/* Nexthop reachability check. */ /* Nexthop reachability check. */
if ((afi == AFI_IP || afi == AFI_IP6) if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
&& safi == SAFI_UNICAST
&& (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED
|| (peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
{ {
if (bgp_find_or_add_nexthop (afi, ri, NULL, NULL)) if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
connected = 1;
else
connected = 0;
if (bgp_find_or_add_nexthop (afi, ri, NULL, connected))
bgp_info_set_flag (rn, ri, BGP_INFO_VALID); bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
else else
{
if (BGP_DEBUG(nht, NHT))
{
char buf1[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN);
zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
}
bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
} }
}
else else
bgp_info_set_flag (rn, ri, BGP_INFO_VALID); bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
@ -2484,18 +2483,27 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
memcpy ((bgp_info_extra_get (new))->tag, tag, 3); memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
/* Nexthop reachability check. */ /* Nexthop reachability check. */
if ((afi == AFI_IP || afi == AFI_IP6) if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
&& safi == SAFI_UNICAST
&& (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED
|| (peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
{ {
if (bgp_find_or_add_nexthop (afi, new, NULL, NULL)) if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
connected = 1;
else
connected = 0;
if (bgp_find_or_add_nexthop (afi, new, NULL, connected))
bgp_info_set_flag (rn, new, BGP_INFO_VALID); bgp_info_set_flag (rn, new, BGP_INFO_VALID);
else else
{
if (BGP_DEBUG(nht, NHT))
{
char buf1[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN);
zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
}
bgp_info_unset_flag (rn, new, BGP_INFO_VALID); bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
} }
}
else else
bgp_info_set_flag (rn, new, BGP_INFO_VALID); bgp_info_set_flag (rn, new, BGP_INFO_VALID);
@ -3558,6 +3566,23 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
ri->attr = attr_new; ri->attr = attr_new;
ri->uptime = bgp_clock (); ri->uptime = bgp_clock ();
/* Nexthop reachability check. */
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
{
if (bgp_find_or_add_nexthop (afi, ri, NULL, 0))
bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
else
{
if (BGP_DEBUG(nht, NHT))
{
char buf1[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, (const void *)&attr_new->nexthop,
buf1, INET6_ADDRSTRLEN);
zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
}
bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
}
}
/* Process change. */ /* Process change. */
bgp_process (bgp, rn, afi, safi); bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn); bgp_unlock_node (rn);
@ -3570,7 +3595,25 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
/* Make new BGP info. */ /* Make new BGP info. */
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self,
attr_new, rn); attr_new, rn);
SET_FLAG (new->flags, BGP_INFO_VALID); /* Nexthop reachability check. */
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
{
if (bgp_find_or_add_nexthop (afi, new, NULL, 0))
bgp_info_set_flag (rn, new, BGP_INFO_VALID);
else
{
if (BGP_DEBUG(nht, NHT))
{
char buf1[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, (const void *)&attr_new->nexthop,
buf1, INET6_ADDRSTRLEN);
zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
}
bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
}
}
else
bgp_info_set_flag (rn, new, BGP_INFO_VALID);
/* Register new BGP information. */ /* Register new BGP information. */
bgp_info_add (rn, new); bgp_info_add (rn, new);
@ -3672,6 +3715,23 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
ri->attr = attr_new; ri->attr = attr_new;
ri->uptime = bgp_clock (); ri->uptime = bgp_clock ();
/* Nexthop reachability check. */
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
{
if (bgp_find_or_add_nexthop (afi, ri, NULL, 0))
bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
else
{
if (BGP_DEBUG(nht, NHT))
{
char buf1[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, (const void *)&attr_new->nexthop,
buf1, INET6_ADDRSTRLEN);
zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
}
bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
}
}
/* Process change. */ /* Process change. */
bgp_aggregate_increment (bgp, p, ri, afi, safi); bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi); bgp_process (bgp, rn, afi, safi);
@ -3685,7 +3745,25 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
/* Make new BGP info. */ /* Make new BGP info. */
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, attr_new, new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, attr_new,
rn); rn);
SET_FLAG (new->flags, BGP_INFO_VALID); /* Nexthop reachability check. */
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
{
if (bgp_find_or_add_nexthop (afi, new, NULL, 0))
bgp_info_set_flag (rn, new, BGP_INFO_VALID);
else
{
if (BGP_DEBUG(nht, NHT))
{
char buf1[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1,
INET6_ADDRSTRLEN);
zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
}
bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
}
}
else
bgp_info_set_flag (rn, new, BGP_INFO_VALID);
/* Aggregate address increment. */ /* Aggregate address increment. */
bgp_aggregate_increment (bgp, p, new, afi, safi); bgp_aggregate_increment (bgp, p, new, afi, safi);
@ -3770,6 +3848,7 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
if (ri) if (ri)
{ {
bgp_aggregate_decrement (bgp, p, ri, afi, safi); bgp_aggregate_decrement (bgp, p, ri, afi, safi);
bgp_unlink_nexthop(ri);
bgp_info_delete (rn, ri); bgp_info_delete (rn, ri);
bgp_process (bgp, rn, afi, safi); bgp_process (bgp, rn, afi, safi);
} }
@ -3906,17 +3985,12 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
rn->info = bgp_static; rn->info = bgp_static;
} }
/* If BGP scan is not enabled, we should install this route here. */
if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
{
bgp_static->valid = 1; bgp_static->valid = 1;
if (need_update) if (need_update)
bgp_static_withdraw (bgp, &p, afi, safi); bgp_static_withdraw (bgp, &p, afi, safi);
if (! bgp_static->backdoor) if (! bgp_static->backdoor)
bgp_static_update (bgp, &p, bgp_static, afi, safi); bgp_static_update (bgp, &p, bgp_static, afi, safi);
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -3964,6 +4038,7 @@ bgp_static_unset (struct vty *vty, struct bgp *bgp, const char *ip_str,
bgp_static_withdraw (bgp, &p, afi, safi); bgp_static_withdraw (bgp, &p, afi, safi);
/* Clear configuration. */ /* Clear configuration. */
bgp_unlink_nexthop(bgp_static);
bgp_static_free (bgp_static); bgp_static_free (bgp_static);
rn->info = NULL; rn->info = NULL;
bgp_unlock_node (rn); bgp_unlock_node (rn);

View File

@ -58,6 +58,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_network.h" #include "bgpd/bgp_network.h"
#include "bgpd/bgp_vty.h" #include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h" #include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_nht.h"
#ifdef HAVE_SNMP #ifdef HAVE_SNMP
#include "bgpd/bgp_snmp.h" #include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */ #endif /* HAVE_SNMP */
@ -4733,9 +4734,8 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
else else
UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
return 0; {
group = peer->group; group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
{ {
@ -4750,7 +4750,17 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
else else
UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
if ((peer->status == Established) && (peer->afc[afi][safi]))
bgp_maximum_prefix_overflow (peer, afi, safi, 1);
} }
}
else
{
if ((peer->status == Established) && (peer->afc[afi][safi]))
bgp_maximum_prefix_overflow (peer, afi, safi, 1);
}
return 0; return 0;
} }
@ -5767,9 +5777,6 @@ bgp_config_write (struct vty *vty)
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
vty_out (vty, " bgp network import-check%s", VTY_NEWLINE); vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
/* BGP scan interval. */
bgp_config_write_scan_time (vty);
/* BGP flag dampening. */ /* BGP flag dampening. */
if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
BGP_CONFIG_DAMPENING)) BGP_CONFIG_DAMPENING))
@ -5849,12 +5856,16 @@ bgp_master_init (void)
void void
bgp_init (void) bgp_init (void)
{ {
/* BGP VTY commands installation. */
bgp_vty_init (); /* allocates some vital data structures used by peer commands in vty_init */
bgp_scan_init ();
/* Init zebra. */ /* Init zebra. */
bgp_zebra_init (); bgp_zebra_init ();
/* BGP VTY commands installation. */
bgp_vty_init ();
/* BGP inits. */ /* BGP inits. */
bgp_attr_init (); bgp_attr_init ();
bgp_debug_init (); bgp_debug_init ();
@ -5862,7 +5873,7 @@ bgp_init (void)
bgp_route_init (); bgp_route_init ();
bgp_route_map_init (); bgp_route_map_init ();
bgp_address_init (); bgp_address_init ();
bgp_scan_init (); bgp_scan_vty_init();
bgp_mplsvpn_init (); bgp_mplsvpn_init ();
/* Access list initialize. */ /* Access list initialize. */

View File

@ -233,8 +233,16 @@ zebra_evaluate_rnh_table (int vrfid, int family, int force)
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
continue; continue;
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
{
if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
{
if (rib->type == ZEBRA_ROUTE_CONNECT)
break; break;
} }
else
break;
}
}
} }
state_changed = 0; state_changed = 0;
@ -649,7 +657,9 @@ print_rnh (struct route_node *rn, struct vty *vty)
print_nh(nexthop, vty); print_nh(nexthop, vty);
} }
else else
vty_out(vty, " unresolved%s", VTY_NEWLINE); vty_out(vty, " unresolved%s%s",
CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : "",
VTY_NEWLINE);
vty_out(vty, " Client list:"); vty_out(vty, " Client list:");
for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))

View File

@ -30,6 +30,7 @@
struct rnh struct rnh
{ {
u_char flags; u_char flags;
#define ZEBRA_NHT_CONNECTED 0x1
struct rib *state; struct rib *state;
struct list *client_list; struct list *client_list;
struct route_node *node; struct route_node *node;

View File

@ -755,6 +755,7 @@ zserv_nexthop_register (struct zserv *client, int sock, u_short length)
struct stream *s; struct stream *s;
struct prefix p; struct prefix p;
u_short l = 0; u_short l = 0;
u_char connected;
if (IS_ZEBRA_DEBUG_NHT) if (IS_ZEBRA_DEBUG_NHT)
zlog_debug("nexthop_register msg from client %s: length=%d\n", zlog_debug("nexthop_register msg from client %s: length=%d\n",
@ -764,12 +765,16 @@ zserv_nexthop_register (struct zserv *client, int sock, u_short length)
while (l < length) while (l < length)
{ {
connected = stream_getc(s);
p.family = stream_getw(s); p.family = stream_getw(s);
p.prefixlen = stream_getc(s); p.prefixlen = stream_getc(s);
l += 3; l += 4;
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
l += PSIZE(p.prefixlen); l += PSIZE(p.prefixlen);
rnh = zebra_add_rnh(&p, 0); rnh = zebra_add_rnh(&p, 0);
if (connected)
SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
zebra_add_rnh_client(rnh, client); zebra_add_rnh_client(rnh, client);
} }
zebra_evaluate_rnh_table(0, AF_INET, 0); zebra_evaluate_rnh_table(0, AF_INET, 0);
@ -785,6 +790,7 @@ zserv_nexthop_unregister (struct zserv *client, int sock, u_short length)
struct stream *s; struct stream *s;
struct prefix p; struct prefix p;
u_short l = 0; u_short l = 0;
u_char connected;
if (IS_ZEBRA_DEBUG_NHT) if (IS_ZEBRA_DEBUG_NHT)
zlog_debug("nexthop_unregister msg from client %s: length=%d\n", zlog_debug("nexthop_unregister msg from client %s: length=%d\n",
@ -794,9 +800,10 @@ zserv_nexthop_unregister (struct zserv *client, int sock, u_short length)
while (l < length) while (l < length)
{ {
connected = stream_getc(s);
p.family = stream_getw(s); p.family = stream_getw(s);
p.prefixlen = stream_getc(s); p.prefixlen = stream_getc(s);
l += 3; l += 4;
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
l += PSIZE(p.prefixlen); l += PSIZE(p.prefixlen);
rnh = zebra_lookup_rnh(&p, 0); rnh = zebra_lookup_rnh(&p, 0);