summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/Makefile.am4
-rw-r--r--bgpd/bgp_advertise.c55
-rw-r--r--bgpd/bgp_advertise.h29
-rw-r--r--bgpd/bgp_aspath.c176
-rw-r--r--bgpd/bgp_aspath.h14
-rw-r--r--bgpd/bgp_attr.c245
-rw-r--r--bgpd/bgp_attr.h12
-rw-r--r--bgpd/bgp_btoa.c1
-rw-r--r--bgpd/bgp_clist.c15
-rw-r--r--bgpd/bgp_damp.c1
-rw-r--r--bgpd/bgp_debug.c1121
-rw-r--r--bgpd/bgp_debug.h39
-rw-r--r--bgpd/bgp_ecommunity.c1
-rw-r--r--bgpd/bgp_filter.c31
-rw-r--r--bgpd/bgp_filter.h4
-rw-r--r--bgpd/bgp_fsm.c828
-rw-r--r--bgpd/bgp_fsm.h24
-rw-r--r--bgpd/bgp_main.c33
-rw-r--r--bgpd/bgp_mpath.c58
-rw-r--r--bgpd/bgp_mpath.h6
-rw-r--r--bgpd/bgp_mplsvpn.c18
-rw-r--r--bgpd/bgp_network.c139
-rw-r--r--bgpd/bgp_network.h2
-rw-r--r--bgpd/bgp_nexthop.c1143
-rw-r--r--bgpd/bgp_nexthop.h42
-rw-r--r--bgpd/bgp_nht.c518
-rw-r--r--bgpd/bgp_nht.h58
-rw-r--r--bgpd/bgp_open.c25
-rw-r--r--bgpd/bgp_packet.c796
-rw-r--r--bgpd/bgp_packet.h13
-rw-r--r--bgpd/bgp_regex.c2
-rw-r--r--bgpd/bgp_route.c2528
-rw-r--r--bgpd/bgp_route.h38
-rw-r--r--bgpd/bgp_routemap.c1038
-rw-r--r--bgpd/bgp_table.c1
-rw-r--r--bgpd/bgp_table.h1
-rw-r--r--bgpd/bgp_vty.c1921
-rw-r--r--bgpd/bgp_vty.h4
-rw-r--r--bgpd/bgp_zebra.c729
-rw-r--r--bgpd/bgp_zebra.h9
-rw-r--r--bgpd/bgpd.c749
-rw-r--r--bgpd/bgpd.h139
42 files changed, 8954 insertions, 3656 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index d2775f39..fe1be32e 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -16,7 +16,7 @@ libbgp_a_SOURCES = \
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
- bgp_encap.c bgp_encap_tlv.c
+ bgp_encap.c bgp_encap_tlv.c bgp_nht.c
noinst_HEADERS = \
bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
@@ -24,7 +24,7 @@ noinst_HEADERS = \
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h \
- bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h
+ bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h
bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index ecf531f7..43573b59 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -26,12 +26,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "hash.h"
#include "thread.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_fsm.h"
@@ -186,10 +188,12 @@ bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
struct bgp_advertise *adv;
struct bgp_advertise_attr *baa;
struct bgp_advertise *next;
+ struct bgp_advertise_fifo *fhead;
adv = adj->adv;
baa = adv->baa;
next = NULL;
+ fhead = (struct bgp_advertise_fifo *)&peer->sync[afi][safi]->withdraw;
if (baa)
{
@@ -201,10 +205,12 @@ bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
/* Unintern BGP advertise attribute. */
bgp_advertise_unintern (peer->hash[afi][safi], baa);
+
+ fhead = (struct bgp_advertise_fifo *)&peer->sync[afi][safi]->update;
}
/* Unlink myself from advertisement FIFO. */
- FIFO_DEL (adv);
+ BGP_ADV_FIFO_DEL (fhead, adv);
/* Free memory. */
bgp_advertise_free (adj->adv);
@@ -264,7 +270,24 @@ bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
/* Add new advertisement to advertisement attribute list. */
bgp_advertise_add (adv->baa, adv);
- FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
+ BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
+
+ /*
+ * Schedule write thread (by triggering adjustment of MRAI timer) only if
+ * update FIFO has grown. Otherwise, it will be done upon the work queue
+ * being fully processed. Only adjust timer if needed.
+ */
+ if (!BGP_ROUTE_ADV_HOLD(peer->bgp) &&
+ (BGP_ADV_FIFO_COUNT(&peer->sync[afi][safi]->update) >=
+ peer->bgp->adv_quanta))
+ {
+ if (!peer->radv_adjusted)
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s scheduling MRAI timer after adj_out_set", peer->host);
+ bgp_adjust_routeadv(peer);
+ }
+ }
}
void
@@ -298,10 +321,24 @@ bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p,
adv->adj = adj;
/* Add to synchronization entry for withdraw announcement. */
- FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
-
- /* Schedule packet write. */
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
+
+ /*
+ * Schedule write thread only if withdraw FIFO has grown. Otherwise,
+ * it will be done upon the work queue being fully processed.
+ */
+ if (!BGP_ROUTE_ADV_HOLD(peer->bgp) &&
+ (BGP_ADV_FIFO_COUNT(&peer->sync[afi][safi]->withdraw) >=
+ peer->bgp->wd_quanta))
+ {
+ if (!peer->t_write)
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s scheduling write thread after adj_out_unset",
+ peer->host);
+ BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ }
+ }
}
else
{
@@ -391,9 +428,9 @@ bgp_sync_init (struct peer *peer)
{
sync = XCALLOC (MTYPE_BGP_SYNCHRONISE,
sizeof (struct bgp_synchronize));
- FIFO_INIT (&sync->update);
- FIFO_INIT (&sync->withdraw);
- FIFO_INIT (&sync->withdraw_low);
+ BGP_ADV_FIFO_INIT (&sync->update);
+ BGP_ADV_FIFO_INIT (&sync->withdraw);
+ BGP_ADV_FIFO_INIT (&sync->withdraw_low);
peer->sync[afi][safi] = sync;
peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
}
diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h
index 51ba6267..6babc16c 100644
--- a/bgpd/bgp_advertise.h
+++ b/bgpd/bgp_advertise.h
@@ -23,6 +23,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include <lib/fifo.h>
+/* BGP advertise FIFO. */
+struct bgp_advertise_fifo
+{
+ struct bgp_advertise *next;
+ struct bgp_advertise *prev;
+ u_int32_t count;
+};
+
/* BGP advertise attribute. */
struct bgp_advertise_attr
{
@@ -124,6 +132,27 @@ struct bgp_synchronize
#define BGP_ADJ_OUT_ADD(N,A) BGP_INFO_ADD(N,A,adj_out)
#define BGP_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out)
+#define BGP_ADV_FIFO_ADD(F, N) \
+ do { \
+ FIFO_ADD((F), (N)); \
+ (F)->count++; \
+ } while (0)
+
+#define BGP_ADV_FIFO_DEL(F, N) \
+ do { \
+ FIFO_DEL((N)); \
+ (F)->count--; \
+ } while (0)
+
+#define BGP_ADV_FIFO_INIT(F) \
+ do { \
+ FIFO_INIT((F)); \
+ (F)->count = 0; \
+ } while (0)
+
+#define BGP_ADV_FIFO_COUNT(F) \
+ (F)->count
+
/* Prototypes. */
extern void bgp_adj_out_set (struct bgp_node *, struct peer *, struct prefix *,
struct attr *, afi_t, safi_t, struct bgp_info *);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 6ab29376..71d510ec 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "stream.h"
#include "jhash.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_aspath.h"
@@ -427,7 +428,7 @@ aspath_count_confeds (struct aspath *aspath)
}
unsigned int
-aspath_count_hops (struct aspath *aspath)
+aspath_count_hops (const struct aspath *aspath)
{
int count = 0;
struct assegment *seg = aspath->segments;
@@ -471,13 +472,11 @@ aspath_highest (struct aspath *aspath)
struct assegment *seg = aspath->segments;
as_t highest = 0;
unsigned int i;
-
+
while (seg)
{
for (i = 0; i < seg->length; i++)
- if (seg->as[i] > highest
- && (seg->as[i] < BGP_PRIVATE_AS_MIN
- || seg->as[i] > BGP_PRIVATE_AS_MAX))
+ if (seg->as[i] > highest && !BGP_AS_IS_PRIVATE(seg->as[i]))
highest = seg->as[i];
seg = seg->next;
}
@@ -1065,6 +1064,9 @@ aspath_aggregate (struct aspath *as1, struct aspath *as2)
if (match != minlen || match != seg1->length
|| seg1->length != seg2->length)
break;
+ /* We are moving on to the next segment to reset match */
+ else
+ match = 0;
seg1 = seg1->next;
seg2 = seg2->next;
@@ -1146,20 +1148,44 @@ int
aspath_private_as_check (struct aspath *aspath)
{
struct assegment *seg;
-
+
if ( !(aspath && aspath->segments) )
return 0;
-
+
seg = aspath->segments;
while (seg)
{
int i;
-
+
+ for (i = 0; i < seg->length; i++)
+ {
+ if (!BGP_AS_IS_PRIVATE(seg->as[i]))
+ return 0;
+ }
+ seg = seg->next;
+ }
+ return 1;
+}
+
+/* Return True if the entire ASPATH consist of the specified ASN */
+int
+aspath_single_asn_check (struct aspath *aspath, as_t asn)
+{
+ struct assegment *seg;
+
+ if ( !(aspath && aspath->segments) )
+ return 0;
+
+ seg = aspath->segments;
+
+ while (seg)
+ {
+ int i;
+
for (i = 0; i < seg->length; i++)
{
- if ( (seg->as[i] < BGP_PRIVATE_AS_MIN)
- || (seg->as[i] > BGP_PRIVATE_AS_MAX) )
+ if (seg->as[i] != asn)
return 0;
}
seg = seg->next;
@@ -1167,6 +1193,132 @@ aspath_private_as_check (struct aspath *aspath)
return 1;
}
+/* Replace all instances of the target ASN with our own ASN */
+struct aspath *
+aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn,
+ as_t our_asn)
+{
+ struct aspath *new;
+ struct assegment *seg;
+
+ new = aspath_dup(aspath);
+ seg = new->segments;
+
+ while (seg)
+ {
+ int i;
+
+ for (i = 0; i < seg->length; i++)
+ {
+ if (seg->as[i] == target_asn)
+ seg->as[i] = our_asn;
+ }
+ seg = seg->next;
+ }
+
+ aspath_str_update(new);
+ return new;
+}
+
+/* Replace all private ASNs with our own ASN */
+struct aspath *
+aspath_replace_private_asns (struct aspath *aspath, as_t asn)
+{
+ struct aspath *new;
+ struct assegment *seg;
+
+ new = aspath_dup(aspath);
+ seg = new->segments;
+
+ while (seg)
+ {
+ int i;
+
+ for (i = 0; i < seg->length; i++)
+ {
+ if (BGP_AS_IS_PRIVATE(seg->as[i]))
+ seg->as[i] = asn;
+ }
+ seg = seg->next;
+ }
+
+ aspath_str_update(new);
+ return new;
+}
+
+/* Remove all private ASNs */
+struct aspath *
+aspath_remove_private_asns (struct aspath *aspath)
+{
+ struct aspath *new;
+ struct assegment *seg;
+ struct assegment *new_seg;
+ struct assegment *last_new_seg;
+ int i;
+ int j;
+ int public = 0;
+
+ new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
+
+ new_seg = NULL;
+ last_new_seg = NULL;
+ seg = aspath->segments;
+ while (seg)
+ {
+ public = 0;
+ for (i = 0; i < seg->length; i++)
+ {
+ // ASN is public
+ if (!BGP_AS_IS_PRIVATE(seg->as[i]))
+ {
+ public++;
+ }
+ }
+
+ // The entire segment is private so skip it
+ if (!public)
+ {
+ seg = seg->next;
+ continue;
+ }
+
+ // The entire segment is public so copy it
+ else if (public == seg->length)
+ {
+ new_seg = assegment_dup (seg);
+ }
+
+ // The segment is a mix of public and private ASNs. Copy as many spots as
+ // there are public ASNs then come back and fill in only the public ASNs.
+ else
+ {
+ new_seg = assegment_new (seg->type, public);
+ j = 0;
+ for (i = 0; i < seg->length; i++)
+ {
+ // ASN is public
+ if (!BGP_AS_IS_PRIVATE(seg->as[i]))
+ {
+ new_seg->as[j] = seg->as[i];
+ j++;
+ }
+ }
+ }
+
+ // This is the first segment so set the aspath segments pointer to this one
+ if (!last_new_seg)
+ new->segments = new_seg;
+ else
+ last_new_seg->next = new_seg;
+
+ last_new_seg = new_seg;
+ seg = seg->next;
+ }
+
+ aspath_str_update(new);
+ return new;
+}
+
/* AS path confed check. If aspath contains confed set or sequence then return 1. */
int
aspath_confed_check (struct aspath *aspath)
@@ -1443,6 +1595,10 @@ aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2)
seg1 = aspath1->segments;
seg2 = aspath2->segments;
+ /* If both paths are originated in this AS then we do want to compare MED */
+ if (!seg1 && !seg2)
+ return 1;
+
/* find first non-confed segments for each */
while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE)
|| (seg1->type == AS_CONFED_SET)))
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 1311f8a5..134f1f66 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -31,12 +31,20 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define BGP_PRIVATE_AS_MIN 64512U
#define BGP_PRIVATE_AS_MAX 65535U
+/* Private 4 byte AS range defined in RFC6996. */
+#define BGP_PRIVATE_AS4_MIN 4200000000U
+#define BGP_PRIVATE_AS4_MAX 4294967294U
+
/* we leave BGP_AS_MAX as the 16bit AS MAX number. */
#define BGP_AS_MAX 65535U
#define BGP_AS4_MAX 4294967295U
/* Transition 16Bit AS as defined by IANA */
#define BGP_AS_TRANS 23456U
+#define BGP_AS_IS_PRIVATE(ASN) \
+ (((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \
+ ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
+
/* AS_PATH segment data in abstracted form, no limit is placed on length */
struct assegment
{
@@ -90,11 +98,15 @@ extern void aspath_print_all_vty (struct vty *);
extern unsigned int aspath_key_make (void *);
extern int aspath_loop_check (struct aspath *, as_t);
extern int aspath_private_as_check (struct aspath *);
+extern int aspath_single_asn_check (struct aspath *, as_t asn);
+extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn);
+extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn);
+extern struct aspath *aspath_remove_private_asns (struct aspath *aspath);
extern int aspath_firstas_check (struct aspath *, as_t);
extern int aspath_confed_check (struct aspath *);
extern int aspath_left_confed_check (struct aspath *);
extern unsigned long aspath_count (void);
-extern unsigned int aspath_count_hops (struct aspath *);
+extern unsigned int aspath_count_hops (const struct aspath *);
extern unsigned int aspath_count_confeds (struct aspath *);
extern unsigned int aspath_size (struct aspath *);
extern as_t aspath_highest (struct aspath *);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index f34e6493..bc39f3b8 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -153,7 +153,6 @@ cluster_free (struct cluster_list *cluster)
XFREE (MTYPE_CLUSTER, cluster);
}
-#if 0
static struct cluster_list *
cluster_dup (struct cluster_list *cluster)
{
@@ -172,7 +171,6 @@ cluster_dup (struct cluster_list *cluster)
return new;
}
-#endif
static struct cluster_list *
cluster_intern (struct cluster_list *cluster)
@@ -322,6 +320,23 @@ transit_free (struct transit *transit)
XFREE (MTYPE_TRANSIT, transit);
}
+static struct transit *
+transit_dup (struct transit *transit)
+{
+ struct transit *new;
+
+ new = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit));
+ new->length = transit->length;
+ if (new->length)
+ {
+ new->val = XMALLOC (MTYPE_TRANSIT_VAL, transit->length);
+ memcpy (new->val, transit->val, transit->length);
+ }
+ else
+ new->val = NULL;
+
+ return new;
+}
static void *
transit_hash_alloc (void *p)
@@ -458,6 +473,46 @@ bgp_attr_dup (struct attr *new, struct attr *orig)
}
}
+void
+bgp_attr_deep_dup (struct attr *new, struct attr *orig)
+{
+ if (orig->aspath)
+ new->aspath = aspath_dup(orig->aspath);
+
+ if (orig->community)
+ new->community = community_dup(orig->community);
+
+ if (orig->extra)
+ {
+ if (orig->extra->ecommunity)
+ new->extra->ecommunity = ecommunity_dup(orig->extra->ecommunity);
+ if (orig->extra->cluster)
+ new->extra->cluster = cluster_dup(orig->extra->cluster);
+ if (orig->extra->transit)
+ new->extra->transit = transit_dup(orig->extra->transit);
+ }
+}
+
+void
+bgp_attr_deep_free (struct attr *attr)
+{
+ if (attr->aspath)
+ aspath_free(attr->aspath);
+
+ if (attr->community)
+ community_free(attr->community);
+
+ if (attr->extra)
+ {
+ if (attr->extra->ecommunity)
+ ecommunity_free(&attr->extra->ecommunity);
+ if (attr->extra->cluster)
+ cluster_free(attr->extra->cluster);
+ if (attr->extra->transit)
+ transit_free(attr->extra->transit);
+ }
+}
+
unsigned long int
attr_count (void)
{
@@ -495,6 +550,7 @@ attrhash_key_make (void *p)
MIX(extra->weight);
MIX(extra->mp_nexthop_global_in.s_addr);
MIX(extra->originator_id.s_addr);
+ MIX(extra->tag);
}
if (attr->aspath)
@@ -540,6 +596,7 @@ attrhash_cmp (const void *p1, const void *p2)
&& ae1->aggregator_as == ae2->aggregator_as
&& ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
&& ae1->weight == ae2->weight
+ && ae1->tag == ae2->tag
&& ae1->mp_nexthop_len == ae2->mp_nexthop_len
&& IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
&& IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
@@ -691,6 +748,7 @@ bgp_attr_default_set (struct attr *attr, u_char origin)
attr->aspath = aspath_empty ();
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
+ attr->extra->tag = 0;
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
@@ -717,10 +775,12 @@ bgp_attr_default_intern (u_char origin)
return new;
}
+/* Create the attributes for an aggregate */
struct attr *
bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
struct aspath *aspath,
- struct community *community, int as_set)
+ struct community *community, int as_set,
+ u_char atomic_aggregate)
{
struct attr attr;
struct attr *new;
@@ -753,7 +813,7 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
- if (! as_set)
+ if (! as_set || atomic_aggregate)
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
@@ -962,19 +1022,18 @@ bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args,
CHECK_FLAG (real_flags, attr_flag_str[i].key)
)
{
- zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"",
- LOOKUP (attr_str, attr_code),
- CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
- attr_flag_str[i].str);
+ zlog_err ("%s attribute must%s be flagged as \"%s\"",
+ LOOKUP (attr_str, attr_code),
+ CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not",
+ attr_flag_str[i].str);
seen = 1;
}
if (!seen)
{
- zlog (args->peer->log, LOG_DEBUG,
- "Strange, %s called for attr %s, but no problem found with flags"
- " (real flags 0x%x, desired 0x%x)",
- __func__, LOOKUP (attr_str, attr_code),
- real_flags, desired_flags);
+ zlog_debug ("Strange, %s called for attr %s, but no problem found with flags"
+ " (real flags 0x%x, desired 0x%x)",
+ __func__, LOOKUP (attr_str, attr_code),
+ real_flags, desired_flags);
}
}
@@ -1007,7 +1066,6 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
u_int8_t mask = BGP_ATTR_FLAG_EXTLEN;
const u_int8_t flags = args->flags;
const u_int8_t attr_code = args->type;
- struct peer *const peer = args->peer;
/* there may be attributes we don't know about */
if (attr_code > attr_flags_values_max)
@@ -1021,9 +1079,8 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags)
&& !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags))
{
- zlog (peer->log, LOG_ERR,
- "%s well-known attributes must have transitive flag set (%x)",
- LOOKUP (attr_str, attr_code), flags);
+ zlog_err ("%s well-known attributes must have transitive flag set (%x)",
+ LOOKUP (attr_str, attr_code), flags);
return 1;
}
@@ -1034,19 +1091,17 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
{
if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL))
{
- zlog (peer->log, LOG_ERR,
- "%s well-known attribute "
- "must NOT have the partial flag set (%x)",
- LOOKUP (attr_str, attr_code), flags);
+ zlog_err ("%s well-known attribute "
+ "must NOT have the partial flag set (%x)",
+ LOOKUP (attr_str, attr_code), flags);
return 1;
}
if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)
&& !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS))
{
- zlog (peer->log, LOG_ERR,
- "%s optional + transitive attribute "
- "must NOT have the partial flag set (%x)",
- LOOKUP (attr_str, attr_code), flags);
+ zlog_err ("%s optional + transitive attribute "
+ "must NOT have the partial flag set (%x)",
+ LOOKUP (attr_str, attr_code), flags);
return 1;
}
}
@@ -1081,8 +1136,7 @@ bgp_attr_origin (struct bgp_attr_parser_args *args)
value). */
if (length != 1)
{
- zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
- length);
+ zlog_err ("Origin attribute length is not one %d", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
@@ -1098,8 +1152,7 @@ bgp_attr_origin (struct bgp_attr_parser_args *args)
&& (attr->origin != BGP_ORIGIN_EGP)
&& (attr->origin != BGP_ORIGIN_INCOMPLETE))
{
- zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
- attr->origin);
+ zlog_err ("Origin attribute value is invalid %d", attr->origin);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
args->total);
@@ -1130,9 +1183,7 @@ bgp_attr_aspath (struct bgp_attr_parser_args *args)
/* In case of IBGP, length will be zero. */
if (! attr->aspath)
{
- zlog (peer->log, LOG_ERR,
- "Malformed AS path from %s, length is %d",
- peer->host, length);
+ zlog_err ("Malformed AS path from %s, length is %d", peer->host, length);
return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0);
}
@@ -1159,7 +1210,7 @@ bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
(peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
{
- zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
+ zlog_err ("Malformed AS path from %s", peer->host);
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_AS_PATH);
return BGP_ATTR_PARSE_ERROR;
@@ -1171,8 +1222,7 @@ bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr)
if (peer->sort == BGP_PEER_EBGP
&& ! aspath_firstas_check (attr->aspath, peer->as))
{
- zlog (peer->log, LOG_ERR,
- "%s incorrect first AS (must be %u)", peer->host, peer->as);
+ zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as);
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MAL_AS_PATH);
return BGP_ATTR_PARSE_ERROR;
@@ -1206,9 +1256,7 @@ bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path)
/* In case of IBGP, length will be zero. */
if (!*as4_path)
{
- zlog (peer->log, LOG_ERR,
- "Malformed AS4 path from %s, length is %d",
- peer->host, length);
+ zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_MAL_AS_PATH,
0);
@@ -1234,8 +1282,7 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args)
/* Check nexthop attribute length. */
if (length != 4)
{
- zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
- length);
+ zlog_err ("Nexthop attribute length isn't four [%d]", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
@@ -1253,7 +1300,7 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args)
{
char buf[INET_ADDRSTRLEN];
inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
- zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
+ zlog_err ("Martian nexthop %s", buf);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
args->total);
@@ -1276,8 +1323,7 @@ bgp_attr_med (struct bgp_attr_parser_args *args)
/* Length check. */
if (length != 4)
{
- zlog (peer->log, LOG_ERR,
- "MED attribute length isn't four [%d]", length);
+ zlog_err ("MED attribute length isn't four [%d]", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
@@ -1302,8 +1348,7 @@ bgp_attr_local_pref (struct bgp_attr_parser_args *args)
/* Length check. */
if (length != 4)
{
- zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]",
- length);
+ zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
@@ -1330,15 +1375,13 @@ bgp_attr_local_pref (struct bgp_attr_parser_args *args)
static int
bgp_attr_atomic (struct bgp_attr_parser_args *args)
{
- struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
/* Length check. */
if (length != 0)
{
- zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
- length);
+ zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
@@ -1367,8 +1410,7 @@ bgp_attr_aggregator (struct bgp_attr_parser_args *args)
if (length != wantedlen)
{
- zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]",
- wantedlen, length);
+ zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
@@ -1398,8 +1440,7 @@ bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args,
if (length != 8)
{
- zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]",
- length);
+ zlog_err ("New Aggregator length is not 8 [%d]", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
0);
@@ -1562,7 +1603,7 @@ bgp_attr_originator_id (struct bgp_attr_parser_args *args)
/* Length check. */
if (length != 4)
{
- zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
+ zlog_err ("Bad originator ID length %d", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
@@ -1588,7 +1629,7 @@ bgp_attr_cluster_list (struct bgp_attr_parser_args *args)
/* Check length. */
if (length % 4)
{
- zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
+ zlog_err ("Bad cluster list length %d", length);
return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
@@ -1698,8 +1739,8 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
char buf1[INET6_ADDRSTRLEN];
char buf2[INET6_ADDRSTRLEN];
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
+ if (bgp_debug_update(peer, NULL, 1))
+ zlog_debug ("%s sent two nexthops %s %s but second one is not a link-local nexthop", peer->host,
inet_ntop (AF_INET6, &attre->mp_nexthop_global,
buf1, INET6_ADDRSTRLEN),
inet_ntop (AF_INET6, &attre->mp_nexthop_local,
@@ -1736,7 +1777,7 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
__func__, peer->host);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
-
+
mp_update->afi = afi;
mp_update->safi = safi;
mp_update->nlri = stream_pnt (s);
@@ -1837,8 +1878,7 @@ bgp_attr_encap(
if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
|| !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL))
{
- zlog (peer->log, LOG_ERR,
- "Tunnel Encap attribute flag isn't optional and transitive %d", flag);
+ zlog_err ("Tunnel Encap attribute flag isn't optional and transitive %d", flag);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
@@ -1851,8 +1891,7 @@ bgp_attr_encap(
uint16_t tlv_length;
if (length < 4) {
- zlog (peer->log, LOG_ERR,
- "Tunnel Encap attribute not long enough to contain outer T,L");
+ zlog_err ("Tunnel Encap attribute not long enough to contain outer T,L");
bgp_notify_send_with_data(peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
@@ -1864,7 +1903,7 @@ bgp_attr_encap(
length -= 4;
if (tlv_length != length) {
- zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)",
+ zlog_err ("%s: tlv_length(%d) != length(%d)",
__func__, tlv_length, length);
}
}
@@ -1881,8 +1920,7 @@ bgp_attr_encap(
}
if (sublength > length) {
- zlog (peer->log, LOG_ERR,
- "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
+ zlog_err ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
sublength, length);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_UPDATE_ERR,
@@ -1923,8 +1961,7 @@ bgp_attr_encap(
if (length) {
/* spurious leftover data */
- zlog (peer->log, LOG_ERR,
- "Tunnel Encap attribute length is bad: %d leftover octets", length);
+ zlog_err ("Tunnel Encap attribute length is bad: %d leftover octets", length);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
@@ -1949,15 +1986,10 @@ bgp_attr_unknown (struct bgp_attr_parser_args *args)
const u_char flag = args->flags;
const bgp_size_t length = args->length;
-
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
- peer->host, type, length);
+ if (bgp_debug_update(peer, NULL, 1))
+ zlog_debug ("%s Unknown attribute is received (type %d, length %d)",
+ peer->host, type, length);
- if (BGP_DEBUG (events, EVENTS))
- zlog (peer->log, LOG_DEBUG,
- "Unknown attribute type %d length %d is received", type, length);
-
/* Forward read pointer of input stream. */
stream_forward_getp (peer->ibuf, length);
@@ -2039,9 +2071,7 @@ bgp_attr_check (struct peer *peer, struct attr *attr)
if (type)
{
- zlog (peer->log, LOG_WARNING,
- "%s Missing well-known attribute %d / %s",
- peer->host, type, LOOKUP (attr_str, type));
+ zlog_warn ("%s Missing well-known attribute %d.", peer->host, type);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_MISS_ATTR,
@@ -2083,10 +2113,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
{
/* XXX warning: long int format, int arg (arg 5) */
- zlog (peer->log, LOG_WARNING,
- "%s: error BGP attribute length %lu is smaller than min len",
- peer->host,
- (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
+ zlog_warn ("%s: error BGP attribute length %lu is smaller than min len",
+ peer->host,
+ (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
@@ -2106,10 +2135,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
&& ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
{
- zlog (peer->log, LOG_WARNING,
- "%s: Extended length set, but just %lu bytes of attr header",
- peer->host,
- (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
+ zlog_warn ("%s: Extended length set, but just %lu bytes of attr header",
+ peer->host,
+ (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
@@ -2129,9 +2157,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (CHECK_BITMAP (seen, type))
{
- zlog (peer->log, LOG_WARNING,
- "%s: error BGP attribute type %d appears twice in a message",
- peer->host, type);
+ zlog_warn ("%s: error BGP attribute type %d appears twice in a message",
+ peer->host, type);
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
@@ -2149,11 +2176,11 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (attr_endp > endp)
{
- zlog (peer->log, LOG_WARNING,
- "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp);
- bgp_notify_send (peer,
- BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+ zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp);
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ startp, attr_endp - startp);
return BGP_ATTR_PARSE_ERROR;
}
@@ -2252,10 +2279,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
/* If hard error occured immediately return to the caller. */
if (ret == BGP_ATTR_PARSE_ERROR)
{
- zlog (peer->log, LOG_WARNING,
- "%s: Attribute %s, parse error",
- peer->host,
- LOOKUP (attr_str, type));
+ zlog_warn ("%s: Attribute %s, parse error",
+ peer->host,
+ LOOKUP (attr_str, type));
if (as4_path)
aspath_unintern (&as4_path);
return ret;
@@ -2263,10 +2289,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
if (ret == BGP_ATTR_PARSE_WITHDRAW)
{
- zlog (peer->log, LOG_WARNING,
- "%s: Attribute %s, parse error - treating as withdrawal",
- peer->host,
- LOOKUP (attr_str, type));
+ zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal",
+ peer->host,
+ LOOKUP (attr_str, type));
if (as4_path)
aspath_unintern (&as4_path);
return ret;
@@ -2275,9 +2300,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
/* Check the fetched length. */
if (BGP_INPUT_PNT (peer) != attr_endp)
{
- zlog (peer->log, LOG_WARNING,
- "%s: BGP attribute %s, fetch error",
- peer->host, LOOKUP (attr_str, type));
+ zlog_warn ("%s: BGP attribute %s, fetch error",
+ peer->host, LOOKUP (attr_str, type));
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
@@ -2289,9 +2313,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
/* Check final read pointer is same as end pointer. */
if (BGP_INPUT_PNT (peer) != endp)
{
- zlog (peer->log, LOG_WARNING,
- "%s: BGP attribute %s, length mismatch",
- peer->host, LOOKUP (attr_str, type));
+ zlog_warn ("%s: BGP attribute %s, length mismatch",
+ peer->host, LOOKUP (attr_str, type));
bgp_notify_send (peer,
BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
@@ -2547,8 +2570,7 @@ bgp_packet_mpattr_tea(
}
if (attrlenfield > 0xffff) {
- zlog (peer->log, LOG_ERR,
- "%s attribute is too long (length=%d), can't send it",
+ zlog_err ("%s attribute is too long (length=%d), can't send it",
attrname,
attrlenfield);
return;
@@ -2705,12 +2727,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
}
/* MED attribute. */
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) ||
+ bgp->maxmed_active)
{
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
stream_putc (s, 4);
- stream_putl (s, attr->med);
+ stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med));
}
/* Local preference. */
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index fe6c2a1a..87310d50 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -93,6 +93,9 @@ struct attr_extra
uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
+
+ /* route tag */
+ u_short tag;
};
/* BGP core attribute structure. */
@@ -117,6 +120,7 @@ struct attr
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
+ ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
@@ -140,6 +144,10 @@ struct transit
#define ATTR_FLAG_BIT(X) (1 << ((X) - 1))
+#define BGP_CLUSTER_LIST_LENGTH(attr) \
+ (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \
+ (attr)->extra->cluster->length : 0)
+
typedef enum {
BGP_ATTR_PARSE_PROCEED = 0,
BGP_ATTR_PARSE_ERROR = -1,
@@ -158,6 +166,8 @@ extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
extern struct attr_extra *bgp_attr_extra_get (struct attr *);
extern void bgp_attr_extra_free (struct attr *);
extern void bgp_attr_dup (struct attr *, struct attr *);
+extern void bgp_attr_deep_dup (struct attr *, struct attr *);
+extern void bgp_attr_deep_free (struct attr *);
extern struct attr *bgp_attr_intern (struct attr *attr);
extern void bgp_attr_unintern_sub (struct attr *);
extern void bgp_attr_unintern (struct attr **);
@@ -166,7 +176,7 @@ extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
extern struct attr *bgp_attr_default_intern (u_char);
extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char,
struct aspath *,
- struct community *, int as_set);
+ struct community *, int as_set, u_char);
extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *,
struct stream *, struct attr *,
struct prefix *, afi_t, safi_t,
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
index b408efdd..d298f8ba 100644
--- a/bgpd/bgp_btoa.c
+++ b/bgpd/bgp_btoa.c
@@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "privs.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_dump.h"
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index bb06028b..4abdf0c7 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "prefix.h"
#include "memory.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_community.h"
@@ -707,7 +708,10 @@ community_list_set (struct community_list_handler *ch,
if (community_list_dup_check (list, entry))
community_entry_free (entry);
else
- community_list_entry_add (list, entry);
+ {
+ community_list_entry_add (list, entry);
+ route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED);
+ }
return 0;
}
@@ -733,6 +737,7 @@ community_list_unset (struct community_list_handler *ch,
if (!str)
{
community_list_delete (list);
+ route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
return 0;
}
@@ -758,6 +763,7 @@ community_list_unset (struct community_list_handler *ch,
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
community_list_entry_delete (list, entry, style);
+ route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
return 0;
}
@@ -826,7 +832,10 @@ extcommunity_list_set (struct community_list_handler *ch,
if (community_list_dup_check (list, entry))
community_entry_free (entry);
else
- community_list_entry_add (list, entry);
+ {
+ community_list_entry_add (list, entry);
+ route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED);
+ }
return 0;
}
@@ -852,6 +861,7 @@ extcommunity_list_unset (struct community_list_handler *ch,
if (!str)
{
community_list_delete (list);
+ route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
return 0;
}
@@ -877,6 +887,7 @@ extcommunity_list_unset (struct community_list_handler *ch,
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
community_list_entry_delete (list, entry, style);
+ route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
return 0;
}
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index ac647239..1c128cc1 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "log.h"
#include "thread.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_damp.h"
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 60e2777e..2a4997e8 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "log.h"
#include "sockunion.h"
#include "filter.h"
+#include "memory.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_aspath.h"
@@ -38,24 +39,31 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_community.h"
unsigned long conf_bgp_debug_as4;
-unsigned long conf_bgp_debug_fsm;
+unsigned long conf_bgp_debug_neighbor_events;
unsigned long conf_bgp_debug_events;
unsigned long conf_bgp_debug_packet;
unsigned long conf_bgp_debug_filter;
unsigned long conf_bgp_debug_keepalive;
unsigned long conf_bgp_debug_update;
-unsigned long conf_bgp_debug_normal;
unsigned long conf_bgp_debug_zebra;
+unsigned long conf_bgp_debug_nht;
unsigned long term_bgp_debug_as4;
-unsigned long term_bgp_debug_fsm;
+unsigned long term_bgp_debug_neighbor_events;
unsigned long term_bgp_debug_events;
unsigned long term_bgp_debug_packet;
unsigned long term_bgp_debug_filter;
unsigned long term_bgp_debug_keepalive;
unsigned long term_bgp_debug_update;
-unsigned long term_bgp_debug_normal;
unsigned long term_bgp_debug_zebra;
+unsigned long term_bgp_debug_nht;
+
+struct list *bgp_debug_neighbor_events_peers = NULL;
+struct list *bgp_debug_keepalive_peers = NULL;
+struct list *bgp_debug_update_out_peers = NULL;
+struct list *bgp_debug_update_in_peers = NULL;
+struct list *bgp_debug_update_prefixes = NULL;
+struct list *bgp_debug_zebra_prefixes = NULL;
/* messages for BGP-4 status */
const struct message bgp_status_msg[] =
@@ -90,7 +98,7 @@ static const struct message bgp_notify_msg[] =
{ BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"},
{ BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"},
{ BGP_NOTIFY_HOLD_ERR, "Hold Timer Expired"},
- { BGP_NOTIFY_FSM_ERR, "Finite State Machine Error"},
+ { BGP_NOTIFY_FSM_ERR, "Neighbor Events Error"},
{ BGP_NOTIFY_CEASE, "Cease"},
{ BGP_NOTIFY_CAPABILITY_ERR, "CAPABILITY Message Error"},
};
@@ -161,6 +169,151 @@ static const int bgp_notify_capability_msg_max = BGP_NOTIFY_CAPABILITY_MAX;
const char *bgp_origin_str[] = {"i","e","?"};
const char *bgp_origin_long_str[] = {"IGP","EGP","incomplete"};
+
+/* Given a string return a pointer the corresponding peer structure */
+static struct peer *
+bgp_find_peer (struct vty *vty, const char *peer_str)
+{
+ int ret;
+ union sockunion su;
+ struct bgp *bgp;
+
+ bgp = vty->index;
+ ret = str2sockunion (peer_str, &su);
+
+ /* 'swpX' string */
+ if (ret < 0)
+ return peer_lookup_by_conf_if (bgp, peer_str);
+ else
+ return peer_lookup (bgp, &su);
+}
+
+static void
+bgp_debug_list_free(struct list *list)
+{
+ struct bgp_debug_filter *filter;
+ struct listnode *node, *nnode;
+
+ if (list)
+ for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
+ {
+ listnode_delete (list, filter);
+
+ if (filter->p)
+ prefix_free(filter->p);
+
+ if (filter->peer)
+ peer_unlock (filter->peer);
+
+ XFREE (MTYPE_BGP_DEBUG_FILTER, filter);
+ }
+}
+
+/* Print the desc along with a list of peers/prefixes this debug is
+ * enabled for */
+static void
+bgp_debug_list_print (struct vty *vty, const char *desc, struct list *list)
+{
+ struct bgp_debug_filter *filter;
+ struct listnode *node, *nnode;
+ char buf[INET6_ADDRSTRLEN];
+
+ vty_out (vty, "%s", desc);
+
+ if (list && !list_isempty(list))
+ {
+ vty_out (vty, " for");
+ for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
+ {
+ if (filter->peer)
+ vty_out (vty, " %s", filter->peer->host);
+
+ if (filter->p)
+ vty_out (vty, " %s/%d",
+ inet_ntop (filter->p->family, &filter->p->u.prefix, buf, INET6_ADDRSTRLEN),
+ filter->p->prefixlen);
+ }
+ }
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+static void
+bgp_debug_list_add_entry(struct list *list, struct peer *peer, struct prefix *p)
+{
+ struct bgp_debug_filter *filter;
+
+ filter = XCALLOC (MTYPE_BGP_DEBUG_FILTER, sizeof (struct bgp_debug_filter));
+
+ if (peer)
+ {
+ peer_lock (peer);
+ filter->peer = peer;
+ filter->p = NULL;
+ }
+ else if (p)
+ {
+ filter->peer = NULL;
+ filter->p = p;
+ }
+
+ listnode_add(list, filter);
+}
+
+static int
+bgp_debug_list_remove_entry(struct list *list, struct peer *peer, struct prefix *p)
+{
+ struct bgp_debug_filter *filter;
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
+ {
+ if (peer && filter->peer == peer)
+ {
+ listnode_delete (list, filter);
+ peer_unlock (filter->peer);
+ XFREE (MTYPE_BGP_DEBUG_FILTER, filter);
+ return 1;
+ }
+ else if (p && filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p))
+ {
+ listnode_delete (list, filter);
+ prefix_free (filter->p);
+ XFREE (MTYPE_BGP_DEBUG_FILTER, filter);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bgp_debug_list_has_entry(struct list *list, struct peer *peer, struct prefix *p)
+{
+ struct bgp_debug_filter *filter;
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
+ {
+ if (peer)
+ {
+ if (filter->peer == peer)
+ {
+ return 1;
+ }
+ }
+ else if (p)
+ {
+ if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p))
+ {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
/* Dump attribute. */
int
bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
@@ -276,18 +429,12 @@ bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
break;
}
- if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
+ if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS) || bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
zlog_info ("%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s",
strcmp (direct, "received") == 0 ? "received from" : "sent to",
peer->host, bgp_notify->code, bgp_notify->subcode,
code_str, subcode_str, bgp_notify->length,
bgp_notify->data ? bgp_notify->data : "");
- else if (BGP_DEBUG (normal, NORMAL))
- plog_debug (peer->log, "%s %s NOTIFICATION %d/%d (%s%s) %d bytes %s",
- peer ? peer->host : "",
- direct, bgp_notify->code, bgp_notify->subcode,
- code_str, subcode_str, bgp_notify->length,
- bgp_notify->data ? bgp_notify->data : "");
}
/* Debug option setting interface. */
@@ -334,13 +481,6 @@ DEFUN (no_debug_bgp_as4,
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_as4,
- undebug_bgp_as4_cmd,
- "undebug bgp as4",
- UNDEBUG_STR
- BGP_STR
- "BGP AS4 actions\n")
-
DEFUN (debug_bgp_as4_segment,
debug_bgp_as4_segment_cmd,
"debug bgp as4 segment",
@@ -378,140 +518,163 @@ DEFUN (no_debug_bgp_as4_segment,
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_as4_segment,
- undebug_bgp_as4_segment_cmd,
- "undebug bgp as4 segment",
- UNDEBUG_STR
- BGP_STR
- "BGP AS4 actions\n"
- "BGP AS4 aspath segment handling\n")
-
-DEFUN (debug_bgp_fsm,
- debug_bgp_fsm_cmd,
- "debug bgp fsm",
+/* debug bgp neighbor_events */
+DEFUN (debug_bgp_neighbor_events,
+ debug_bgp_neighbor_events_cmd,
+ "debug bgp neighbor-events",
DEBUG_STR
BGP_STR
- "BGP Finite State Machine\n")
+ "BGP Neighbor Events\n")
{
if (vty->node == CONFIG_NODE)
- DEBUG_ON (fsm, FSM);
+ DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
else
{
- TERM_DEBUG_ON (fsm, FSM);
- vty_out (vty, "BGP fsm debugging is on%s", VTY_NEWLINE);
+ TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
+ vty_out (vty, "BGP neighbor-events debugging is on%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-DEFUN (no_debug_bgp_fsm,
- no_debug_bgp_fsm_cmd,
- "no debug bgp fsm",
- NO_STR
+DEFUN (debug_bgp_neighbor_events_peer,
+ debug_bgp_neighbor_events_peer_cmd,
+ "debug bgp neighbor-events (A.B.C.D|X:X::X:X|WORD)",
DEBUG_STR
BGP_STR
- "Finite State Machine\n")
+ "BGP Neighbor Events\n"
+ "BGP neighbor IP address to debug\n"
+ "BGP IPv6 neighbor to debug\n"
+ "BGP neighbor on interface to debug\n")
{
+ struct peer *peer;
+
+ peer = bgp_find_peer (vty, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!bgp_debug_neighbor_events_peers)
+ bgp_debug_neighbor_events_peers = list_new ();
+
+ if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, peer, NULL))
+ {
+ vty_out (vty, "BGP neighbor-events debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, peer, NULL);
+
if (vty->node == CONFIG_NODE)
- DEBUG_OFF (fsm, FSM);
+ DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
else
{
- TERM_DEBUG_OFF (fsm, FSM);
- vty_out (vty, "BGP fsm debugging is off%s", VTY_NEWLINE);
+ TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
+ vty_out (vty, "BGP neighbor-events debugging is on for %s%s", argv[0], VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_fsm,
- undebug_bgp_fsm_cmd,
- "undebug bgp fsm",
- UNDEBUG_STR
- BGP_STR
- "Finite State Machine\n")
-
-DEFUN (debug_bgp_events,
- debug_bgp_events_cmd,
- "debug bgp events",
+DEFUN (no_debug_bgp_neighbor_events,
+ no_debug_bgp_neighbor_events_cmd,
+ "no debug bgp neighbor-events",
+ NO_STR
DEBUG_STR
BGP_STR
- "BGP events\n")
+ "Neighbor Events\n")
{
+ bgp_debug_list_free(bgp_debug_neighbor_events_peers);
+
if (vty->node == CONFIG_NODE)
- DEBUG_ON (events, EVENTS);
+ DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS);
else
{
- TERM_DEBUG_ON (events, EVENTS);
- vty_out (vty, "BGP events debugging is on%s", VTY_NEWLINE);
+ TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS);
+ vty_out (vty, "BGP neighbor-events debugging is off%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-DEFUN (no_debug_bgp_events,
- no_debug_bgp_events_cmd,
- "no debug bgp events",
+DEFUN (no_debug_bgp_neighbor_events_peer,
+ no_debug_bgp_neighbor_events_peer_cmd,
+ "no debug bgp neighbor-events (A.B.C.D|X:X::X:X|WORD)",
NO_STR
DEBUG_STR
BGP_STR
- "BGP events\n")
+ "Neighbor Events\n"
+ "BGP neighbor IP address to debug\n"
+ "BGP IPv6 neighbor to debug\n"
+ "BGP neighbor on interface to debug\n")
{
- if (vty->node == CONFIG_NODE)
- DEBUG_OFF (events, EVENTS);
- else
+ int found_peer = 0;
+ struct peer *peer;
+
+ peer = bgp_find_peer (vty, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (bgp_debug_neighbor_events_peers && !list_isempty(bgp_debug_neighbor_events_peers))
{
- TERM_DEBUG_OFF (events, EVENTS);
- vty_out (vty, "BGP events debugging is off%s", VTY_NEWLINE);
+ found_peer = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, peer, NULL);
+
+ if (list_isempty(bgp_debug_neighbor_events_peers))
+ {
+ if (vty->node == CONFIG_NODE)
+ DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS);
+ else
+ TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS);
+ }
}
+
+ if (found_peer)
+ vty_out (vty, "BGP neighbor-events debugging is off for %s%s", argv[0], VTY_NEWLINE);
+ else
+ vty_out (vty, "BGP neighbor-events debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_events,
- undebug_bgp_events_cmd,
- "undebug bgp events",
- UNDEBUG_STR
- BGP_STR
- "BGP events\n")
-
-DEFUN (debug_bgp_filter,
- debug_bgp_filter_cmd,
- "debug bgp filters",
+/* debug bgp nht */
+DEFUN (debug_bgp_nht,
+ debug_bgp_nht_cmd,
+ "debug bgp nht",
DEBUG_STR
BGP_STR
- "BGP filters\n")
+ "BGP nexthop tracking events\n")
{
if (vty->node == CONFIG_NODE)
- DEBUG_ON (filter, FILTER);
+ DEBUG_ON (nht, NHT);
else
{
- TERM_DEBUG_ON (filter, FILTER);
- vty_out (vty, "BGP filters debugging is on%s", VTY_NEWLINE);
+ TERM_DEBUG_ON (nht, NHT);
+ vty_out (vty, "BGP nexthop tracking debugging is on%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-DEFUN (no_debug_bgp_filter,
- no_debug_bgp_filter_cmd,
- "no debug bgp filters",
+DEFUN (no_debug_bgp_nht,
+ no_debug_bgp_nht_cmd,
+ "no debug bgp nht",
NO_STR
DEBUG_STR
BGP_STR
- "BGP filters\n")
+ "BGP nexthop tracking events\n")
{
if (vty->node == CONFIG_NODE)
- DEBUG_OFF (filter, FILTER);
+ DEBUG_OFF (nht, NHT);
else
{
- TERM_DEBUG_OFF (filter, FILTER);
- vty_out (vty, "BGP filters debugging is off%s", VTY_NEWLINE);
+ TERM_DEBUG_OFF (nht, NHT);
+ vty_out (vty, "BGP nexthop tracking debugging is off%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_filter,
- undebug_bgp_filter_cmd,
- "undebug bgp filters",
- UNDEBUG_STR
- BGP_STR
- "BGP filters\n")
-
+/* debug bgp keepalives */
DEFUN (debug_bgp_keepalive,
debug_bgp_keepalive_cmd,
"debug bgp keepalives",
@@ -529,6 +692,46 @@ DEFUN (debug_bgp_keepalive,
return CMD_SUCCESS;
}
+DEFUN (debug_bgp_keepalive_peer,
+ debug_bgp_keepalive_peer_cmd,
+ "debug bgp keepalives (A.B.C.D|X:X::X:X|WORD)",
+ DEBUG_STR
+ BGP_STR
+ "BGP Neighbor Events\n"
+ "BGP neighbor IP address to debug\n"
+ "BGP IPv6 neighbor to debug\n"
+ "BGP neighbor on interface to debug\n")
+{
+ struct peer *peer;
+
+ peer = bgp_find_peer (vty, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!bgp_debug_keepalive_peers)
+ bgp_debug_keepalive_peers = list_new ();
+
+ if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, peer, NULL))
+ {
+ vty_out (vty, "BGP keepalive debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ bgp_debug_list_add_entry(bgp_debug_keepalive_peers, peer, NULL);
+
+ if (vty->node == CONFIG_NODE)
+ DEBUG_ON (keepalive, KEEPALIVE);
+ else
+ {
+ TERM_DEBUG_ON (keepalive, KEEPALIVE);
+ vty_out (vty, "BGP keepalives debugging is on for %s%s", argv[0], VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (no_debug_bgp_keepalive,
no_debug_bgp_keepalive_cmd,
"no debug bgp keepalives",
@@ -537,6 +740,8 @@ DEFUN (no_debug_bgp_keepalive,
BGP_STR
"BGP keepalives\n")
{
+ bgp_debug_list_free(bgp_debug_keepalive_peers);
+
if (vty->node == CONFIG_NODE)
DEBUG_OFF (keepalive, KEEPALIVE);
else
@@ -547,13 +752,49 @@ DEFUN (no_debug_bgp_keepalive,
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_keepalive,
- undebug_bgp_keepalive_cmd,
- "undebug bgp keepalives",
- UNDEBUG_STR
+DEFUN (no_debug_bgp_keepalive_peer,
+ no_debug_bgp_keepalive_peer_cmd,
+ "no debug bgp keepalives (A.B.C.D|X:X::X:X|WORD)",
+ NO_STR
+ DEBUG_STR
BGP_STR
- "BGP keepalives\n")
+ "BGP keepalives\n"
+ "BGP neighbor IP address to debug\n"
+ "BGP IPv6 neighbor to debug\n"
+ "BGP neighbor on interface to debug\n")
+{
+ int found_peer = 0;
+ struct peer *peer;
+
+ peer = bgp_find_peer (vty, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (bgp_debug_keepalive_peers && !list_isempty(bgp_debug_keepalive_peers))
+ {
+ found_peer = bgp_debug_list_remove_entry(bgp_debug_keepalive_peers, peer, NULL);
+
+ if (list_isempty(bgp_debug_keepalive_peers))
+ {
+ if (vty->node == CONFIG_NODE)
+ DEBUG_OFF (keepalive, KEEPALIVE);
+ else
+ TERM_DEBUG_OFF (keepalive, KEEPALIVE);
+ }
+ }
+ if (found_peer)
+ vty_out (vty, "BGP keepalives debugging is off for %s%s", argv[0], VTY_NEWLINE);
+ else
+ vty_out (vty, "BGP keepalives debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+/* debug bgp updates */
DEFUN (debug_bgp_update,
debug_bgp_update_cmd,
"debug bgp updates",
@@ -615,74 +856,299 @@ DEFUN (debug_bgp_update_direct,
return CMD_SUCCESS;
}
-DEFUN (no_debug_bgp_update,
- no_debug_bgp_update_cmd,
- "no debug bgp updates",
- NO_STR
+DEFUN (debug_bgp_update_direct_peer,
+ debug_bgp_update_direct_peer_cmd,
+ "debug bgp updates (in|out) (A.B.C.D|X:X::X:X|WORD)",
DEBUG_STR
BGP_STR
- "BGP updates\n")
+ "BGP updates\n"
+ "Inbound updates\n"
+ "Outbound updates\n"
+ "BGP neighbor IP address to debug\n"
+ "BGP IPv6 neighbor to debug\n"
+ "BGP neighbor on interface to debug\n")
{
+ struct peer *peer;
+ int inbound;
+
+ peer = bgp_find_peer (vty, argv[1]);
+ if (!peer)
+ {
+ vty_out (vty, "%s is not a configured peer%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+
+ if (!bgp_debug_update_in_peers)
+ bgp_debug_update_in_peers = list_new ();
+
+ if (!bgp_debug_update_out_peers)
+ bgp_debug_update_out_peers = list_new ();
+
+ if (strncmp ("i", argv[0], 1) == 0)
+ inbound = 1;
+ else
+ inbound = 0;
+
+ if (inbound)
+ {
+ if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, peer, NULL))
+ {
+ vty_out (vty, "BGP inbound update debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ }
+
+ else
+ {
+ if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, peer, NULL))
+ {
+ vty_out (vty, "BGP outbound update debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ }
+
+ if (inbound)
+ bgp_debug_list_add_entry(bgp_debug_update_in_peers, peer, NULL);
+ else
+ bgp_debug_list_add_entry(bgp_debug_update_out_peers, peer, NULL);
+
if (vty->node == CONFIG_NODE)
{
- DEBUG_OFF (update, UPDATE_IN);
- DEBUG_OFF (update, UPDATE_OUT);
+ if (inbound)
+ {
+ DEBUG_OFF (update, UPDATE_OUT);
+ DEBUG_ON (update, UPDATE_IN);
+ }
+ else
+ {
+ DEBUG_OFF (update, UPDATE_IN);
+ DEBUG_ON (update, UPDATE_OUT);
+ }
}
else
{
- TERM_DEBUG_OFF (update, UPDATE_IN);
- TERM_DEBUG_OFF (update, UPDATE_OUT);
- vty_out (vty, "BGP updates debugging is off%s", VTY_NEWLINE);
+ if (inbound)
+ {
+ TERM_DEBUG_OFF (update, UPDATE_OUT);
+ TERM_DEBUG_ON (update, UPDATE_IN);
+ vty_out (vty, "BGP updates debugging is on (inbound) for %s%s", argv[1], VTY_NEWLINE);
+ }
+ else
+ {
+ TERM_DEBUG_OFF (update, UPDATE_IN);
+ TERM_DEBUG_ON (update, UPDATE_OUT);
+ vty_out (vty, "BGP updates debugging is on (outbound) for %s%s", argv[1], VTY_NEWLINE);
+ }
}
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_update,
- undebug_bgp_update_cmd,
- "undebug bgp updates",
- UNDEBUG_STR
+DEFUN (no_debug_bgp_update_direct_peer,
+ no_debug_bgp_update_direct_peer_cmd,
+ "no debug bgp updates (in|out) (A.B.C.D|X:X::X:X|WORD)",
+ NO_STR
+ DEBUG_STR
BGP_STR
- "BGP updates\n")
+ "BGP updates\n"
+ "Inbound updates\n"
+ "Outbound updates\n"
+ "BGP neighbor IP address to debug\n"
+ "BGP IPv6 neighbor to debug\n"
+ "BGP neighbor on interface to debug\n")
+{
+ int inbound;
+ int found_peer = 0;
+ struct peer *peer;
+
+ peer = bgp_find_peer (vty, argv[1]);
+ if (!peer)
+ {
+ vty_out (vty, "%s is not a configured peer%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (strncmp ("i", argv[0], 1) == 0)
+ inbound = 1;
+ else
+ inbound = 0;
+
+ if (inbound && bgp_debug_update_in_peers &&
+ !list_isempty(bgp_debug_update_in_peers))
+ {
+ found_peer = bgp_debug_list_remove_entry(bgp_debug_update_in_peers, peer, NULL);
+
+ if (list_isempty(bgp_debug_update_in_peers))
+ {
+ if (vty->node == CONFIG_NODE)
+ DEBUG_OFF (update, UPDATE_IN);
+ else
+ {
+ TERM_DEBUG_OFF (update, UPDATE_IN);
+ vty_out (vty, "BGP updates debugging (inbound) is off%s", VTY_NEWLINE);
+ }
+ }
+ }
+
+ if (!inbound && bgp_debug_update_out_peers &&
+ !list_isempty(bgp_debug_update_out_peers))
+ {
+ found_peer = bgp_debug_list_remove_entry(bgp_debug_update_out_peers, peer, NULL);
+
+ if (list_isempty(bgp_debug_update_out_peers))
+ {
+ if (vty->node == CONFIG_NODE)
+ DEBUG_OFF (update, UPDATE_OUT);
+ else
+ {
+ TERM_DEBUG_OFF (update, UPDATE_OUT);
+ vty_out (vty, "BGP updates debugging (outbound) is off%s", VTY_NEWLINE);
+ }
+ }
+ }
+
+ if (found_peer)
+ if (inbound)
+ vty_out (vty, "BGP updates debugging (inbound) is off for %s%s", argv[1], VTY_NEWLINE);
+ else
+ vty_out (vty, "BGP updates debugging (outbound) is off for %s%s", argv[1], VTY_NEWLINE);
+ else
+ if (inbound)
+ vty_out (vty, "BGP updates debugging (inbound) was not enabled for %s%s", argv[1], VTY_NEWLINE);
+ else
+ vty_out (vty, "BGP updates debugging (outbound) was not enabled for %s%s", argv[1], VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
-DEFUN (debug_bgp_normal,
- debug_bgp_normal_cmd,
- "debug bgp",
+DEFUN (debug_bgp_update_prefix,
+ debug_bgp_update_prefix_cmd,
+ "debug bgp updates prefix (A.B.C.D/M|X:X::X:X/M)",
DEBUG_STR
- BGP_STR)
+ BGP_STR
+ "BGP updates\n"
+ "Specify a prefix to debug\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "IPv6 prefix <network>/<length>\n")
+
{
+ struct prefix *argv_p;
+ int ret;
+
+ argv_p = prefix_new();
+ ret = str2prefix (argv[0], argv_p);
+ if (!ret)
+ {
+ prefix_free(argv_p);
+ vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+
+ if (!bgp_debug_update_prefixes)
+ bgp_debug_update_prefixes = list_new ();
+
+ if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p))
+ {
+ vty_out (vty, "BGP updates debugging is already enabled for %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p);
+
if (vty->node == CONFIG_NODE)
- DEBUG_ON (normal, NORMAL);
+ {
+ DEBUG_ON (update, UPDATE_PREFIX);
+ }
else
{
- TERM_DEBUG_ON (normal, NORMAL);
- vty_out (vty, "BGP debugging is on%s", VTY_NEWLINE);
+ TERM_DEBUG_ON (update, UPDATE_PREFIX);
+ vty_out (vty, "BGP updates debugging is on for %s%s", argv[0], VTY_NEWLINE);
}
+
return CMD_SUCCESS;
}
-DEFUN (no_debug_bgp_normal,
- no_debug_bgp_normal_cmd,
- "no debug bgp",
+DEFUN (no_debug_bgp_update_prefix,
+ no_debug_bgp_update_prefix_cmd,
+ "no debug bgp updates prefix (A.B.C.D/M|X:X::X:X/M)",
NO_STR
DEBUG_STR
- BGP_STR)
+ BGP_STR
+ "BGP updates\n"
+ "Specify a prefix to debug\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "IPv6 prefix <network>/<length>\n")
+
{
+ struct prefix *argv_p;
+ int found_prefix = 0;
+ int ret;
+
+ argv_p = prefix_new();
+ ret = str2prefix (argv[0], argv_p);
+ if (!ret)
+ {
+ prefix_free(argv_p);
+ vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (bgp_debug_update_prefixes && !list_isempty(bgp_debug_update_prefixes))
+ {
+ found_prefix = bgp_debug_list_remove_entry(bgp_debug_update_prefixes, NULL, argv_p);
+
+ if (list_isempty(bgp_debug_update_prefixes))
+ {
+ if (vty->node == CONFIG_NODE)
+ {
+ DEBUG_OFF (update, UPDATE_PREFIX);
+ }
+ else
+ {
+ TERM_DEBUG_OFF (update, UPDATE_PREFIX);
+ vty_out (vty, "BGP updates debugging (per prefix) is off%s", VTY_NEWLINE);
+ }
+ }
+ }
+
+ if (found_prefix)
+ vty_out (vty, "BGP updates debugging is off for %s%s", argv[0], VTY_NEWLINE);
+ else
+ vty_out (vty, "BGP updates debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_update,
+ no_debug_bgp_update_cmd,
+ "no debug bgp updates",
+ NO_STR
+ DEBUG_STR
+ BGP_STR
+ "BGP updates\n")
+{
+ bgp_debug_list_free(bgp_debug_update_in_peers);
+ bgp_debug_list_free(bgp_debug_update_out_peers);
+ bgp_debug_list_free(bgp_debug_update_prefixes);
+
if (vty->node == CONFIG_NODE)
- DEBUG_OFF (normal, NORMAL);
+ {
+ DEBUG_OFF (update, UPDATE_IN);
+ DEBUG_OFF (update, UPDATE_OUT);
+ DEBUG_OFF (update, UPDATE_PREFIX);
+ }
else
{
- TERM_DEBUG_OFF (normal, NORMAL);
- vty_out (vty, "BGP debugging is off%s", VTY_NEWLINE);
+ TERM_DEBUG_OFF (update, UPDATE_IN);
+ TERM_DEBUG_OFF (update, UPDATE_OUT);
+ TERM_DEBUG_OFF (update, UPDATE_PREFIX);
+ vty_out (vty, "BGP updates debugging is off%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_normal,
- undebug_bgp_normal_cmd,
- "undebug bgp",
- UNDEBUG_STR
- BGP_STR)
-
+/* debug bgp zebra */
DEFUN (debug_bgp_zebra,
debug_bgp_zebra_cmd,
"debug bgp zebra",
@@ -700,6 +1166,51 @@ DEFUN (debug_bgp_zebra,
return CMD_SUCCESS;
}
+DEFUN (debug_bgp_zebra_prefix,
+ debug_bgp_zebra_prefix_cmd,
+ "debug bgp zebra prefix (A.B.C.D/M|X:X::X:X/M)",
+ DEBUG_STR
+ BGP_STR
+ "BGP Zebra messages\n"
+ "Specify a prefix to debug\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "IPv6 prefix <network>/<length>\n")
+
+{
+ struct prefix *argv_p;
+ int ret;
+
+ argv_p = prefix_new();
+ ret = str2prefix (argv[0], argv_p);
+ if (!ret)
+ {
+ prefix_free(argv_p);
+ vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!bgp_debug_zebra_prefixes)
+ bgp_debug_zebra_prefixes = list_new();
+
+ if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, argv_p))
+ {
+ vty_out (vty, "BGP zebra debugging is already enabled for %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, argv_p);
+
+ if (vty->node == CONFIG_NODE)
+ DEBUG_ON (zebra, ZEBRA);
+ else
+ {
+ TERM_DEBUG_ON (zebra, ZEBRA);
+ vty_out (vty, "BGP zebra debugging is on for %s%s", argv[0], VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (no_debug_bgp_zebra,
no_debug_bgp_zebra_cmd,
"no debug bgp zebra",
@@ -708,6 +1219,8 @@ DEFUN (no_debug_bgp_zebra,
BGP_STR
"BGP Zebra messages\n")
{
+ bgp_debug_list_free(bgp_debug_zebra_prefixes);
+
if (vty->node == CONFIG_NODE)
DEBUG_OFF (zebra, ZEBRA);
else
@@ -718,43 +1231,82 @@ DEFUN (no_debug_bgp_zebra,
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_zebra,
- undebug_bgp_zebra_cmd,
- "undebug bgp zebra",
- UNDEBUG_STR
+DEFUN (no_debug_bgp_zebra_prefix,
+ no_debug_bgp_zebra_prefix_cmd,
+ "no debug bgp zebra prefix (A.B.C.D/M|X:X::X:X/M)",
+ NO_STR
+ DEBUG_STR
BGP_STR
- "BGP Zebra messages\n")
+ "BGP Zebra messages\n"
+ "Specify a prefix to debug\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "IPv6 prefix <network>/<length>\n")
+
+{
+ struct prefix *argv_p;
+ int found_prefix = 0;
+ int ret;
+
+ argv_p = prefix_new();
+ ret = str2prefix (argv[0], argv_p);
+ if (!ret)
+ {
+ prefix_free(argv_p);
+ vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (bgp_debug_zebra_prefixes && !list_isempty(bgp_debug_zebra_prefixes))
+ {
+ found_prefix = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, NULL, argv_p);
+
+ if (list_isempty(bgp_debug_zebra_prefixes))
+ {
+ if (vty->node == CONFIG_NODE)
+ DEBUG_OFF (zebra, ZEBRA);
+ else
+ {
+ TERM_DEBUG_OFF (zebra, ZEBRA);
+ vty_out (vty, "BGP zebra debugging is off%s", VTY_NEWLINE);
+ }
+ }
+ }
-DEFUN (no_debug_bgp_all,
- no_debug_bgp_all_cmd,
- "no debug all bgp",
+ if (found_prefix)
+ vty_out (vty, "BGP zebra debugging is off for %s%s", argv[0], VTY_NEWLINE);
+ else
+ vty_out (vty, "BGP zebra debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp,
+ no_debug_bgp_cmd,
+ "no debug bgp",
NO_STR
DEBUG_STR
- "Enable all debugging\n"
BGP_STR)
{
- TERM_DEBUG_OFF (normal, NORMAL);
- TERM_DEBUG_OFF (events, EVENTS);
+ bgp_debug_list_free(bgp_debug_neighbor_events_peers);
+ bgp_debug_list_free(bgp_debug_keepalive_peers);
+ bgp_debug_list_free(bgp_debug_update_in_peers);
+ bgp_debug_list_free(bgp_debug_update_out_peers);
+ bgp_debug_list_free(bgp_debug_update_prefixes);
+ bgp_debug_list_free(bgp_debug_zebra_prefixes);
+
TERM_DEBUG_OFF (keepalive, KEEPALIVE);
TERM_DEBUG_OFF (update, UPDATE_IN);
TERM_DEBUG_OFF (update, UPDATE_OUT);
+ TERM_DEBUG_OFF (update, UPDATE_PREFIX);
TERM_DEBUG_OFF (as4, AS4);
TERM_DEBUG_OFF (as4, AS4_SEGMENT);
- TERM_DEBUG_OFF (fsm, FSM);
- TERM_DEBUG_OFF (filter, FILTER);
+ TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS);
TERM_DEBUG_OFF (zebra, ZEBRA);
vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
-ALIAS (no_debug_bgp_all,
- undebug_bgp_all_cmd,
- "undebug all bgp",
- UNDEBUG_STR
- "Enable all debugging\n"
- BGP_STR)
-
DEFUN (show_debugging_bgp,
show_debugging_bgp_cmd,
"show debugging bgp",
@@ -764,28 +1316,39 @@ DEFUN (show_debugging_bgp,
{
vty_out (vty, "BGP debugging status:%s", VTY_NEWLINE);
- if (BGP_DEBUG (normal, NORMAL))
- vty_out (vty, " BGP debugging is on%s", VTY_NEWLINE);
- if (BGP_DEBUG (events, EVENTS))
- vty_out (vty, " BGP events debugging is on%s", VTY_NEWLINE);
- if (BGP_DEBUG (keepalive, KEEPALIVE))
- vty_out (vty, " BGP keepalives debugging is on%s", VTY_NEWLINE);
- if (BGP_DEBUG (update, UPDATE_IN) && BGP_DEBUG (update, UPDATE_OUT))
- vty_out (vty, " BGP updates debugging is on%s", VTY_NEWLINE);
- else if (BGP_DEBUG (update, UPDATE_IN))
- vty_out (vty, " BGP updates debugging is on (inbound)%s", VTY_NEWLINE);
- else if (BGP_DEBUG (update, UPDATE_OUT))
- vty_out (vty, " BGP updates debugging is on (outbound)%s", VTY_NEWLINE);
- if (BGP_DEBUG (fsm, FSM))
- vty_out (vty, " BGP fsm debugging is on%s", VTY_NEWLINE);
- if (BGP_DEBUG (filter, FILTER))
- vty_out (vty, " BGP filter debugging is on%s", VTY_NEWLINE);
- if (BGP_DEBUG (zebra, ZEBRA))
- vty_out (vty, " BGP zebra debugging is on%s", VTY_NEWLINE);
if (BGP_DEBUG (as4, AS4))
vty_out (vty, " BGP as4 debugging is on%s", VTY_NEWLINE);
+
if (BGP_DEBUG (as4, AS4_SEGMENT))
vty_out (vty, " BGP as4 aspath segment debugging is on%s", VTY_NEWLINE);
+
+ if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
+ bgp_debug_list_print (vty, " BGP neighbor-events debugging is on",
+ bgp_debug_neighbor_events_peers);
+
+ if (BGP_DEBUG (keepalive, KEEPALIVE))
+ bgp_debug_list_print (vty, " BGP keepalives debugging is on",
+ bgp_debug_keepalive_peers);
+
+ if (BGP_DEBUG (nht, NHT))
+ vty_out (vty, " BGP next-hop tracking debugging is on%s", VTY_NEWLINE);
+
+ if (BGP_DEBUG (update, UPDATE_PREFIX))
+ bgp_debug_list_print (vty, " BGP updates debugging is on for",
+ bgp_debug_update_prefixes);
+
+ if (BGP_DEBUG (update, UPDATE_IN))
+ bgp_debug_list_print (vty, " BGP updates debugging is on (inbound)",
+ bgp_debug_update_in_peers);
+
+ if (BGP_DEBUG (update, UPDATE_OUT))
+ bgp_debug_list_print (vty, " BGP updates debugging is on (outbound)",
+ bgp_debug_update_out_peers);
+
+ if (BGP_DEBUG (zebra, ZEBRA))
+ bgp_debug_list_print (vty, " BGP zebra debugging is on",
+ bgp_debug_zebra_prefixes);
+
vty_out (vty, "%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -795,12 +1358,6 @@ bgp_config_write_debug (struct vty *vty)
{
int write = 0;
- if (CONF_BGP_DEBUG (normal, NORMAL))
- {
- vty_out (vty, "debug bgp%s", VTY_NEWLINE);
- write++;
- }
-
if (CONF_BGP_DEBUG (as4, AS4))
{
vty_out (vty, "debug bgp as4%s", VTY_NEWLINE);
@@ -813,12 +1370,6 @@ bgp_config_write_debug (struct vty *vty)
write++;
}
- if (CONF_BGP_DEBUG (events, EVENTS))
- {
- vty_out (vty, "debug bgp events%s", VTY_NEWLINE);
- write++;
- }
-
if (CONF_BGP_DEBUG (keepalive, KEEPALIVE))
{
vty_out (vty, "debug bgp keepalives%s", VTY_NEWLINE);
@@ -841,21 +1392,21 @@ bgp_config_write_debug (struct vty *vty)
write++;
}
- if (CONF_BGP_DEBUG (fsm, FSM))
+ if (CONF_BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
{
- vty_out (vty, "debug bgp fsm%s", VTY_NEWLINE);
+ vty_out (vty, "debug bgp neighbor-events%s", VTY_NEWLINE);
write++;
}
- if (CONF_BGP_DEBUG (filter, FILTER))
+ if (CONF_BGP_DEBUG (zebra, ZEBRA))
{
- vty_out (vty, "debug bgp filters%s", VTY_NEWLINE);
+ vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE);
write++;
}
- if (CONF_BGP_DEBUG (zebra, ZEBRA))
+ if (CONF_BGP_DEBUG (nht, NHT))
{
- vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE);
+ vty_out (vty, "debug bgp nht%s", VTY_NEWLINE);
write++;
}
@@ -881,51 +1432,189 @@ bgp_debug_init (void)
install_element (ENABLE_NODE, &debug_bgp_as4_segment_cmd);
install_element (CONFIG_NODE, &debug_bgp_as4_segment_cmd);
- install_element (ENABLE_NODE, &debug_bgp_fsm_cmd);
- install_element (CONFIG_NODE, &debug_bgp_fsm_cmd);
- install_element (ENABLE_NODE, &debug_bgp_events_cmd);
- install_element (CONFIG_NODE, &debug_bgp_events_cmd);
- install_element (ENABLE_NODE, &debug_bgp_filter_cmd);
- install_element (CONFIG_NODE, &debug_bgp_filter_cmd);
+ install_element (ENABLE_NODE, &debug_bgp_neighbor_events_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_neighbor_events_cmd);
+ install_element (ENABLE_NODE, &debug_bgp_nht_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_nht_cmd);
install_element (ENABLE_NODE, &debug_bgp_keepalive_cmd);
install_element (CONFIG_NODE, &debug_bgp_keepalive_cmd);
install_element (ENABLE_NODE, &debug_bgp_update_cmd);
install_element (CONFIG_NODE, &debug_bgp_update_cmd);
install_element (ENABLE_NODE, &debug_bgp_update_direct_cmd);
install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd);
- install_element (ENABLE_NODE, &debug_bgp_normal_cmd);
- install_element (CONFIG_NODE, &debug_bgp_normal_cmd);
install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
+ /* deb bgp updates [in|out] A.B.C.D */
+ install_element (ENABLE_NODE, &debug_bgp_update_direct_peer_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_update_direct_peer_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_update_direct_peer_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_update_direct_peer_cmd);
+
+ /* deb bgp updates prefix A.B.C.D/M */
+ install_element (ENABLE_NODE, &debug_bgp_update_prefix_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_update_prefix_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_update_prefix_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_update_prefix_cmd);
+
+ /* deb bgp zebra prefix A.B.C.D/M */
+ install_element (ENABLE_NODE, &debug_bgp_zebra_prefix_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_zebra_prefix_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_zebra_prefix_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_zebra_prefix_cmd);
+
install_element (ENABLE_NODE, &no_debug_bgp_as4_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_as4_cmd);
install_element (CONFIG_NODE, &no_debug_bgp_as4_cmd);
install_element (ENABLE_NODE, &no_debug_bgp_as4_segment_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_as4_segment_cmd);
install_element (CONFIG_NODE, &no_debug_bgp_as4_segment_cmd);
- install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
- install_element (CONFIG_NODE, &no_debug_bgp_fsm_cmd);
- install_element (ENABLE_NODE, &no_debug_bgp_events_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_events_cmd);
- install_element (CONFIG_NODE, &no_debug_bgp_events_cmd);
- install_element (ENABLE_NODE, &no_debug_bgp_filter_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_filter_cmd);
- install_element (CONFIG_NODE, &no_debug_bgp_filter_cmd);
+ /* deb bgp neighbor-events A.B.C.D */
+ install_element (ENABLE_NODE, &debug_bgp_neighbor_events_peer_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_neighbor_events_peer_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_peer_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_peer_cmd);
+
+ /* deb bgp keepalive A.B.C.D */
+ install_element (ENABLE_NODE, &debug_bgp_keepalive_peer_cmd);
+ install_element (CONFIG_NODE, &debug_bgp_keepalive_peer_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_keepalive_peer_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_keepalive_peer_cmd);
+
+ install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_nht_cmd);
+ install_element (CONFIG_NODE, &no_debug_bgp_nht_cmd);
install_element (ENABLE_NODE, &no_debug_bgp_keepalive_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_keepalive_cmd);
install_element (CONFIG_NODE, &no_debug_bgp_keepalive_cmd);
install_element (ENABLE_NODE, &no_debug_bgp_update_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_update_cmd);
install_element (CONFIG_NODE, &no_debug_bgp_update_cmd);
- install_element (ENABLE_NODE, &no_debug_bgp_normal_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_normal_cmd);
- install_element (CONFIG_NODE, &no_debug_bgp_normal_cmd);
install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_zebra_cmd);
install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd);
- install_element (ENABLE_NODE, &no_debug_bgp_all_cmd);
- install_element (ENABLE_NODE, &undebug_bgp_all_cmd);
+ install_element (ENABLE_NODE, &no_debug_bgp_cmd);
+}
+
+/* Return true if this prefix is on the per_prefix_list of prefixes to debug
+ * for BGP_DEBUG_TYPE
+ */
+static int
+bgp_debug_per_prefix (struct prefix *p, unsigned long term_bgp_debug_type,
+ unsigned int BGP_DEBUG_TYPE, struct list *per_prefix_list)
+{
+ struct bgp_debug_filter *filter;
+ struct listnode *node, *nnode;
+
+ if (term_bgp_debug_type & BGP_DEBUG_TYPE)
+ {
+ /* We are debugging all prefixes so return true */
+ if (!per_prefix_list || list_isempty(per_prefix_list))
+ return 1;
+
+ else
+ {
+ if (!p)
+ return 0;
+
+ for (ALL_LIST_ELEMENTS (per_prefix_list, node, nnode, filter))
+ if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p))
+ return 1;
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/* Return true if this peer is on the per_peer_list of peers to debug
+ * for BGP_DEBUG_TYPE
+ */
+static int
+bgp_debug_per_peer(struct peer *peer, unsigned long term_bgp_debug_type,
+ unsigned int BGP_DEBUG_TYPE, struct list *per_peer_list)
+{
+ struct bgp_debug_filter *filter;
+ struct listnode *node, *nnode;
+
+ if (term_bgp_debug_type & BGP_DEBUG_TYPE)
+ {
+ /* We are debugging all peers so return true */
+ if (!per_peer_list || list_isempty(per_peer_list))
+ return 1;
+
+ else
+ {
+ if (!peer)
+ return 0;
+
+ for (ALL_LIST_ELEMENTS (per_peer_list, node, nnode, filter))
+ if (filter->peer == peer)
+ return 1;
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+int
+bgp_debug_neighbor_events (struct peer *peer)
+{
+ return bgp_debug_per_peer (peer,
+ term_bgp_debug_neighbor_events,
+ BGP_DEBUG_NEIGHBOR_EVENTS,
+ bgp_debug_neighbor_events_peers);
+}
+
+int
+bgp_debug_keepalive (struct peer *peer)
+{
+ return bgp_debug_per_peer (peer,
+ term_bgp_debug_keepalive,
+ BGP_DEBUG_KEEPALIVE,
+ bgp_debug_keepalive_peers);
+}
+
+int
+bgp_debug_update (struct peer *peer, struct prefix *p, unsigned int inbound)
+{
+ if (inbound)
+ {
+ if (bgp_debug_per_peer (peer, term_bgp_debug_update, BGP_DEBUG_UPDATE_IN,
+ bgp_debug_update_in_peers))
+ return 1;
+ }
+
+ /* outbound */
+ else
+ {
+ if (bgp_debug_per_peer (peer, term_bgp_debug_update,
+ BGP_DEBUG_UPDATE_OUT,
+ bgp_debug_update_out_peers))
+ return 1;
+ }
+
+
+ if (BGP_DEBUG (update, UPDATE_PREFIX))
+ {
+ if (bgp_debug_per_prefix (p, term_bgp_debug_update,
+ BGP_DEBUG_UPDATE_PREFIX,
+ bgp_debug_update_prefixes))
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+bgp_debug_zebra (struct prefix *p)
+{
+ if (BGP_DEBUG (zebra, ZEBRA))
+ {
+ if (bgp_debug_per_prefix (p, term_bgp_debug_zebra, BGP_DEBUG_ZEBRA,
+ bgp_debug_zebra_prefixes))
+ return 1;
+ }
+
+ return 0;
}
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index ce8547b0..b8ad7b9c 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -59,44 +59,49 @@ extern void bgp_packet_dump (struct stream *);
extern int debug (unsigned int option);
extern unsigned long conf_bgp_debug_as4;
-extern unsigned long conf_bgp_debug_fsm;
-extern unsigned long conf_bgp_debug_events;
+extern unsigned long conf_bgp_debug_neighbor_events;
extern unsigned long conf_bgp_debug_packet;
-extern unsigned long conf_bgp_debug_filter;
extern unsigned long conf_bgp_debug_keepalive;
extern unsigned long conf_bgp_debug_update;
-extern unsigned long conf_bgp_debug_normal;
extern unsigned long conf_bgp_debug_zebra;
+extern unsigned long conf_bgp_debug_nht;
extern unsigned long term_bgp_debug_as4;
-extern unsigned long term_bgp_debug_fsm;
-extern unsigned long term_bgp_debug_events;
+extern unsigned long term_bgp_debug_neighbor_events;
extern unsigned long term_bgp_debug_packet;
-extern unsigned long term_bgp_debug_filter;
extern unsigned long term_bgp_debug_keepalive;
extern unsigned long term_bgp_debug_update;
-extern unsigned long term_bgp_debug_normal;
extern unsigned long term_bgp_debug_zebra;
+extern unsigned long term_bgp_debug_nht;
+
+extern struct list *bgp_debug_neighbor_events_peers;
+extern struct list *bgp_debug_keepalive_peers;
+extern struct list *bgp_debug_update_in_peers;
+extern struct list *bgp_debug_update_out_peers;
+extern struct list *bgp_debug_update_prefixes;
+extern struct list *bgp_debug_zebra_prefixes;
+
+struct bgp_debug_filter
+{
+ struct peer *peer;
+ struct prefix *p;
+};
#define BGP_DEBUG_AS4 0x01
#define BGP_DEBUG_AS4_SEGMENT 0x02
-#define BGP_DEBUG_FSM 0x01
-#define BGP_DEBUG_EVENTS 0x01
+#define BGP_DEBUG_NEIGHBOR_EVENTS 0x01
#define BGP_DEBUG_PACKET 0x01
-#define BGP_DEBUG_FILTER 0x01
#define BGP_DEBUG_KEEPALIVE 0x01
#define BGP_DEBUG_UPDATE_IN 0x01
#define BGP_DEBUG_UPDATE_OUT 0x02
-#define BGP_DEBUG_NORMAL 0x01
+#define BGP_DEBUG_UPDATE_PREFIX 0x04
#define BGP_DEBUG_ZEBRA 0x01
+#define BGP_DEBUG_NHT 0x01
#define BGP_DEBUG_PACKET_SEND 0x01
#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
-#define BGP_DEBUG_PACKET_RECV 0x01
-#define BGP_DEBUG_PACKET_RECV_DETAIL 0x02
-
#define CONF_DEBUG_ON(a, b) (conf_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
#define CONF_DEBUG_OFF(a, b) (conf_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
@@ -124,5 +129,9 @@ extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *);
extern const struct message bgp_status_msg[];
extern const int bgp_status_msg_max;
+extern int bgp_debug_neighbor_events(struct peer *peer);
+extern int bgp_debug_keepalive(struct peer *peer);
+extern int bgp_debug_update(struct peer *peer, struct prefix *p, unsigned int inbound);
+extern int bgp_debug_zebra(struct prefix *p);
#endif /* _QUAGGA_BGP_DEBUG_H */
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 5d69b42c..11b02768 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "prefix.h"
#include "command.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_ecommunity.h"
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index 26819fc1..fd282b8e 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -25,6 +25,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "buffer.h"
#include "filter.h"
+#include "linklist.h"
+#include "prefix.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_aspath.h"
@@ -48,10 +50,10 @@ struct as_list_master
struct as_list_list str;
/* Hook function which is executed when new access_list is added. */
- void (*add_hook) (void);
+ void (*add_hook) (char *);
/* Hook function which is executed when access_list is deleted. */
- void (*delete_hook) (void);
+ void (*delete_hook) (const char *);
};
/* Element of AS path filter. */
@@ -145,6 +147,11 @@ as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter)
else
aslist->head = asfilter;
aslist->tail = asfilter;
+
+ /* Run hook function. */
+ if (as_list_master.add_hook)
+ (*as_list_master.add_hook) (aslist->name);
+
}
/* Lookup as_list from list of as_list by name. */
@@ -278,13 +285,7 @@ as_list_get (const char *name)
aslist = as_list_lookup (name);
if (aslist == NULL)
- {
- aslist = as_list_insert (name);
-
- /* Run hook function. */
- if (as_list_master.add_hook)
- (*as_list_master.add_hook) ();
- }
+ aslist = as_list_insert (name);
return aslist;
}
@@ -345,6 +346,8 @@ as_list_empty (struct as_list *aslist)
static void
as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
{
+ char *name = strdup (aslist->name);
+
if (asfilter->next)
asfilter->next->prev = asfilter->prev;
else
@@ -363,7 +366,9 @@ as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
/* Run hook function. */
if (as_list_master.delete_hook)
- (*as_list_master.delete_hook) ();
+ (*as_list_master.delete_hook) (name);
+ if (name)
+ free(name);
}
static int
@@ -396,14 +401,14 @@ as_list_apply (struct as_list *aslist, void *object)
/* Add hook function. */
void
-as_list_add_hook (void (*func) (void))
+as_list_add_hook (void (*func) (char *))
{
as_list_master.add_hook = func;
}
/* Delete hook function. */
void
-as_list_delete_hook (void (*func) (void))
+as_list_delete_hook (void (*func) (const char *))
{
as_list_master.delete_hook = func;
}
@@ -567,7 +572,7 @@ DEFUN (no_ip_as_path_all,
/* Run hook function. */
if (as_list_master.delete_hook)
- (*as_list_master.delete_hook) ();
+ (*as_list_master.delete_hook) (argv[0]);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h
index c1da9041..03447942 100644
--- a/bgpd/bgp_filter.h
+++ b/bgpd/bgp_filter.h
@@ -33,7 +33,7 @@ extern void bgp_filter_reset (void);
extern enum as_filter_type as_list_apply (struct as_list *, void *);
extern struct as_list *as_list_lookup (const char *);
-extern void as_list_add_hook (void (*func) (void));
-extern void as_list_delete_hook (void (*func) (void));
+extern void as_list_add_hook (void (*func) (char *));
+extern void as_list_delete_hook (void (*func) (const char *));
#endif /* _QUAGGA_BGP_FILTER_H */
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index c4cfd58e..7dd0b8e2 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -42,6 +42,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_dump.h"
#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_nht.h"
#ifdef HAVE_SNMP
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */
@@ -63,11 +65,101 @@ static int bgp_keepalive_timer (struct thread *);
/* BGP FSM functions. */
static int bgp_start (struct peer *);
-/* BGP start timer jitter. */
-static int
-bgp_start_jitter (int time)
+static void
+peer_xfer_stats (struct peer *peer_dst, struct peer *peer_src)
{
- return ((random () % (time + 1)) - (time / 2));
+ /* Copy stats over. These are only the pre-established state stats */
+ peer_dst->open_in += peer_src->open_in;
+ peer_dst->open_out += peer_src->open_out;
+ peer_dst->keepalive_in += peer_src->keepalive_in;
+ peer_dst->keepalive_out += peer_src->keepalive_out;
+ peer_dst->notify_in += peer_src->notify_in;
+ peer_dst->notify_out += peer_src->notify_out;
+ peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in;
+ peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out;
+}
+
+static struct peer *
+peer_xfer_conn(struct peer *from_peer)
+{
+ struct peer *peer;
+ afi_t afi;
+ safi_t safi;
+ int fd;
+ int status, pstatus;
+
+ assert(from_peer != NULL);
+
+ peer = from_peer->doppelganger;
+
+ if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ return from_peer;
+
+ BGP_WRITE_OFF(peer->t_write);
+ BGP_READ_OFF(peer->t_read);
+ BGP_WRITE_OFF(from_peer->t_write);
+ BGP_READ_OFF(from_peer->t_read);
+
+ fd = peer->fd;
+ peer->fd = from_peer->fd;
+ from_peer->fd = fd;
+ stream_reset(peer->ibuf);
+ stream_fifo_clean(peer->obuf);
+ stream_fifo_clean(from_peer->obuf);
+
+ peer->v_holdtime = from_peer->v_holdtime;
+ peer->v_keepalive = from_peer->v_keepalive;
+ peer->routeadv = from_peer->routeadv;
+ peer->v_routeadv = from_peer->v_routeadv;
+ peer->v_gr_restart = from_peer->v_gr_restart;
+ peer->cap = from_peer->cap;
+ status = peer->status;
+ pstatus = peer->ostatus;
+ peer->status = from_peer->status;
+ peer->ostatus = from_peer->ostatus;
+ from_peer->status = status;
+ from_peer->ostatus = pstatus;
+ peer->remote_id = from_peer->remote_id;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ peer->af_flags[afi][safi] = from_peer->af_flags[afi][safi];
+ peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
+ peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
+ peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
+ peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi];
+ peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
+ }
+
+ if (bgp_getsockname(peer) < 0)
+ {
+ zlog_err ("%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)",
+ (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""),
+ peer->host, peer->fd, from_peer->fd);
+ bgp_stop(peer);
+ bgp_stop(from_peer);
+ return NULL;
+ }
+ if (from_peer->status > Active)
+ {
+ if (bgp_getsockname(from_peer) < 0)
+ {
+ zlog_err ("%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)",
+ (CHECK_FLAG (from_peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""),
+ from_peer->host, from_peer->fd, peer->fd);
+ bgp_stop(from_peer);
+ from_peer = NULL;
+ }
+ }
+
+ BGP_READ_ON(peer->t_read, bgp_read, peer->fd);
+ BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+
+ if (from_peer)
+ peer_xfer_stats(peer, from_peer);
+
+ return(peer);
}
/* Check if suppress start/restart of sessions to peer. */
@@ -81,8 +173,6 @@ bgp_start_jitter (int time)
void
bgp_timer_set (struct peer *peer)
{
- int jitter = 0;
-
switch (peer->status)
{
case Idle:
@@ -95,9 +185,8 @@ bgp_timer_set (struct peer *peer)
}
else
{
- jitter = bgp_start_jitter (peer->v_start);
BGP_TIMER_ON (peer->t_start, bgp_start_timer,
- peer->v_start + jitter);
+ peer->v_start);
}
BGP_TIMER_OFF (peer->t_connect);
BGP_TIMER_OFF (peer->t_holdtime);
@@ -106,7 +195,7 @@ bgp_timer_set (struct peer *peer)
break;
case Connect:
- /* After start timer is expired, the peer moves to Connnect
+ /* After start timer is expired, the peer moves to Connect
status. Make sure start timer is off and connect timer is
on. */
BGP_TIMER_OFF (peer->t_start);
@@ -205,6 +294,7 @@ bgp_timer_set (struct peer *peer)
BGP_TIMER_OFF (peer->t_holdtime);
BGP_TIMER_OFF (peer->t_keepalive);
BGP_TIMER_OFF (peer->t_routeadv);
+ break;
}
}
@@ -218,9 +308,8 @@ bgp_start_timer (struct thread *thread)
peer = THREAD_ARG (thread);
peer->t_start = NULL;
- if (BGP_DEBUG (fsm, FSM))
- zlog (peer->log, LOG_DEBUG,
- "%s [FSM] Timer (start timer expire).", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (start timer expire).", peer->host);
THREAD_VAL (thread) = BGP_Start;
bgp_event (thread); /* bgp_event unlocks peer */
@@ -233,18 +322,27 @@ static int
bgp_connect_timer (struct thread *thread)
{
struct peer *peer;
+ int ret;
peer = THREAD_ARG (thread);
peer->t_connect = NULL;
- if (BGP_DEBUG (fsm, FSM))
- zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
- peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host);
- THREAD_VAL (thread) = ConnectRetry_timer_expired;
- bgp_event (thread); /* bgp_event unlocks peer */
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ {
+ bgp_stop(peer);
+ ret = -1;
+ }
+ else
+ {
+ THREAD_VAL (thread) = ConnectRetry_timer_expired;
+ bgp_event (thread); /* bgp_event unlocks peer */
+ ret = 0;
+ }
- return 0;
+ return ret;
}
/* BGP holdtime timer. */
@@ -256,10 +354,8 @@ bgp_holdtime_timer (struct thread *thread)
peer = THREAD_ARG (thread);
peer->t_holdtime = NULL;
- if (BGP_DEBUG (fsm, FSM))
- zlog (peer->log, LOG_DEBUG,
- "%s [FSM] Timer (holdtime timer expire)",
- peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Timer (holdtime timer expire)", peer->host);
THREAD_VAL (thread) = Hold_Timer_expired;
bgp_event (thread); /* bgp_event unlocks peer */
@@ -276,10 +372,8 @@ bgp_keepalive_timer (struct thread *thread)
peer = THREAD_ARG (thread);
peer->t_keepalive = NULL;
- if (BGP_DEBUG (fsm, FSM))
- zlog (peer->log, LOG_DEBUG,
- "%s [FSM] Timer (keepalive timer expire)",
- peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Timer (keepalive timer expire)", peer->host);
THREAD_VAL (thread) = KeepAlive_timer_expired;
bgp_event (thread); /* bgp_event unlocks peer */
@@ -288,24 +382,40 @@ bgp_keepalive_timer (struct thread *thread)
}
static int
+bgp_routeq_empty (struct peer *peer)
+{
+ afi_t afi;
+ safi_t safi;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ if (!FIFO_EMPTY(&peer->sync[afi][safi]->withdraw) ||
+ !FIFO_EMPTY(&peer->sync[afi][safi]->update))
+ return 0;
+ }
+ return 1;
+}
+
+static int
bgp_routeadv_timer (struct thread *thread)
{
struct peer *peer;
peer = THREAD_ARG (thread);
peer->t_routeadv = NULL;
+ peer->radv_adjusted = 0;
- if (BGP_DEBUG (fsm, FSM))
- zlog (peer->log, LOG_DEBUG,
- "%s [FSM] Timer (routeadv timer expire)",
- peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Timer (routeadv timer expire)", peer->host);
peer->synctime = bgp_clock ();
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
- BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
- peer->v_routeadv);
+ /* MRAI timer is no longer restarted here, it would be done
+ * when the FIFO is built.
+ */
return 0;
}
@@ -357,7 +467,7 @@ bgp_graceful_restart_timer_expire (struct thread *thread)
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
BGP_TIMER_OFF (peer->t_gr_stale);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
{
zlog_debug ("%s graceful restart timer expired", peer->host);
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
@@ -378,7 +488,7 @@ bgp_graceful_stale_timer_expire (struct thread *thread)
peer = THREAD_ARG (thread);
peer->t_gr_stale = NULL;
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s graceful restart stalepath timer expired", peer->host);
/* NSF delete stale route */
@@ -390,11 +500,396 @@ bgp_graceful_stale_timer_expire (struct thread *thread)
return 0;
}
+static int
+bgp_update_delay_applicable (struct bgp *bgp)
+{
+ /* update_delay_over flag should be reset (set to 0) for any new
+ applicability of the update-delay during BGP process lifetime.
+ And it should be set after an occurence of the update-delay is over)*/
+ if (!bgp->update_delay_over)
+ return 1;
+
+ return 0;
+}
+
+int
+bgp_update_delay_active (struct bgp *bgp)
+{
+ if (bgp->t_update_delay)
+ return 1;
+
+ return 0;
+}
+
+int
+bgp_update_delay_configured (struct bgp *bgp)
+{
+ if (bgp->v_update_delay)
+ return 1;
+
+ return 0;
+}
+
+/* Do the post-processing needed when bgp comes out of the read-only mode
+ on ending the update delay. */
+void
+bgp_update_delay_end (struct bgp *bgp)
+{
+ THREAD_TIMER_OFF (bgp->t_update_delay);
+ THREAD_TIMER_OFF (bgp->t_establish_wait);
+
+ /* Reset update-delay related state */
+ bgp->update_delay_over = 1;
+ bgp->established = 0;
+ bgp->restarted_peers = 0;
+ bgp->implicit_eors = 0;
+ bgp->explicit_eors = 0;
+
+ quagga_timestamp(3, bgp->update_delay_end_time,
+ sizeof(bgp->update_delay_end_time));
+
+ /*
+ * Add an end-of-initial-update marker to the main process queues so that
+ * the route advertisement timer for the peers can be started. Also set
+ * the zebra and peer update hold flags. These flags are used to achieve
+ * three stages in the update-delay post processing:
+ * 1. Finish best-path selection for all the prefixes held on the queues.
+ * (routes in BGP are updated, and peers sync queues are populated too)
+ * 2. As the eoiu mark is reached in the bgp process routine, ship all the
+ * routes to zebra. With that zebra should see updates from BGP close
+ * to each other.
+ * 3. Unblock the peer update writes. With that peer update packing with
+ * the prefixes should be at its maximum.
+ */
+ bgp_add_eoiu_mark(bgp, BGP_TABLE_MAIN);
+ bgp_add_eoiu_mark(bgp, BGP_TABLE_RSCLIENT);
+ bgp->main_zebra_update_hold = 1;
+ bgp->main_peers_update_hold = 1;
+ bgp->rsclient_peers_update_hold = 1;
+
+ /* Resume the queue processing. This should trigger the event that would take
+ care of processing any work that was queued during the read-only mode. */
+ work_queue_unplug(bm->process_main_queue);
+ work_queue_unplug(bm->process_rsclient_queue);
+}
+
+/**
+ * see bgp_fsm.h
+ */
+void
+bgp_start_routeadv (struct bgp *bgp)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ zlog_info("bgp_start_routeadv(), update hold status - main: %d, rsclient: %d",
+ bgp->main_peers_update_hold, bgp->rsclient_peers_update_hold);
+
+ if (bgp->main_peers_update_hold || bgp->rsclient_peers_update_hold)
+ return;
+
+ quagga_timestamp(3, bgp->update_delay_peers_resume_time,
+ sizeof(bgp->update_delay_peers_resume_time));
+
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ {
+ if (peer->status != Established)
+ continue;
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
+ }
+}
+
+/**
+ * see bgp_fsm.h
+ */
+void
+bgp_adjust_routeadv (struct peer *peer)
+{
+ time_t nowtime = bgp_clock();
+ double diff;
+ unsigned long remain;
+
+ /* Bypass checks for special case of MRAI being 0 */
+ if (peer->v_routeadv == 0)
+ {
+ /* Stop existing timer, just in case it is running for a different
+ * duration and schedule write thread immediately.
+ */
+ if (peer->t_routeadv)
+ BGP_TIMER_OFF(peer->t_routeadv);
+
+ peer->synctime = bgp_clock ();
+ BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ return;
+ }
+
+ /* Mark that we've adjusted the timer */
+ peer->radv_adjusted = 1;
+
+
+ /*
+ * CASE I:
+ * If the last update was written more than MRAI back, expire the timer
+ * instantly so that we can send the update out sooner.
+ *
+ * <------- MRAI --------->
+ * |-----------------|-----------------------|
+ * <------------- m ------------>
+ * ^ ^ ^
+ * | | |
+ * | | current time
+ * | timer start
+ * last write
+ *
+ * m > MRAI
+ */
+ diff = difftime(nowtime, peer->last_write);
+ if (diff > (double) peer->v_routeadv)
+ {
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0);
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug ("%s: MRAI timer to expire instantly", peer->host);
+ return;
+ }
+
+ /*
+ * CASE II:
+ * - Find when to expire the MRAI timer.
+ * If MRAI timer is not active, assume we can start it now.
+ *
+ * <------- MRAI --------->
+ * |------------|-----------------------|
+ * <-------- m ----------><----- r ----->
+ * ^ ^ ^
+ * | | |
+ * | | current time
+ * | timer start
+ * last write
+ *
+ * (MRAI - m) < r
+ */
+ if (peer->t_routeadv)
+ remain = thread_timer_remain_second(peer->t_routeadv);
+ else
+ remain = peer->v_routeadv;
+ diff = peer->v_routeadv - diff;
+ if (diff <= (double) remain)
+ {
+ BGP_TIMER_OFF(peer->t_routeadv);
+ BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff);
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug ("%s: MRAI timer to expire in %f secs", peer->host, diff);
+ }
+}
+
+static int
+bgp_maxmed_onstartup_applicable (struct bgp *bgp)
+{
+ if (!bgp->maxmed_onstartup_over)
+ return 1;
+
+ return 0;
+}
+
+int
+bgp_maxmed_onstartup_configured (struct bgp *bgp)
+{
+ if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
+ return 1;
+
+ return 0;
+}
+
+int
+bgp_maxmed_onstartup_active (struct bgp *bgp)
+{
+ if (bgp->t_maxmed_onstartup)
+ return 1;
+
+ return 0;
+}
+
+void
+bgp_maxmed_update (struct bgp *bgp)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer;
+ u_char maxmed_active;
+ u_int32_t maxmed_value;
+
+ if (bgp->v_maxmed_admin)
+ {
+ maxmed_active = 1;
+ maxmed_value = bgp->maxmed_admin_value;
+ }
+ else if (bgp->t_maxmed_onstartup)
+ {
+ maxmed_active = 1;
+ maxmed_value = bgp->maxmed_onstartup_value;
+ }
+ else
+ {
+ maxmed_active = 0;
+ maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
+ }
+
+ if (bgp->maxmed_active != maxmed_active ||
+ bgp->maxmed_value != maxmed_value)
+ {
+ bgp->maxmed_active = maxmed_active;
+ bgp->maxmed_value = maxmed_value;
+
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ bgp_announce_route_all (peer);
+ }
+}
+
+/* The maxmed onstartup timer expiry callback. */
+static int
+bgp_maxmed_onstartup_timer (struct thread *thread)
+{
+ struct bgp *bgp;
+
+ zlog_info ("Max med on startup ended - timer expired.");
+
+ bgp = THREAD_ARG (thread);
+ THREAD_TIMER_OFF (bgp->t_maxmed_onstartup);
+ bgp->maxmed_onstartup_over = 1;
+
+ bgp_maxmed_update(bgp);
+
+ return 0;
+}
+
+static void
+bgp_maxmed_onstartup_begin (struct bgp *bgp)
+{
+ /* Applicable only once in the process lifetime on the startup */
+ if (bgp->maxmed_onstartup_over)
+ return;
+
+ zlog_info ("Begin maxmed onstartup mode - timer %d seconds",
+ bgp->v_maxmed_onstartup);
+
+ THREAD_TIMER_ON (bm->master, bgp->t_maxmed_onstartup,
+ bgp_maxmed_onstartup_timer,
+ bgp, bgp->v_maxmed_onstartup);
+
+ if (!bgp->v_maxmed_admin)
+ {
+ bgp->maxmed_active = 1;
+ bgp->maxmed_value = bgp->maxmed_onstartup_value;
+ }
+
+ /* Route announce to all peers should happen after this in bgp_establish() */
+}
+
+static void
+bgp_maxmed_onstartup_process_status_change(struct peer *peer)
+{
+ if (peer->status == Established && !peer->bgp->established)
+ {
+ bgp_maxmed_onstartup_begin(peer->bgp);
+ }
+}
+
+/* The update delay timer expiry callback. */
+static int
+bgp_update_delay_timer (struct thread *thread)
+{
+ struct bgp *bgp;
+
+ zlog_info ("Update delay ended - timer expired.");
+
+ bgp = THREAD_ARG (thread);
+ THREAD_TIMER_OFF (bgp->t_update_delay);
+ bgp_update_delay_end(bgp);
+
+ return 0;
+}
+
+/* The establish wait timer expiry callback. */
+static int
+bgp_establish_wait_timer (struct thread *thread)
+{
+ struct bgp *bgp;
+
+ zlog_info ("Establish wait - timer expired.");
+
+ bgp = THREAD_ARG (thread);
+ THREAD_TIMER_OFF (bgp->t_establish_wait);
+ bgp_check_update_delay(bgp);
+
+ return 0;
+}
+
+/* Steps to begin the update delay:
+ - initialize queues if needed
+ - stop the queue processing
+ - start the timer */
+static void
+bgp_update_delay_begin (struct bgp *bgp)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ if ((bm->process_main_queue == NULL) ||
+ (bm->process_rsclient_queue == NULL))
+ bgp_process_queue_init();
+
+ /* Stop the processing of queued work. Enqueue shall continue */
+ work_queue_plug(bm->process_main_queue);
+ work_queue_plug(bm->process_rsclient_queue);
+
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ peer->update_delay_over = 0;
+
+ /* Start the update-delay timer */
+ THREAD_TIMER_ON (bm->master, bgp->t_update_delay, bgp_update_delay_timer,
+ bgp, bgp->v_update_delay);
+
+ if (bgp->v_establish_wait != bgp->v_update_delay)
+ THREAD_TIMER_ON (bm->master, bgp->t_establish_wait, bgp_establish_wait_timer,
+ bgp, bgp->v_establish_wait);
+
+ quagga_timestamp(3, bgp->update_delay_begin_time,
+ sizeof(bgp->update_delay_begin_time));
+}
+
+static void
+bgp_update_delay_process_status_change(struct peer *peer)
+{
+ if (peer->status == Established)
+ {
+ if (!peer->bgp->established++)
+ {
+ bgp_update_delay_begin(peer->bgp);
+ zlog_info ("Begin read-only mode - update-delay timer %d seconds",
+ peer->bgp->v_update_delay);
+ }
+ if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV))
+ bgp_update_restarted_peers(peer);
+ }
+ if (peer->ostatus == Established && bgp_update_delay_active(peer->bgp))
+ {
+ /* Adjust the update-delay state to account for this flap.
+ NOTE: Intentionally skipping adjusting implicit_eors or explicit_eors
+ counters. Extra sanity check in bgp_check_update_delay() should
+ be enough to take care of any additive discrepancy in bgp eor
+ counters */
+ peer->bgp->established--;
+ peer->update_delay_over = 0;
+ }
+}
+
/* Called after event occured, this function change status and reset
read/write and timer thread. */
void
bgp_fsm_change_status (struct peer *peer, int status)
{
+
bgp_dump_state (peer, peer->status, status);
/* Transition into Clearing or Deleted must /always/ clear all routes..
@@ -422,8 +917,26 @@ bgp_fsm_change_status (struct peer *peer, int status)
/* Preserve old status and change into new status. */
peer->ostatus = peer->status;
peer->status = status;
-
- if (BGP_DEBUG (normal, NORMAL))
+
+ if (status == Established)
+ UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
+
+ /* If max-med processing is applicable, do the necessary. */
+ if (status == Established)
+ {
+ if (bgp_maxmed_onstartup_configured(peer->bgp) &&
+ bgp_maxmed_onstartup_applicable(peer->bgp))
+ bgp_maxmed_onstartup_process_status_change(peer);
+ else
+ peer->bgp->maxmed_onstartup_over = 1;
+ }
+
+ /* If update-delay processing is applicable, do the necessary. */
+ if (bgp_update_delay_configured(peer->bgp) &&
+ bgp_update_delay_applicable(peer->bgp))
+ bgp_update_delay_process_status_change(peer);
+
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s went from %s to %s",
peer->host,
LOOKUP (bgp_status_msg, peer->ostatus),
@@ -435,7 +948,9 @@ static int
bgp_clearing_completed (struct peer *peer)
{
int rc = bgp_stop(peer);
- BGP_EVENT_FLUSH (peer);
+
+ if (rc >= 0)
+ BGP_EVENT_FLUSH (peer);
return rc;
}
@@ -448,6 +963,7 @@ bgp_stop (struct peer *peer)
afi_t afi;
safi_t safi;
char orf_name[BUFSIZ];
+ int ret = 0;
/* Can't do this in Clearing; events are used for state transitions */
if (peer->status != Clearing)
@@ -470,12 +986,12 @@ bgp_stop (struct peer *peer)
if (peer->t_gr_stale)
{
BGP_TIMER_OFF (peer->t_gr_stale);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
{
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
{
zlog_debug ("%s graceful restart timer started for %d sec",
peer->host, peer->v_gr_restart);
@@ -553,9 +1069,11 @@ bgp_stop (struct peer *peer)
/* Received ORF prefix-filter */
peer->orf_plist[afi][safi] = NULL;
- /* ORF received prefix-filter pnt */
- sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
- prefix_bgp_orf_remove_all (afi, orf_name);
+ if ((peer->status == OpenConfirm) || (peer->status == Established)) {
+ /* ORF received prefix-filter pnt */
+ sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
+ prefix_bgp_orf_remove_all (afi, orf_name);
+ }
}
/* Reset keepalive and holdtime */
@@ -583,7 +1101,18 @@ bgp_stop (struct peer *peer)
peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
#endif /* 0 */
- return 0;
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
+ !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE)))
+ {
+ peer_delete(peer);
+ ret = -1;
+ }
+ else
+ {
+ bgp_peer_conf_if_to_su_update(peer);
+ }
+
+ return ret;
}
/* BGP peer is stoped by the error. */
@@ -597,9 +1126,7 @@ bgp_stop_with_error (struct peer *peer)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
- bgp_stop (peer);
-
- return 0;
+ return(bgp_stop (peer));
}
@@ -610,21 +1137,10 @@ bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
/* Send notify to remote peer */
bgp_notify_send (peer, code, sub_code);
- /* Sweep if it is temporary peer. */
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
- peer_delete (peer);
- return -1;
- }
-
/* Clear start timer value to default. */
peer->v_start = BGP_INIT_START_TIMER;
- /* bgp_stop needs to be invoked while in Established state */
- bgp_stop(peer);
-
- return 0;
+ return(bgp_stop(peer));
}
@@ -637,14 +1153,21 @@ bgp_connect_success (struct peer *peer)
{
zlog_err ("bgp_connect_success peer's fd is negative value %d",
peer->fd);
+ bgp_stop(peer);
return -1;
}
- BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- bgp_getsockname (peer);
+ if (bgp_getsockname (peer) < 0)
+ {
+ zlog_err ("%s: bgp_getsockname(): failed for peer %s", __FUNCTION__,
+ peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); /* internal error */
+ return -1;
+ }
- if (BGP_DEBUG (normal, NORMAL))
+ BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
+
+ if (bgp_debug_neighbor_events(peer))
{
char buf1[SU_ADDRSTRLEN];
@@ -655,8 +1178,7 @@ bgp_connect_success (struct peer *peer)
zlog_debug ("%s passive open", peer->host);
}
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- bgp_open_send (peer);
+ bgp_open_send (peer);
return 0;
}
@@ -665,8 +1187,7 @@ bgp_connect_success (struct peer *peer)
static int
bgp_connect_fail (struct peer *peer)
{
- bgp_stop (peer);
- return 0;
+ return (bgp_stop (peer));
}
/* This function is the first starting point of all BGP connection. It
@@ -675,11 +1196,14 @@ int
bgp_start (struct peer *peer)
{
int status;
+ int connected = 0;
+
+ bgp_peer_conf_if_to_su_update(peer);
if (BGP_PEER_START_SUPPRESSED (peer))
{
- if (BGP_DEBUG (fsm, FSM))
- plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
+ if (bgp_debug_neighbor_events(peer))
+ zlog_err ("%s [FSM] Trying to start suppressed peer"
" - this is never supposed to happen!", peer->host);
return -1;
}
@@ -713,26 +1237,32 @@ bgp_start (struct peer *peer)
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);
switch (status)
{
case connect_error:
- if (BGP_DEBUG (fsm, FSM))
- plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Connect error", peer->host);
BGP_EVENT_ADD (peer, TCP_connection_open_failed);
break;
case connect_success:
- if (BGP_DEBUG (fsm, FSM))
- plog_debug (peer->log, "%s [FSM] Connect immediately success",
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Connect immediately success",
peer->host);
BGP_EVENT_ADD (peer, TCP_connection_open);
break;
case connect_in_progress:
/* To check nonblocking connect, we wait until socket is
readable or writable. */
- if (BGP_DEBUG (fsm, FSM))
- plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Non blocking connect waiting result",
peer->host);
if (peer->fd < 0)
{
@@ -751,9 +1281,14 @@ bgp_start (struct peer *peer)
static int
bgp_reconnect (struct peer *peer)
{
- bgp_stop (peer);
- bgp_start (peer);
- return 0;
+ int ret = 0;
+
+ if (bgp_stop (peer) > 0)
+ bgp_start (peer);
+ else
+ ret = -1;
+
+ return ret;
}
static int
@@ -772,6 +1307,13 @@ bgp_fsm_open (struct peer *peer)
static int
bgp_fsm_keepalive_expire (struct peer *peer)
{
+ /*
+ * If there are UPDATE messages to send, no need to send keepalive. The
+ * peer will note our progress through the UPDATEs.
+ */
+ if (!bgp_routeq_empty(peer))
+ return 0;
+
bgp_keepalive_send (peer);
return 0;
}
@@ -781,7 +1323,7 @@ bgp_fsm_keepalive_expire (struct peer *peer)
static int
bgp_fsm_event_error (struct peer *peer)
{
- plog_err (peer->log, "%s [FSM] unexpected packet received in state %s",
+ zlog_err ("%s [FSM] unexpected packet received in state %s",
peer->host, LOOKUP (bgp_status_msg, peer->status));
return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0);
@@ -792,8 +1334,8 @@ bgp_fsm_event_error (struct peer *peer)
static int
bgp_fsm_holdtime_expire (struct peer *peer)
{
- if (BGP_DEBUG (fsm, FSM))
- plog_debug (peer->log, "%s [FSM] Hold timer expire", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] Hold timer expire", peer->host);
return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0);
}
@@ -807,6 +1349,19 @@ bgp_establish (struct peer *peer)
afi_t afi;
safi_t safi;
int nsf_af_count = 0;
+ int ret = 0;
+ struct peer *other;
+
+ other = peer->doppelganger;
+ peer = peer_xfer_conn(peer);
+ if (!peer)
+ {
+ zlog_err ("%%Neighbor failed in xfer_conn");
+ return -1;
+ }
+
+ if (other == peer)
+ ret = 1; /* bgp_establish specific code when xfer_conn happens. */
/* Reset capability open status flag. */
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
@@ -861,7 +1416,7 @@ bgp_establish (struct peer *peer)
if (peer->t_gr_stale)
{
BGP_TIMER_OFF (peer->t_gr_stale);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
}
@@ -869,7 +1424,7 @@ bgp_establish (struct peer *peer)
if (peer->t_gr_restart)
{
BGP_TIMER_OFF (peer->t_gr_restart);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s graceful restart timer stopped", peer->host);
}
@@ -893,9 +1448,6 @@ bgp_establish (struct peer *peer)
REFRESH_IMMEDIATE, 0);
}
- if (peer->v_keepalive)
- bgp_keepalive_send (peer);
-
/* First update is deferred until ORF or ROUTE-REFRESH is received */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
@@ -906,15 +1458,34 @@ bgp_establish (struct peer *peer)
bgp_announce_route_all (peer);
- BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
+ /* Start the route advertisement timer to send updates to the peer - if BGP
+ * is not in read-only mode. If it is, the timer will be started at the end
+ * of read-only mode.
+ */
+ if (!bgp_update_delay_active(peer->bgp))
+ BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 0);
- return 0;
+ if (peer->doppelganger && (peer->doppelganger->status != Deleted))
+ {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("[Event] Deleting stub connection for peer %s", peer->host);
+
+ if (peer->doppelganger->status > Active)
+ bgp_notify_send (peer->doppelganger, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ else
+ peer_delete(peer->doppelganger);
+ }
+
+ return ret;
}
/* Keepalive packet is received. */
static int
bgp_fsm_keepalive (struct peer *peer)
{
+ bgp_update_implicit_eors(peer);
+
/* peer count update */
peer->keepalive_in++;
@@ -934,11 +1505,50 @@ bgp_fsm_update (struct peer *peer)
static int
bgp_ignore (struct peer *peer)
{
- if (BGP_DEBUG (fsm, FSM))
- zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [FSM] bgp_ignore called", peer->host);
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 */
static const struct {
int (*func) (struct peer *);
@@ -1108,19 +1718,34 @@ static const char *bgp_event_str[] =
int
bgp_event (struct thread *thread)
{
- int ret = 0;
int event;
- int next;
struct peer *peer;
+ int ret;
peer = THREAD_ARG (thread);
event = THREAD_VAL (thread);
+ ret = bgp_event_update(peer, event);
+
+ return (ret);
+}
+
+int
+bgp_event_update (struct peer *peer, int event)
+{
+ int next;
+ int ret = 0;
+ struct peer *other;
+ int passive_conn = 0;
+
+ other = peer->doppelganger;
+ passive_conn = (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0;
+
/* Logging this event. */
next = FSM [peer->status -1][event - 1].next_state;
- if (BGP_DEBUG (fsm, FSM) && peer->status != next)
- plog_debug (peer->log, "%s [FSM] %s (%s->%s)", peer->host,
+ if (bgp_debug_neighbor_events(peer) && peer->status != next)
+ zlog_debug ("%s [FSM] %s (%s->%s)", peer->host,
bgp_event_str[event],
LOOKUP (bgp_status_msg, peer->status),
LOOKUP (bgp_status_msg, next));
@@ -1132,13 +1757,28 @@ bgp_event (struct thread *thread)
/* When function do not want proceed next job return -1. */
if (ret >= 0)
{
+ if (ret == 1 && next == Established)
+ {
+ /* The case when doppelganger swap accurred in bgp_establish.
+ Update the peer pointer accordingly */
+ peer = other;
+ }
+
/* If status is changed. */
if (next != peer->status)
bgp_fsm_change_status (peer, next);
/* Make sure timer is set. */
bgp_timer_set (peer);
+
+ }
+ else if (!passive_conn && peer->bgp)
+ {
+ /* If we got a return value of -1, that means there was an error, restart
+ * the FSM. If the peer structure was deleted
+ */
+ bgp_fsm_change_status(peer, Idle);
+ bgp_timer_set(peer);
}
-
return ret;
}
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index 752d6e2b..89077857 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -71,11 +71,35 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
thread_cancel_event (bm->master, (P)); \
} while (0)
+#define BGP_MSEC_JITTER 10
+
/* Prototypes. */
+extern void bgp_fsm_nht_update(struct peer *, int valid);
extern int bgp_event (struct thread *);
+extern int bgp_event_update (struct peer *, int event);
extern int bgp_stop (struct peer *peer);
extern void bgp_timer_set (struct peer *);
extern void bgp_fsm_change_status (struct peer *peer, int status);
extern const char *peer_down_str[];
+extern void bgp_update_delay_end (struct bgp *);
+extern void bgp_maxmed_update (struct bgp *);
+extern int bgp_maxmed_onstartup_configured (struct bgp *);
+extern int bgp_maxmed_onstartup_active (struct bgp *);
+
+/**
+ * Start the route advertisement timer (that honors MRAI) for all the
+ * peers. Typically called at the end of initial convergence, coming
+ * out of read-only mode.
+ */
+extern void bgp_start_routeadv (struct bgp *);
+
+/**
+ * See if the route advertisement timer needs to be adjusted for a
+ * peer. For example, if the last update was written to the peer a
+ * long while back, we don't need to wait for the periodic advertisement
+ * timer to expire to send the new set of prefixes. It should fire
+ * instantly and updates should go out sooner.
+ */
+extern void bgp_adjust_routeadv (struct peer *);
#endif /* _QUAGGA_BGP_FSM_H */
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 11c73cea..2f157652 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -38,6 +38,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "stream.h"
#include "vrf.h"
#include "workqueue.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -51,6 +52,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_filter.h"
#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_network.h"
/* bgpd options, we use GNU getopt library. */
static const struct option longopts[] =
@@ -175,7 +177,7 @@ Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
void
sighup (void)
{
- zlog (NULL, LOG_INFO, "SIGHUP received");
+ zlog_info ("SIGHUP received");
/* Terminate all thread. */
bgp_terminate ();
@@ -225,13 +227,13 @@ bgp_exit (int status)
{
struct bgp *bgp;
struct listnode *node, *nnode;
- int *socket;
struct interface *ifp;
- extern struct zclient *zlookup;
/* it only makes sense for this to be called on a clean exit */
assert (status == 0);
+ bgp_close();
+
/* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
bgp_delete (bgp);
@@ -256,14 +258,6 @@ bgp_exit (int status)
work_queue_free (bm->process_rsclient_queue);
bm->process_rsclient_queue = NULL;
}
-
- /* reverse bgp_master_init */
- for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
- {
- if (close ((int)(long)socket) == -1)
- zlog_err ("close (%d): %s", (int)(long)socket, safe_strerror (errno));
- }
- list_delete (bm->listen_sockets);
/* reverse bgp_zebra_init/if_init */
if (retain_mode)
@@ -286,11 +280,8 @@ bgp_exit (int status)
/* reverse bgp_route_init */
bgp_route_finish ();
- /* reverse bgp_route_map_init/route_map_init */
- route_map_finish ();
-
- /* reverse bgp_scan_init */
- bgp_scan_finish ();
+ /* cleanup route maps */
+ bgp_route_map_terminate();
/* reverse access_list_init */
access_list_add_hook (NULL);
@@ -316,10 +307,13 @@ bgp_exit (int status)
bgp_address_destroy();
bgp_scan_destroy();
bgp_zebra_destroy();
- if (zlookup)
- zclient_free (zlookup);
if (bgp_nexthop_buf)
stream_free (bgp_nexthop_buf);
+ if (bgp_ifindices_buf)
+ stream_free (bgp_ifindices_buf);
+
+ /* reverse bgp_scan_init */
+ bgp_scan_finish ();
/* reverse bgp_master_init */
if (bm->master)
@@ -328,9 +322,6 @@ bgp_exit (int status)
if (zlog_default)
closezlog (zlog_default);
- if (CONF_BGP_DEBUG (normal, NORMAL))
- log_memstats_stderr ("bgpd");
-
exit (status);
}
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 8e78aafe..3d17ec85 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -74,7 +74,7 @@ bgp_mpath_is_configured (struct bgp *bgp, afi_t afi, safi_t safi)
*/
int
bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi,
- int peertype, u_int16_t maxpaths)
+ int peertype, u_int16_t maxpaths, u_int16_t options)
{
if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
return -1;
@@ -83,6 +83,7 @@ bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi,
{
case BGP_PEER_IBGP:
bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths;
+ bgp->maxpaths[afi][safi].ibgp_flags |= options;
break;
case BGP_PEER_EBGP:
bgp->maxpaths[afi][safi].maxpaths_ebgp = maxpaths;
@@ -110,6 +111,7 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
{
case BGP_PEER_IBGP:
bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
+ bgp->maxpaths[afi][safi].ibgp_flags = 0;
break;
case BGP_PEER_EBGP:
bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
@@ -139,26 +141,45 @@ bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop);
- if (!compare && ae1 && ae2 && (ae1->mp_nexthop_len == ae2->mp_nexthop_len))
+ if (!compare && ae1 && ae2)
{
- switch (ae1->mp_nexthop_len)
+ if (ae1->mp_nexthop_len == ae2->mp_nexthop_len)
+ {
+ switch (ae1->mp_nexthop_len)
+ {
+ case 4:
+ case 12:
+ compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in,
+ &ae2->mp_nexthop_global_in);
+ break;
+ case 16:
+ compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
+ &ae2->mp_nexthop_global);
+ break;
+ case 32:
+ compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
+ &ae2->mp_nexthop_global);
+ if (!compare)
+ compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local,
+ &ae2->mp_nexthop_local);
+ break;
+ }
+ }
+
+ /* This can happen if one IPv6 peer sends you global and link-local
+ * nexthops but another IPv6 peer only sends you global
+ */
+ else if (ae1->mp_nexthop_len == 16 || ae1->mp_nexthop_len == 32)
{
- case 4:
- case 12:
- compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in,
- &ae2->mp_nexthop_global_in);
- break;
- case 16:
- compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
- &ae2->mp_nexthop_global);
- break;
- case 32:
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global,
&ae2->mp_nexthop_global);
if (!compare)
- compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local,
- &ae2->mp_nexthop_local);
- break;
+ {
+ if (ae1->mp_nexthop_len < ae2->mp_nexthop_len)
+ compare = -1;
+ else
+ compare = 1;
+ }
}
}
@@ -427,7 +448,7 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
struct listnode *mp_node, *mp_next_node;
struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
int mpath_changed, debug;
- char pfx_buf[INET_ADDRSTRLEN], nh_buf[2][INET_ADDRSTRLEN];
+ char pfx_buf[INET6_ADDRSTRLEN], nh_buf[2][INET6_ADDRSTRLEN];
struct bgp_maxpaths_cfg *mpath_cfg = NULL;
mpath_changed = 0;
@@ -437,8 +458,7 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
old_mpath_count = 0;
prev_mpath = new_best;
mp_node = listhead (mp_list);
-
- debug = BGP_DEBUG (events, EVENTS);
+ debug = bgp_debug_update(NULL, &rn->p, 1) || bgp_debug_update(NULL, &rn->p, 0);
if (debug)
prefix2str (&rn->p, pfx_buf, sizeof (pfx_buf));
diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h
index 2a84d5e1..83db8264 100644
--- a/bgpd/bgp_mpath.h
+++ b/bgpd/bgp_mpath.h
@@ -24,6 +24,9 @@
#ifndef _QUAGGA_BGP_MPATH_H
#define _QUAGGA_BGP_MPATH_H
+/* Limit on number of configured maxpaths */
+#define BGP_MAXIMUM_MAXPATHS 255
+
/* BGP default maximum-paths */
#define BGP_DEFAULT_MAXPATHS 1
@@ -49,7 +52,8 @@ struct bgp_info_mpath
};
/* Functions to support maximum-paths configuration */
-extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t);
+extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t,
+ u_int16_t);
extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int);
bool bgp_mpath_is_configured_sort (struct bgp *, bgp_peer_sort_t, afi_t, safi_t);
bool bgp_mpath_is_configured (struct bgp *, afi_t, safi_t);
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 08a4272d..4a8f5eaa 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "stream.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -133,16 +134,14 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
/* sanity check against packet data */
if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8)
{
- plog_err (peer->log,
- "%s [Error] Update packet error / VPNv4"
- " (prefix length %d less than VPNv4 min length)",
+ zlog_err ("%s [Error] Update packet error / VPNv4"
+ " (prefix length %d less than VPNv4 min length)",
peer->host, prefixlen);
return -1;
}
if ((pnt + psize) > lim)
{
- plog_err (peer->log,
- "%s [Error] Update packet error / VPNv4"
+ zlog_err ("%s [Error] Update packet error / VPNv4"
" (psize %u exceeds packet size (%u)",
peer->host,
prefixlen, (uint)(lim-pnt));
@@ -152,8 +151,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
/* sanity check against storage for the IP address portion */
if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t) sizeof(p.u))
{
- plog_err (peer->log,
- "%s [Error] Update packet error / VPNv4"
+ zlog_err ("%s [Error] Update packet error / VPNv4"
" (psize %u exceeds storage size (%zu)",
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u));
@@ -163,8 +161,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
/* Sanity check against max bitlen of the address family */
if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen (&p))
{
- plog_err (peer->log,
- "%s [Error] Update packet error / VPNv4"
+ zlog_err ("%s [Error] Update packet error / VPNv4"
" (psize %u exceeds family (%u) max byte len %u)",
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES*8,
@@ -214,8 +211,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
/* Packet length consistency check. */
if (pnt != lim)
{
- plog_err (peer->log,
- "%s [Error] Update packet error / VPNv4"
+ zlog_err ("%s [Error] Update packet error / VPNv4"
" (%zu data remaining after parsing)",
peer->host, lim - pnt);
return -1;
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 51a6f602..283fa344 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -34,6 +34,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "filter.h"
#include "bgpd/bgpd.h"
+#include "bgpd/bgp_open.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_debug.h"
@@ -67,8 +68,7 @@ bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
#endif /* HAVE_TCP_MD5SIG */
if (ret < 0)
- zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
- socket, safe_strerror (en));
+ zlog_warn ("can't set TCP_MD5SIG option on socket %d: %s", socket, safe_strerror (en));
return ret;
}
@@ -150,7 +150,7 @@ static void
bgp_set_socket_ttl (struct peer *peer, int bgp_sock)
{
char buf[INET_ADDRSTRLEN];
- int ret;
+ int ret = 0;
/* In case of peer is EBGP, we should set TTL for this connection. */
if (!peer->gtsm_hops && (peer_sort (peer) == BGP_PEER_EBGP))
@@ -222,50 +222,90 @@ bgp_accept (struct thread *thread)
/* Set socket send buffer size */
bgp_update_sock_send_buffer_size(bgp_sock);
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
-
/* Check remote IP address */
peer1 = peer_lookup (NULL, &su);
- if (! peer1 || peer1->status == Idle)
+ if (! peer1)
{
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(NULL))
{
- if (! peer1)
- zlog_debug ("[Event] BGP connection IP address %s is not configured",
- inet_sutop (&su, buf));
- else
- zlog_debug ("[Event] BGP connection IP address %s is Idle state",
- inet_sutop (&su, buf));
+ zlog_debug ("[Event] BGP connection IP address %s is not configured",
+ inet_sutop (&su, buf));
}
close (bgp_sock);
return -1;
}
+ if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN))
+ {
+ if (bgp_debug_neighbor_events(peer1))
+ zlog_debug ("[Event] connection from %s rejected due to admin shutdown",
+ inet_sutop (&su, buf));
+ close (bgp_sock);
+ return -1;
+ }
+
+ /*
+ * Do not accept incoming connections in Clearing state. This can result
+ * in incorect state transitions - e.g., the connection goes back to
+ * Established and then the Clearing_Completed event is generated. Also,
+ * block incoming connection in Deleted state.
+ */
+ if (peer1->status == Clearing || peer1->status == Deleted)
+ {
+ if (bgp_debug_neighbor_events(peer1))
+ zlog_debug("[Event] Closing incoming conn for %s (%p) state %d",
+ peer1->host, peer1, peer1->status);
+ close (bgp_sock);
+ return -1;
+ }
+
+ if (bgp_debug_neighbor_events(peer1))
+ zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
+
+ if (peer1->doppelganger)
+ {
+ /* We have an existing connection. Kill the existing one and run
+ with this one.
+ */
+ if (bgp_debug_neighbor_events(peer1))
+ zlog_debug ("[Event] New active connection from peer %s, Killing"
+ " previous active connection", peer1->host);
+ peer_delete(peer1->doppelganger);
+ }
+
bgp_set_socket_ttl (peer1, bgp_sock);
- /* Make dummy peer until read Open packet. */
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("[Event] Make dummy peer structure until read Open packet");
+ peer = peer_create (&su, peer1->conf_if, peer1->bgp, peer1->local_as,
+ peer1->as, 0, 0);
- {
- char buf[SU_ADDRSTRLEN];
+ peer_xfer_config(peer, peer1);
+ UNSET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
- peer = peer_create_accept (peer1->bgp);
- SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
- peer->su = su;
- peer->fd = bgp_sock;
- peer->status = Active;
- peer->local_id = peer1->local_id;
- peer->v_holdtime = peer1->v_holdtime;
- peer->v_keepalive = peer1->v_keepalive;
+ peer->doppelganger = peer1;
+ peer1->doppelganger = peer;
+ peer->fd = bgp_sock;
+ bgp_fsm_change_status(peer, Active);
+ BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
- /* Make peer's address string. */
- sockunion2str (&su, buf, SU_ADDRSTRLEN);
- peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
- }
+ SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
- BGP_EVENT_ADD (peer, TCP_connection_open);
+ /* Make dummy peer until read Open packet. */
+ if (peer1->status == Established &&
+ CHECK_FLAG (peer1->sflags, PEER_STATUS_NSF_MODE))
+ {
+ /* If we have an existing established connection with graceful restart
+ * capability announced with one or more address families, then drop
+ * existing established connection and move state to connect.
+ */
+ peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
+ SET_FLAG (peer1->sflags, PEER_STATUS_NSF_WAIT);
+ bgp_event_update(peer1, TCP_connection_closed);
+ }
+
+ if (peer_active (peer))
+ {
+ BGP_EVENT_ADD (peer, TCP_connection_open);
+ }
return 0;
}
@@ -278,11 +318,14 @@ bgp_bind (struct peer *peer)
int ret;
struct ifreq ifreq;
int myerrno;
+ char *name;
- if (! peer->ifname)
+ if (! peer->ifname && !peer->conf_if)
return 0;
- strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name));
+ name = (peer->conf_if ? peer->conf_if : peer->ifname);
+
+ strncpy ((char *)&ifreq.ifr_name, name, sizeof (ifreq.ifr_name));
if ( bgpd_privs.change (ZPRIVS_RAISE) )
zlog_err ("bgp_bind: could not raise privs");
@@ -296,8 +339,8 @@ bgp_bind (struct peer *peer)
if (ret < 0)
{
- zlog (peer->log, LOG_INFO, "bind to interface %s failed, errno=%d",
- peer->ifname, myerrno);
+ zlog_info ("bind to interface %s failed, errno=%d",
+ name, myerrno);
return ret;
}
#endif /* SO_BINDTODEVICE */
@@ -367,6 +410,11 @@ bgp_connect (struct peer *peer)
{
ifindex_t ifindex = 0;
+ if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer))
+ {
+ zlog_debug("Peer address not learnt: Returning from connect");
+ return 0;
+ }
/* Make socket for the peer. */
peer->fd = sockunion_socket (&peer->su);
if (peer->fd < 0)
@@ -402,19 +450,19 @@ bgp_connect (struct peer *peer)
/* Update source bind. */
bgp_update_source (peer);
- if (peer->ifname)
- ifindex = ifname2ifindex (peer->ifname);
+ if (peer->conf_if || peer->ifname)
+ ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname);
- if (BGP_DEBUG (events, EVENTS))
- plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",
- peer->host, peer->host, peer->fd);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [Event] Connect start to %s fd %d",
+ peer->host, peer->host, peer->fd);
/* Connect to the remote peer. */
return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
}
/* After TCP connection is established. Get local address and port. */
-void
+int
bgp_getsockname (struct peer *peer)
{
if (peer->su_local)
@@ -430,9 +478,13 @@ bgp_getsockname (struct peer *peer)
}
peer->su_local = sockunion_getsockname (peer->fd);
+ if (!peer->su_local) return -1;
peer->su_remote = sockunion_getpeername (peer->fd);
+ if (!peer->su_remote) return -1;
bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
+
+ return 0;
}
@@ -548,6 +600,9 @@ bgp_close (void)
struct listnode *node, *next;
struct bgp_listener *listener;
+ if (bm->listen_sockets == NULL)
+ return;
+
for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener))
{
thread_cancel (listener->thread);
diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h
index 12768430..403393e8 100644
--- a/bgpd/bgp_network.h
+++ b/bgpd/bgp_network.h
@@ -26,7 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
extern int bgp_socket (unsigned short, const char *);
extern void bgp_close (void);
extern int bgp_connect (struct peer *);
-extern void bgp_getsockname (struct peer *);
+extern int bgp_getsockname (struct peer *);
extern int bgp_md5_set (struct peer *);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 24068141..4be27b47 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -31,59 +31,35 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "hash.h"
#include "jhash.h"
#include "filter.h"
+#include "nexthop.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_damp.h"
#include "zebra/rib.h"
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
-struct bgp_nexthop_cache *zlookup_query (struct in_addr);
-struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
-
-/* Only one BGP scan thread are activated at the same time. */
-static struct thread *bgp_scan_thread = NULL;
-
-/* BGP import thread */
-static struct thread *bgp_import_thread = NULL;
-
-/* BGP scan interval. */
-static int bgp_scan_interval;
-
-/* BGP import interval. */
-static int bgp_import_interval;
/* Route table for next-hop lookup cache. */
-static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
+struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
static struct bgp_table *cache1_table[AFI_MAX];
-static struct bgp_table *cache2_table[AFI_MAX];
/* Route table for connected route. */
static struct bgp_table *bgp_connected_table[AFI_MAX];
-/* BGP nexthop lookup query client. */
-struct zclient *zlookup = NULL;
-
-/* Add nexthop to the end of the list. */
-static void
-bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
+char *
+bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
{
- 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;
+ prefix2str(&(bnc->node->p), buf, size);
+ return buf;
}
-static void
+void
bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
{
struct nexthop *nexthop;
@@ -96,93 +72,29 @@ bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
}
}
-static struct bgp_nexthop_cache *
+struct bgp_nexthop_cache *
bnc_new (void)
{
- return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
+ struct bgp_nexthop_cache *bnc;
+
+ bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
+ LIST_INIT(&(bnc->paths));
+ return bnc;
}
-static void
+void
bnc_free (struct bgp_nexthop_cache *bnc)
{
bnc_nexthop_free (bnc);
XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
}
-static int
-bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
-{
- if (next1->type != next2->type)
- return 0;
-
- switch (next1->type)
- {
- case ZEBRA_NEXTHOP_IPV4:
- if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
- return 0;
- break;
- case ZEBRA_NEXTHOP_IPV4_IFINDEX:
- if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)
- || next1->ifindex != next2->ifindex)
- return 0;
- break;
- case ZEBRA_NEXTHOP_IFINDEX:
- case ZEBRA_NEXTHOP_IFNAME:
- if (next1->ifindex != next2->ifindex)
- return 0;
- break;
- case ZEBRA_NEXTHOP_IPV6:
- if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
- return 0;
- break;
- case ZEBRA_NEXTHOP_IPV6_IFINDEX:
- case ZEBRA_NEXTHOP_IPV6_IFNAME:
- if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
- return 0;
- if (next1->ifindex != next2->ifindex)
- return 0;
- break;
- default:
- /* do nothing */
- break;
- }
- return 1;
-}
-
-static int
-bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
- 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++)
- {
- if (! bgp_nexthop_same (next1, next2))
- return 1;
-
- next1 = next1->next;
- next2 = next2->next;
- }
- return 0;
-}
-
/* If nexthop exists on connected network return 1. */
int
bgp_nexthop_onlink (afi_t afi, struct attr *attr)
{
struct bgp_node *rn;
- /* If zebra is not enabled return */
- if (zlookup->sock < 0)
- return 1;
-
/* Lookup the address is onlink or not. */
if (afi == AFI_IP)
{
@@ -214,325 +126,6 @@ bgp_nexthop_onlink (afi_t afi, struct attr *attr)
return 0;
}
-/* Check specified next-hop is reachable or not. */
-static int
-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;
-
- /* If lookup is not enabled, return valid. */
- if (zlookup->sock < 0)
- {
- if (ri->extra)
- ri->extra->igpmetric = 0;
- return 1;
- }
-
- /* Only check IPv6 global address only nexthop. */
- attr = ri->attr;
-
- if (attr->extra->mp_nexthop_len != 16
- || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
- return 1;
-
- memset (&p, 0, sizeof (struct prefix));
- p.family = AF_INET6;
- p.prefixlen = IPV6_MAX_BITLEN;
- p.u.prefix6 = attr->extra->mp_nexthop_global;
-
- /* IBGP or ebgp-multihop */
- rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
-
- if (rn->info)
- {
- bnc = rn->info;
- bgp_unlock_node (rn);
- }
- else
- {
- if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
- bnc = bnc_new ();
- else
- {
- if (changed)
- {
- struct bgp_table *old;
- struct bgp_node *oldrn;
-
- if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
- old = cache2_table[AFI_IP6];
- else
- old = cache1_table[AFI_IP6];
-
- oldrn = bgp_node_lookup (old, &p);
- if (oldrn)
- {
- struct bgp_nexthop_cache *oldbnc = oldrn->info;
-
- bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
-
- if (bnc->metric != oldbnc->metric)
- bnc->metricchanged = 1;
-
- bgp_unlock_node (oldrn);
- }
- }
- }
- rn->info = bnc;
- }
-
- if (changed)
- *changed = bnc->changed;
-
- if (metricchanged)
- *metricchanged = bnc->metricchanged;
-
- if (bnc->valid && bnc->metric)
- (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
- else if (ri->extra)
- ri->extra->igpmetric = 0;
-
- return bnc->valid;
-}
-
-/* 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;
-
- /* If lookup is not enabled, return valid. */
- if (zlookup->sock < 0)
- {
- if (ri->extra)
- ri->extra->igpmetric = 0;
- return 1;
- }
-
- if (afi == AFI_IP6)
- return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
-
- 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 */
- rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
-
- if (rn->info)
- {
- bnc = rn->info;
- bgp_unlock_node (rn);
- }
- else
- {
- if (NULL == (bnc = zlookup_query (addr)))
- bnc = bnc_new ();
- else
- {
- if (changed)
- {
- struct bgp_table *old;
- struct bgp_node *oldrn;
-
- if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
- old = cache2_table[AFI_IP];
- else
- old = cache1_table[AFI_IP];
-
- oldrn = bgp_node_lookup (old, &p);
- if (oldrn)
- {
- struct bgp_nexthop_cache *oldbnc = oldrn->info;
-
- bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
-
- if (bnc->metric != oldbnc->metric)
- bnc->metricchanged = 1;
-
- bgp_unlock_node (oldrn);
- }
- }
- }
- rn->info = bnc;
- }
-
- if (changed)
- *changed = bnc->changed;
-
- if (metricchanged)
- *metricchanged = bnc->metricchanged;
-
- if (bnc->valid && bnc->metric)
- (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
- else if (ri->extra)
- ri->extra->igpmetric = 0;
-
- return bnc->valid;
-}
-
-/* Reset and free all BGP nexthop cache. */
-static void
-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);
- }
-}
-
-static void
-bgp_scan (afi_t afi, safi_t safi)
-{
- struct bgp_node *rn;
- struct bgp *bgp;
- struct bgp_info *bi;
- struct bgp_info *next;
- struct peer *peer;
- struct listnode *node, *nnode;
- int valid;
- int current;
- int changed;
- int metricchanged;
-
- /* Change cache. */
- if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
- bgp_nexthop_cache_table[afi] = cache2_table[afi];
- else
- bgp_nexthop_cache_table[afi] = cache1_table[afi];
-
- /* Get default bgp. */
- bgp = bgp_get_default ();
- if (bgp == NULL)
- return;
-
- /* Maximum prefix check */
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- {
- if (peer->status != Established)
- continue;
-
- 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);
- }
-
- for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
- 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)
- {
- changed = 0;
- metricchanged = 0;
-
- if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1
- && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
- valid = bgp_nexthop_onlink (afi, bi->attr);
- else
- valid = bgp_nexthop_lookup (afi, bi->peer, bi,
- &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,
- afi, SAFI_UNICAST);
- bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
- }
- else
- {
- bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
- bgp_aggregate_increment (bgp, &rn->p, bi,
- afi, SAFI_UNICAST);
- }
- }
-
- if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
- BGP_CONFIG_DAMPENING)
- && bi->extra && bi->extra->damp_info )
- if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
- bgp_aggregate_increment (bgp, &rn->p, bi,
- afi, SAFI_UNICAST);
- }
- }
- if (rn->info)
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
- }
-
- /* Flash old cache. */
- if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
- bgp_nexthop_cache_reset (cache2_table[afi]);
- else
- bgp_nexthop_cache_reset (cache1_table[afi]);
-
- 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");
- }
-
- /* 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);
- }
-}
-
-/* BGP scan thread. This thread check nexthop reachability. */
-static int
-bgp_scan_timer (struct thread *t)
-{
- bgp_scan_thread =
- thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
-
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("Performing BGP general scanning");
-
- bgp_scan (AFI_IP, SAFI_UNICAST);
-
- bgp_scan (AFI_IP6, SAFI_UNICAST);
-
- return 0;
-}
-
/* BGP own address structure */
struct bgp_addr
{
@@ -599,6 +192,9 @@ bgp_address_add (struct prefix *p)
tmp.addr = p->u.prefix4;
addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
+ if (!addr)
+ return;
+
addr->refcnt++;
}
@@ -777,652 +373,158 @@ bgp_nexthop_self (struct attr *attr)
return 0;
}
-static struct bgp_nexthop_cache *
-zlookup_read (void)
-{
- struct stream *s;
- uint16_t length;
- u_char marker;
- u_char version;
- uint16_t vrf_id;
- uint16_t command;
- int err;
- struct in_addr raddr __attribute__((unused));
- uint32_t metric;
- int i;
- u_char nexthop_num;
- struct nexthop *nexthop;
- struct bgp_nexthop_cache *bnc;
-
- s = zlookup->ibuf;
- stream_reset (s);
-
- err = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
- &vrf_id, &command);
- if (err < 0)
- {
- zlog_err("%s: zserv_read_header() failed", __func__);
- return NULL;
- }
-
- /* XXX: not doing anything with raddr */
- 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++)
- {
- nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- nexthop->type = stream_getc (s);
- switch (nexthop->type)
- {
- case ZEBRA_NEXTHOP_IPV4:
- nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
- break;
- case ZEBRA_NEXTHOP_IPV4_IFINDEX:
- nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
- nexthop->ifindex = stream_getl (s);
- break;
- case ZEBRA_NEXTHOP_IFINDEX:
- case ZEBRA_NEXTHOP_IFNAME:
- nexthop->ifindex = stream_getl (s);
- break;
- default:
- /* do nothing */
- break;
- }
- 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);
- zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, VRF_DEFAULT);
- stream_put_in_addr (s, &addr);
-
- stream_putw_at (s, 0, stream_get_endp (s));
-
- ret = writen (zlookup->sock, s->data, stream_get_endp (s));
- 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 ();
-}
-
-static struct bgp_nexthop_cache *
-zlookup_read_ipv6 (void)
-{
- struct stream *s;
- uint16_t length, vrf_id, cmd;
- u_char version, marker;
- struct in6_addr raddr;
- uint32_t metric;
- int i, err;
- u_char nexthop_num;
- struct nexthop *nexthop;
- struct bgp_nexthop_cache *bnc;
-
- s = zlookup->ibuf;
- stream_reset (s);
-
- err = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
- &vrf_id, &cmd);
- if (err < 0)
- {
- zlog_err("%s: zserv_read_header() failed", __func__);
- return NULL;
- }
-
- /* XXX: not actually doing anything with raddr */
- 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++)
- {
- nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
- 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;
- default:
- /* do nothing */
- break;
- }
- 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);
- zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, VRF_DEFAULT);
- stream_put (s, addr, 16);
- stream_putw_at (s, 0, stream_get_endp (s));
-
- ret = writen (zlookup->sock, s->data, stream_get_endp (s));
- 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 ();
-}
-
-static int
-bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
- struct in_addr *igpnexthop)
-{
- struct stream *s;
- int ret;
- u_int16_t length, vrf_id, command;
- u_char version, marker;
- struct in_addr addr __attribute__((unused));
- 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);
- zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP, VRF_DEFAULT);
-
- stream_putc (s, p->prefixlen);
- stream_put_in_addr (s, &p->u.prefix4);
-
- stream_putw_at (s, 0, stream_get_endp (s));
-
- /* Write the packet. */
- ret = writen (zlookup->sock, s->data, stream_get_endp (s));
-
- 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);
-
- ret = zclient_read_header (s, zlookup->sock, &length, &marker, &version,
- &vrf_id, &command);
- if (ret < 0)
- {
- zlog_err("%s: zserv_read_header() failed", __func__);
- return 0;
- }
-
- /* XXX: not using addr */
- 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);
- switch (nexthop_type)
- {
- case ZEBRA_NEXTHOP_IPV4:
- nexthop.s_addr = stream_get_ipv4 (s);
- break;
- case ZEBRA_NEXTHOP_IPV4_IFINDEX:
- nexthop.s_addr = stream_get_ipv4 (s);
- /* ifindex */ (void)stream_getl (s);
- break;
- default:
- /* do nothing */
- break;
- }
- *igpnexthop = nexthop;
-
- return 1;
- }
- else
- return 0;
-}
-
-/* Scan all configured BGP route then check the route exists in IGP or
- not. */
-static int
-bgp_import (struct thread *t)
-{
- struct bgp *bgp;
- struct bgp_node *rn;
- struct bgp_static *bgp_static;
- struct listnode *node, *nnode;
- int valid;
- u_int32_t metric;
- struct in_addr nexthop;
- afi_t afi;
- safi_t safi;
-
- bgp_import_thread =
- thread_add_timer (bm->master, bgp_import, NULL, bgp_import_interval);
-
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("Import timer expired.");
-
- for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
- {
- 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)
- {
- if (bgp_static->backdoor)
- continue;
-
- 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);
- else
- {
- 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);
- }
- }
- }
- return 0;
-}
-
-/* Connect to zebra for nexthop lookup. */
-static int
-zlookup_connect (struct thread *t)
-{
- struct zclient *zlookup;
-
- zlookup = THREAD_ARG (t);
- zlookup->t_connect = NULL;
-
- if (zlookup->sock != -1)
- return 0;
-
- if (zclient_socket_connect (zlookup) < 0)
- return -1;
-
- return 0;
-}
-
-/* Check specified multiaccess next-hop. */
int
-bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
+bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
{
struct bgp_node *rn1;
struct bgp_node *rn2;
- struct prefix p1;
- struct prefix p2;
- struct in_addr addr;
+ struct prefix p;
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;
+ p.family = AF_INET;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ p.u.prefix4 = nexthop;
- rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
- if (! rn1)
- return 0;
- bgp_unlock_node (rn1);
-
- rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
- if (! rn2)
+ rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
+ if (!rn1)
return 0;
- bgp_unlock_node (rn2);
- /* This is safe, even with above unlocks, since we are just
- comparing pointers to the objects, not the objects themselves. */
- if (rn1 == rn2)
- return 1;
-
- return 0;
-}
-
-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]);
+ p.family = AF_INET;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ p.u.prefix4 = peer->su.sin.sin_addr;
- if (bgp_scan_thread)
+ rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p);
+ if (!rn2)
{
- thread_cancel (bgp_scan_thread);
- bgp_scan_thread =
- thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
+ bgp_unlock_node(rn1);
+ return 0;
}
- return CMD_SUCCESS;
-}
+ ret = (rn1 == rn2) ? 1 : 0;
-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;
+ bgp_unlock_node(rn1);
+ bgp_unlock_node(rn2);
- if (bgp_scan_thread)
- {
- thread_cancel (bgp_scan_thread);
- bgp_scan_thread =
- thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval);
- }
-
- return CMD_SUCCESS;
+ return (ret);
}
-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")
-
static int
-show_ip_bgp_scan_tables (struct vty *vty, const char detail)
+show_ip_bgp_nexthop_table (struct vty *vty, int detail)
{
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
char buf[INET6_ADDRSTRLEN];
- u_char i;
-
- 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);
+ struct nexthop *nexthop;
+ time_t tbuf;
+ afi_t afi;
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 (bnc->valid)
- {
- vty_out (vty, " %s valid [IGP metric %d]%s",
- 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++)
- 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_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;
- 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_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
- }
-
- {
- for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
- rn;
- rn = bgp_route_next (rn))
- if ((bnc = rn->info) != NULL)
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ {
+ for (rn = bgp_table_top (bgp_nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
{
- if (bnc->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)
+ if ((bnc = rn->info) != NULL)
+ {
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
{
- 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);
+ vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
+ inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
+ bnc->metric, bnc->path_count, VTY_NEWLINE);
+ if (detail)
+ for (nexthop = bnc->nexthop ; nexthop; nexthop = nexthop->next)
+ switch (nexthop->type)
+ {
+ case NEXTHOP_TYPE_IPV6:
+ vty_out (vty, " gate %s%s",
+ inet_ntop (AF_INET6, &nexthop->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, &nexthop->gate.ipv6, buf,
+ INET6_ADDRSTRLEN),
+ ifindex2ifname(nexthop->ifindex),
+ VTY_NEWLINE);
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ vty_out (vty, " gate %s%s",
+ inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
+ INET6_ADDRSTRLEN), VTY_NEWLINE);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ vty_out (vty, " if %s%s",
+ ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
+ break;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ vty_out (vty, " gate %s, if %s%s",
+ inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
+ INET6_ADDRSTRLEN),
+ ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
+ break;
+ default:
+ vty_out (vty, " invalid nexthop type %u%s",
+ nexthop->type, VTY_NEWLINE);
+ }
}
- }
- else
- vty_out (vty, " %s invalid%s",
- inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
- VTY_NEWLINE);
+ else
+ vty_out (vty, " %s invalid%s",
+ inet_ntop (AF_INET, &rn->p.u.prefix, buf, sizeof (buf)), 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);
+ }
}
- }
-
- vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
- for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
- rn;
- rn = bgp_route_next (rn))
- if (rn->info != NULL)
- vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
- VTY_NEWLINE);
-
- {
- for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
- rn;
- rn = bgp_route_next (rn))
- if (rn->info != NULL)
- vty_out (vty, " %s/%d%s",
- inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
- rn->p.prefixlen,
- VTY_NEWLINE);
- }
-
+ }
return CMD_SUCCESS;
}
-DEFUN (show_ip_bgp_scan,
- show_ip_bgp_scan_cmd,
- "show ip bgp scan",
+DEFUN (show_ip_bgp_nexthop,
+ show_ip_bgp_nexthop_cmd,
+ "show ip bgp nexthop",
SHOW_STR
IP_STR
BGP_STR
- "BGP scan status\n")
+ "BGP nexthop table\n")
{
- return show_ip_bgp_scan_tables (vty, 0);
+ return show_ip_bgp_nexthop_table (vty, 0);
}
-DEFUN (show_ip_bgp_scan_detail,
- show_ip_bgp_scan_detail_cmd,
- "show ip bgp scan detail",
+DEFUN (show_ip_bgp_nexthop_detail,
+ show_ip_bgp_nexthop_detail_cmd,
+ "show ip bgp nexthop detail",
SHOW_STR
IP_STR
BGP_STR
- "BGP scan status\n"
- "More detailed output\n")
+ "BGP nexthop table\n")
{
- return show_ip_bgp_scan_tables (vty, 1);
-}
-
-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;
+ return show_ip_bgp_nexthop_table (vty, 1);
}
void
bgp_scan_init (void)
{
- zlookup = zclient_new (bm->master);
- zlookup->sock = -1;
- zlookup->t_connect = thread_add_event (bm->master, zlookup_connect, zlookup, 0);
-
- bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
- bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
-
cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
- cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
- cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
- /* Make BGP scan thread. */
- bgp_scan_thread = thread_add_timer (bm->master, bgp_scan_timer,
- NULL, bgp_scan_interval);
- /* Make BGP import there. */
- bgp_import_thread = thread_add_timer (bm->master, bgp_import, NULL, 0);
-
- 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);
- install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
- install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
- install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
- install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
+}
+
+void
+bgp_scan_vty_init()
+{
+ install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd);
}
void
@@ -1432,10 +534,6 @@ bgp_scan_finish (void)
bgp_table_unlock (cache1_table[AFI_IP]);
cache1_table[AFI_IP] = NULL;
- if (cache2_table[AFI_IP])
- bgp_table_unlock (cache2_table[AFI_IP]);
- cache2_table[AFI_IP] = NULL;
-
if (bgp_connected_table[AFI_IP])
bgp_table_unlock (bgp_connected_table[AFI_IP]);
bgp_connected_table[AFI_IP] = NULL;
@@ -1444,10 +542,6 @@ bgp_scan_finish (void)
bgp_table_unlock (cache1_table[AFI_IP6]);
cache1_table[AFI_IP6] = NULL;
- if (cache2_table[AFI_IP6])
- bgp_table_unlock (cache2_table[AFI_IP6]);
- cache2_table[AFI_IP6] = NULL;
-
if (bgp_connected_table[AFI_IP6])
bgp_table_unlock (bgp_connected_table[AFI_IP6]);
bgp_connected_table[AFI_IP6] = NULL;
@@ -1456,12 +550,5 @@ bgp_scan_finish (void)
void
bgp_scan_destroy (void)
{
- if (zlookup == NULL)
- return;
- THREAD_OFF(bgp_import_thread);
- THREAD_OFF(bgp_scan_thread);
- THREAD_OFF(zlookup->t_connect);
bgp_scan_finish();
- zclient_free (zlookup);
- zlookup = NULL;
}
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 85c5a5d0..fe4f5ad4 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -22,9 +22,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define _QUAGGA_BGP_NEXTHOP_H
#include "if.h"
-
-#define BGP_SCAN_INTERVAL_DEFAULT 60
-#define BGP_IMPORT_INTERVAL_DEFAULT 15
+#include "queue.h"
+#include "prefix.h"
#define NEXTHOP_FAMILY(nexthop_len) ( \
((nexthop_len) == 4 || \
@@ -38,35 +37,48 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* BGP nexthop cache value structure. */
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. */
u_int32_t metric;
/* Nexthop number and nexthop linked list.*/
u_char nexthop_num;
struct nexthop *nexthop;
+ time_t last_update;
+ u_int16_t flags;
+
+#define BGP_NEXTHOP_VALID (1 << 0)
+#define BGP_NEXTHOP_REGISTERED (1 << 1)
+#define BGP_NEXTHOP_CONNECTED (1 << 2)
+#define BGP_NEXTHOP_PEER_NOTIFIED (1 << 3)
+
+ u_int16_t change_flags;
+
+#define BGP_NEXTHOP_CHANGED (1 << 0)
+#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
+#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
+
+ struct bgp_node *node;
+ void *nht_info; /* In BGP, peer session */
+ LIST_HEAD(path_list, bgp_info) paths;
+ 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 *,
int *, int *);
extern void bgp_connected_add (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_nexthop_onlink (afi_t, struct attr *);
extern int bgp_nexthop_self (struct attr *);
extern void bgp_address_init (void);
extern void bgp_address_destroy (void);
extern void bgp_scan_destroy (void);
+extern struct bgp_nexthop_cache *bnc_new(void);
+extern void bnc_free(struct bgp_nexthop_cache *bnc);
+extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
+extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
+extern void bgp_scan_init (void);
+extern void bgp_scan_vty_init (void);
#endif /* _QUAGGA_BGP_NEXTHOP_H */
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
new file mode 100644
index 00000000..34b5fd1c
--- /dev/null
+++ b/bgpd/bgp_nht.c
@@ -0,0 +1,518 @@
+/* BGP Nexthop tracking
+ * Copyright (C) 2013 Cumulus Networks, Inc.
+ *
+ * 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"
+#include "nexthop.h"
+#include "filter.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_fsm.h"
+
+extern struct zclient *zclient;
+extern struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
+
+static void register_nexthop(struct bgp_nexthop_cache *bnc);
+static void unregister_nexthop (struct bgp_nexthop_cache *bnc);
+static void evaluate_paths(struct bgp_nexthop_cache *bnc);
+static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
+static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
+ int keep);
+
+int
+bgp_find_nexthop (struct bgp_info *path, int connected)
+{
+ struct bgp_nexthop_cache *bnc = path->nexthop;
+
+ if (!bnc)
+ return 0;
+
+ if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
+ return 0;
+
+ return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
+}
+
+void
+bgp_unlink_nexthop (struct bgp_info *path)
+{
+ struct bgp_nexthop_cache *bnc = path->nexthop;
+
+ if (!bnc)
+ return;
+
+ path_nh_map(path, NULL, 0);
+
+ if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
+ {
+ if (BGP_DEBUG(nht, NHT))
+ {
+ char buf[INET6_ADDRSTRLEN];
+ zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
+ bnc_str(bnc, buf, INET6_ADDRSTRLEN));
+ }
+ unregister_nexthop(bnc);
+ bnc->node->info = NULL;
+ bgp_unlock_node(bnc->node);
+ bnc_free(bnc);
+ }
+}
+
+int
+bgp_find_or_add_nexthop (afi_t afi, struct bgp_info *ri, struct peer *peer,
+ int connected)
+{
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct prefix p;
+
+ if (ri)
+ {
+ if (make_prefix(afi, ri, &p) < 0)
+ 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);
+
+ if (!rn->info)
+ {
+ bnc = bnc_new();
+ rn->info = bnc;
+ bnc->node = rn;
+ bgp_lock_node(rn);
+ if (connected)
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
+ }
+
+ bnc = rn->info;
+ bgp_unlock_node (rn);
+
+ if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
+ register_nexthop(bnc);
+
+ if (ri)
+ {
+ path_nh_map(ri, bnc, 1);
+
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
+ (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
+ else if (ri->extra)
+ ri->extra->igpmetric = 0;
+ }
+ else if (peer)
+ bnc->nht_info = (void *)peer;
+
+ return (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID));
+}
+
+void
+bgp_parse_nexthop_update (void)
+{
+ struct stream *s;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct nexthop *nexthop;
+ struct nexthop *oldnh;
+ struct nexthop *nhlist_head = NULL;
+ struct nexthop *nhlist_tail = NULL;
+ uint32_t metric;
+ u_char nexthop_num;
+ struct prefix p;
+ int i;
+
+ s = zclient->ibuf;
+
+ memset(&p, 0, sizeof(struct prefix));
+ p.family = stream_getw(s);
+ p.prefixlen = stream_getc(s);
+ switch (p.family)
+ {
+ case AF_INET:
+ p.u.prefix4.s_addr = stream_get_ipv4 (s);
+ break;
+ case AF_INET6:
+ stream_get(&p.u.prefix6, s, 16);
+ break;
+ default:
+ break;
+ }
+
+ rn = bgp_node_lookup(bgp_nexthop_cache_table[family2afi(p.family)], &p);
+ if (!rn || !rn->info)
+ {
+ if (BGP_DEBUG(nht, NHT))
+ {
+ char buf[INET6_ADDRSTRLEN];
+ prefix2str(&p, buf, INET6_ADDRSTRLEN);
+ zlog_debug("parse nexthop update(%s): rn not found", buf);
+ }
+ if (rn)
+ bgp_unlock_node (rn);
+ return;
+ }
+
+ bnc = rn->info;
+ bgp_unlock_node (rn);
+ bnc->last_update = bgp_clock();
+ bnc->change_flags = 0;
+ metric = stream_getl (s);
+ nexthop_num = stream_getc (s);
+
+ /* debug print the input */
+ if (BGP_DEBUG(nht, NHT))
+ {
+ char buf[INET6_ADDRSTRLEN];
+ prefix2str(&p, buf, INET6_ADDRSTRLEN);
+ zlog_debug("parse nexthop update(%s): metric=%d, #nexthop=%d", buf,
+ metric, nexthop_num);
+ }
+
+ if (metric != bnc->metric)
+ bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
+
+ if(nexthop_num != bnc->nexthop_num)
+ bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+
+ if (nexthop_num)
+ {
+ bnc->flags |= BGP_NEXTHOP_VALID;
+ bnc->metric = metric;
+ bnc->nexthop_num = nexthop_num;
+
+ for (i = 0; i < nexthop_num; i++)
+ {
+ nexthop = nexthop_new();
+ nexthop->type = stream_getc (s);
+ switch (nexthop->type)
+ {
+ case ZEBRA_NEXTHOP_IPV4:
+ nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
+ break;
+ case ZEBRA_NEXTHOP_IFINDEX:
+ case ZEBRA_NEXTHOP_IFNAME:
+ nexthop->ifindex = stream_getl (s);
+ break;
+ case ZEBRA_NEXTHOP_IPV4_IFINDEX:
+ case ZEBRA_NEXTHOP_IPV4_IFNAME:
+ nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
+ nexthop->ifindex = stream_getl (s);
+ break;
+#ifdef HAVE_IPV6
+ 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;
+#endif
+ default:
+ /* do nothing */
+ break;
+ }
+
+ if (nhlist_tail)
+ {
+ nhlist_tail->next = nexthop;
+ nhlist_tail = nexthop;
+ }
+ else
+ {
+ nhlist_tail = nexthop;
+ nhlist_head = nexthop;
+ }
+
+ /* No need to evaluate the nexthop if we have already determined
+ * that there has been a change.
+ */
+ if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
+ continue;
+
+ for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
+ if (nexthop_same_no_recurse(oldnh, nexthop))
+ break;
+
+ if (!oldnh)
+ bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+ }
+ bnc_nexthop_free(bnc);
+ bnc->nexthop = nhlist_head;
+ }
+ else
+ {
+ bnc->flags &= ~BGP_NEXTHOP_VALID;
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
+ bnc_nexthop_free(bnc);
+ bnc->nexthop = NULL;
+ }
+
+ evaluate_paths(bnc);
+}
+
+/**
+ * make_prefix - make a prefix structure from the path (essentially
+ * path's node.
+ */
+static int
+make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
+{
+ memset (p, 0, sizeof (struct prefix));
+ switch (afi)
+ {
+ case AFI_IP:
+ p->family = AF_INET;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ p->u.prefix4 = ri->attr->nexthop;
+ break;
+#ifdef HAVE_IPV6
+ case AFI_IP6:
+ if (ri->attr->extra->mp_nexthop_len != 16
+ || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
+ return -1;
+
+ p->family = AF_INET6;
+ p->prefixlen = IPV6_MAX_BITLEN;
+ p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
+ break;
+#endif
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * sendmsg_nexthop -- Format and send a nexthop register/Unregister
+ * command to Zebra.
+ * ARGUMENTS:
+ * struct bgp_nexthop_cache *bnc -- the nexthop structure.
+ * int command -- either ZEBRA_NEXTHOP_REGISTER or ZEBRA_NEXTHOP_UNREGISTER
+ * RETURNS:
+ * void.
+ */
+static void
+sendmsg_nexthop (struct bgp_nexthop_cache *bnc, int command)
+{
+ struct stream *s;
+ struct prefix *p;
+ int ret;
+
+ /* Check socket. */
+ if (!zclient || zclient->sock < 0)
+ {
+ zlog_debug("%s: Can't send NH register, Zebra client not established",
+ __FUNCTION__);
+ return;
+ }
+
+ p = &(bnc->node->p);
+ s = zclient->obuf;
+ stream_reset (s);
+ zclient_create_header (s, command, VRF_DEFAULT);
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
+ stream_putc(s, 1);
+ else
+ stream_putc(s, 0);
+
+ stream_putw(s, PREFIX_FAMILY(p));
+ stream_putc(s, p->prefixlen);
+ switch (PREFIX_FAMILY(p))
+ {
+ case AF_INET:
+ stream_put_in_addr (s, &p->u.prefix4);
+ break;
+ case AF_INET6:
+ stream_put(s, &(p->u.prefix6), 16);
+ break;
+ default:
+ break;
+ }
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ ret = zclient_send_message(zclient);
+ /* TBD: handle the failure */
+ if (ret < 0)
+ 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;
+}
+
+/**
+ * register_nexthop - register a nexthop with Zebra for notification
+ * when the route to the nexthop changes.
+ * ARGUMENTS:
+ * struct bgp_nexthop_cache *bnc -- the nexthop structure.
+ * RETURNS:
+ * void.
+ */
+static void
+register_nexthop (struct bgp_nexthop_cache *bnc)
+{
+ /* Check if we have already registered */
+ if (bnc->flags & BGP_NEXTHOP_REGISTERED)
+ return;
+ sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_REGISTER);
+}
+
+/**
+ * unregister_nexthop -- Unregister the nexthop from Zebra.
+ * ARGUMENTS:
+ * struct bgp_nexthop_cache *bnc -- the nexthop structure.
+ * RETURNS:
+ * void.
+ */
+static void
+unregister_nexthop (struct bgp_nexthop_cache *bnc)
+{
+ /* Check if we have already registered */
+ if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
+ return;
+
+ sendmsg_nexthop(bnc, ZEBRA_NEXTHOP_UNREGISTER);
+}
+
+/**
+ * evaluate_paths - Evaluate the paths/nets associated with a nexthop.
+ * ARGUMENTS:
+ * struct bgp_nexthop_cache *bnc -- the nexthop structure.
+ * RETURNS:
+ * void.
+ */
+static void
+evaluate_paths (struct bgp_nexthop_cache *bnc)
+{
+ struct bgp_node *rn;
+ struct bgp_info *path;
+ struct bgp *bgp = bgp_get_default();
+ int afi;
+ struct peer *peer = (struct peer *)bnc->nht_info;
+
+ LIST_FOREACH(path, &(bnc->paths), nh_thread)
+ {
+ if (!(path->type == ZEBRA_ROUTE_BGP &&
+ path->sub_type == BGP_ROUTE_NORMAL))
+ continue;
+
+ rn = path->net;
+ afi = family2afi(rn->p.family);
+
+ /* Path becomes valid/invalid depending on whether the nexthop
+ * reachable/unreachable.
+ */
+ if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
+ (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? 1 : 0))
+ {
+ if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
+ {
+ bgp_aggregate_decrement (bgp, &rn->p, path,
+ afi, SAFI_UNICAST);
+ bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
+ }
+ else
+ {
+ bgp_info_set_flag (rn, path, BGP_INFO_VALID);
+ bgp_aggregate_increment (bgp, &rn->p, path,
+ afi, SAFI_UNICAST);
+ }
+ }
+
+ /* Copy the metric to the path. Will be used for bestpath computation */
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
+ (bgp_info_extra_get(path))->igpmetric = bnc->metric;
+ else if (path->extra)
+ path->extra->igpmetric = 0;
+
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_METRIC_CHANGED) ||
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CHANGED))
+ SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
+
+ 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);
+}
+
+/**
+ * path_nh_map - make or break path-to-nexthop association.
+ * ARGUMENTS:
+ * path - pointer to the path structure
+ * bnc - pointer to the nexthop structure
+ * make - if set, make the association. if unset, just break the existing
+ * association.
+ */
+static void
+path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
+{
+ if (path->nexthop)
+ {
+ LIST_REMOVE(path, nh_thread);
+ path->nexthop->path_count--;
+ path->nexthop = NULL;
+ }
+ if (make)
+ {
+ LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
+ path->nexthop = bnc;
+ path->nexthop->path_count++;
+ }
+}
diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h
new file mode 100644
index 00000000..2bced7fb
--- /dev/null
+++ b/bgpd/bgp_nht.h
@@ -0,0 +1,58 @@
+/* BGP Nexthop tracking
+ * Copyright (C) 2013 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _BGP_NHT_H
+#define _BGP_NHT_H
+
+/**
+ * bgp_parse_nexthop_update() - parse a nexthop update message from Zebra.
+ */
+extern void bgp_parse_nexthop_update(void);
+
+/**
+ * bgp_find_nexthop() - lookup the nexthop cache table for the bnc object
+ * ARGUMENTS:
+ * p - path for which the nexthop object is being looked up
+ * connected - True if NH MUST be a connected route
+ */
+extern int bgp_find_nexthop(struct bgp_info *p, int connected);
+
+/**
+ * bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc
+ * object. If not found, create a new object and register with ZEBRA for
+ * nexthop notification.
+ * ARGUMENTS:
+ * a - afi: AFI_IP or AF_IP6
+ * p - path for which the nexthop object is being looked up
+ * peer - The BGP peer associated with this NHT
+ * connected - True if NH MUST be a connected route
+ */
+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.
+ * ARGUMENTS:
+ * p - path structure.
+ */
+extern void bgp_unlink_nexthop(struct bgp_info *p);
+
+#endif /* _BGP_NHT_H */
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 7b8b6577..35387f17 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -160,7 +160,7 @@ bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
bgp_capability_mp_data (s, &mpc);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
peer->host, mpc.afi, mpc.safi);
@@ -182,7 +182,7 @@ static void
bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
u_char type, u_char mode)
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
peer->host, afi, safi, type, mode);
}
@@ -221,7 +221,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
afi = entry.mpc.afi;
safi = entry.mpc.safi;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
peer->host, entry.mpc.afi, entry.mpc.safi);
@@ -298,7 +298,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
continue;
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s OPEN has %s ORF capability"
" as %s for afi/safi: %d/%d",
peer->host, LOOKUP (orf_type_str, type),
@@ -353,7 +353,7 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
UNSET_FLAG (restart_flag_time, 0xF000);
peer->v_gr_restart = restart_flag_time;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
@@ -371,21 +371,21 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
if (!bgp_afi_safi_valid_indices (afi, &safi))
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
" Ignore the Graceful Restart capability",
peer->host, afi, safi);
}
else if (!peer->afc[afi][safi])
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
" Ignore the Graceful Restart capability",
peer->host, afi, safi);
}
else
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Address family %s is%spreserved", peer->host,
afi_safi_print (afi, safi),
CHECK_FLAG (peer->af_cap[afi][safi],
@@ -507,7 +507,7 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
return -1;
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s OPEN has %s capability (%u), length %u",
peer->host,
LOOKUP (capcode_str, caphdr.code),
@@ -750,7 +750,7 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
ret = 0;
error = error_data;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
peer->host, length);
@@ -781,7 +781,7 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
return -1;
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
peer->host, opt_type,
opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
@@ -851,12 +851,11 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
&& ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
&& ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
{
- plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
+ zlog_err ("%s [Error] Configured AFI/SAFIs do not "
"overlap with received MP capabilities",
peer->host);
if (error != error_data)
-
bgp_notify_send_with_data (peer,
BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNSUP_CAPBL,
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 740b0f1c..3fd584c5 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -103,8 +103,8 @@ bgp_packet_delete (struct peer *peer)
}
/* Check file descriptor whether connect is established. */
-static void
-bgp_connect_check (struct peer *peer)
+int
+bgp_connect_check (struct peer *peer, int change_state)
{
int status;
socklen_t slen;
@@ -121,22 +121,25 @@ bgp_connect_check (struct peer *peer)
/* If getsockopt is fail, this is fatal error. */
if (ret < 0)
{
- zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
+ zlog_info ("can't get sockopt for nonblocking connect");
BGP_EVENT_ADD (peer, TCP_fatal_error);
- return;
+ return -1;
}
/* When status is 0 then TCP connection is established. */
if (status == 0)
{
BGP_EVENT_ADD (peer, TCP_connection_open);
+ return 1;
}
else
{
- if (BGP_DEBUG (events, EVENTS))
- plog_debug (peer->log, "%s [Event] Connect failed (%s)",
- peer->host, safe_strerror (errno));
- BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [Event] Connect failed (%s)",
+ peer->host, safe_strerror (errno));
+ if (change_state)
+ BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+ return 0;
}
}
@@ -153,8 +156,13 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
struct bgp_info *binfo = NULL;
bgp_size_t total_attr_len = 0;
unsigned long attrlen_pos = 0;
+ int space_remaining = 0;
+ int space_needed = 0;
size_t mpattrlen_pos = 0;
size_t mpattr_pos = 0;
+ int num_pfx_adv = 0;
+ char send_attr_str[BUFSIZ];
+ int send_attr_printed = 0;
s = peer->work;
stream_reset (s);
@@ -171,9 +179,12 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
if (adv->binfo)
binfo = adv->binfo;
+ space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
+ BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
+
/* When remaining space can't include NLRI and it's length. */
- if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
- (BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(afi,safi,&rn->p)))
+ if (space_remaining < space_needed)
break;
/* If packet is empty, set attribute. */
@@ -217,6 +228,29 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
&rn->p : NULL),
afi, safi,
from, prd, tag);
+ space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
+ BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);;
+
+ /* If the attributes alone do not leave any room for NLRI then
+ * return */
+ if (space_remaining < space_needed)
+ {
+ zlog_err ("%s cannot send UPDATE, the attributes do not leave "
+ "room for NLRI", peer->host);
+ /* Flush the FIFO update queue */
+ while (adv)
+ adv = bgp_advertise_clean (peer, adv->adj, afi, safi);
+ return NULL;
+ }
+
+ if (BGP_DEBUG (update, UPDATE_OUT) ||
+ BGP_DEBUG (update, UPDATE_PREFIX))
+ {
+ memset (send_attr_str, 0, BUFSIZ);
+ send_attr_printed = 0;
+ bgp_dump_attr (peer, adv->baa->attr, send_attr_str, BUFSIZ);
+ }
}
if (afi == AFI_IP && safi == SAFI_UNICAST)
@@ -237,14 +271,21 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
adv->baa->attr);
bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
}
- if (BGP_DEBUG (update, UPDATE_OUT))
+ num_pfx_adv++;
+
+ if (bgp_debug_update(peer, &rn->p, 0))
{
+ if (!send_attr_printed)
+ {
+ zlog_debug ("%s send UPDATE w/ attr: %s", peer->host, send_attr_str);
+ send_attr_printed = 1;
+ }
char buf[INET6_BUFSIZ];
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
- peer->host,
- inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
- rn->p.prefixlen);
+ zlog_debug ("%s send UPDATE %s/%d",
+ peer->host,
+ inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
+ rn->p.prefixlen);
}
/* Synchnorize attribute. */
@@ -274,8 +315,11 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
else
packet = stream_dup (s);
bgp_packet_set_size (packet);
+ if (BGP_DEBUG (update, UPDATE_OUT))
+ zlog_debug("%s form UPDATE (adv) total len %zd numPfx %d",
+ peer->host,
+ (stream_get_endp (s) - stream_get_getp (s)), num_pfx_adv);
bgp_packet_add (peer, packet);
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
stream_reset (s);
stream_reset (snlri);
return packet;
@@ -291,7 +335,7 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
if (DISABLE_BGP_ANNOUNCE)
return NULL;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -347,6 +391,9 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
size_t attrlen_pos = 0;
size_t mplen_pos = 0;
u_char first_time = 1;
+ int space_remaining = 0;
+ int space_needed = 0;
+ int num_pfx_wd = 0;
s = peer->work;
stream_reset (s);
@@ -357,8 +404,12 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
adj = adv->adj;
rn = adv->rn;
- if (STREAM_REMAIN (s)
- < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
+ space_remaining = STREAM_REMAIN (s) -
+ BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN +
+ bgp_packet_mpattr_prefix_size (afi, safi, &rn->p));
+
+ if (space_remaining < space_needed)
break;
if (stream_empty (s))
@@ -390,15 +441,16 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
}
+ num_pfx_wd++;
- if (BGP_DEBUG (update, UPDATE_OUT))
+ if (bgp_debug_update(peer, &rn->p, 0))
{
char buf[INET6_BUFSIZ];
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
- peer->host,
- inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
- rn->p.prefixlen);
+ zlog_debug ("%s send UPDATE %s/%d -- unreachable",
+ peer->host,
+ inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
+ rn->p.prefixlen);
}
peer->scount[afi][safi]--;
@@ -426,6 +478,10 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
stream_putw_at (s, attrlen_pos, total_attr_len);
}
bgp_packet_set_size (s);
+ if (BGP_DEBUG (update, UPDATE_OUT))
+ zlog_debug("%s form UPDATE (wd) total len %zd numPfx %d",
+ peer->host,
+ (stream_get_endp (s) - stream_get_getp (s)), num_pfx_wd);
packet = stream_dup (s);
bgp_packet_add (peer, packet);
stream_reset (s);
@@ -453,16 +509,16 @@ bgp_default_update_send (struct peer *peer, struct attr *attr,
str2prefix ("::/0", &p);
/* Logging the attribute. */
- if (BGP_DEBUG (update, UPDATE_OUT))
+ if (bgp_debug_update(peer, &p, 0))
{
char attrstr[BUFSIZ];
char buf[INET6_BUFSIZ];
attrstr[0] = '\0';
bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
- peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
- p.prefixlen, attrstr);
+ zlog_debug ("%s send UPDATE %s/%d %s",
+ peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
+ p.prefixlen, attrstr);
}
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -521,13 +577,13 @@ bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
total_attr_len = 0;
- if (BGP_DEBUG (update, UPDATE_OUT))
+ if (bgp_debug_update(peer, &p, 0))
{
char buf[INET6_BUFSIZ];
- zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
- peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
- p.prefixlen);
+ zlog_debug ("%s send UPDATE %s/%d -- unreachable",
+ peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
+ p.prefixlen);
}
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -589,6 +645,12 @@ bgp_write_packet (struct peer *peer)
if (s)
return s;
+ /* The code beyond this part deals with update packets, check if updates
+ are on hold as part of the update-delay post processing stages. */
+ if (peer->bgp && (peer->bgp->main_peers_update_hold ||
+ peer->bgp->rsclient_peers_update_hold))
+ return NULL;
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
@@ -607,7 +669,7 @@ bgp_write_packet (struct peer *peer)
adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
if (adv)
{
- if (adv->binfo && adv->binfo->uptime < peer->synctime)
+ if (adv->binfo && adv->binfo->uptime <= peer->synctime)
{
if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
&& CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
@@ -645,28 +707,82 @@ bgp_write_packet (struct peer *peer)
return NULL;
}
-/* Is there partially written packet or updates we can send right
- now. */
-static int
-bgp_write_proceed (struct peer *peer)
+/* Are there prefixes queued for being withdrawn? */
+int
+bgp_peer_wd_fifo_exists (struct peer *peer)
{
afi_t afi;
safi_t safi;
- struct bgp_advertise *adv;
-
- if (stream_fifo_head (peer->obuf))
- return 1;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
return 1;
+ return 0;
+}
+
+/* Are there prefixes queued for being advertised?
+ * Are they recent?
+ */
+int
+bgp_peer_adv_fifo_exists (struct peer *peer, int chk_recent)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp_advertise *adv;
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
- if (adv->binfo->uptime < peer->synctime)
- return 1;
+ {
+ if (!chk_recent)
+ return 1;
+ if (adv->binfo->uptime < peer->synctime)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Schedule updates for the peer, if needed.
+ */
+void
+bgp_peer_schedule_updates(struct peer *peer)
+{
+ /* If withdraw FIFO exists, immediately schedule write */
+ if (bgp_peer_wd_fifo_exists(peer) && !peer->t_write)
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s scheduling write thread", peer->host);
+ BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ }
+
+ /* If update FIFO exists, fire MRAI timer */
+ if (bgp_peer_adv_fifo_exists(peer, 0) && !peer->radv_adjusted)
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s scheduling MRAI timer", peer->host);
+ bgp_adjust_routeadv(peer);
+ }
+}
+
+/* Is there partially written packet or updates we can send right
+ now. */
+static int
+bgp_write_proceed (struct peer *peer)
+{
+ /* If queued packet exists, we should try to write it */
+ if (stream_fifo_head (peer->obuf))
+ return 1;
+
+ /* If there are prefixes to be withdrawn or to be advertised (and
+ * queued before last MRAI timer expiry), schedule write
+ */
+ if (bgp_peer_wd_fifo_exists(peer)
+ || bgp_peer_adv_fifo_exists(peer, 1))
+ return 1;
return 0;
}
@@ -680,6 +796,7 @@ bgp_write (struct thread *thread)
struct stream *s;
int num;
unsigned int count = 0;
+ unsigned int oc = 0;
/* Yes first of all get peer pointer. */
peer = THREAD_ARG (thread);
@@ -688,7 +805,7 @@ bgp_write (struct thread *thread)
/* For non-blocking IO check. */
if (peer->status == Connect)
{
- bgp_connect_check (peer);
+ bgp_connect_check (peer, 1);
return 0;
}
@@ -698,6 +815,8 @@ bgp_write (struct thread *thread)
sockopt_cork (peer->fd, 1);
+ oc = peer->update_out;
+
/* Nonblocking write until TCP output buffer is full. */
do
{
@@ -765,13 +884,17 @@ bgp_write (struct thread *thread)
/* OK we send packet so delete it. */
bgp_packet_delete (peer);
}
- while (++count < BGP_WRITE_PACKET_MAX &&
+ while (++count < peer->bgp->wpkt_quanta &&
(s = bgp_write_packet (peer)) != NULL);
-
+
if (bgp_write_proceed (peer))
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
done:
+ /* Update the last write if some updates were written. */
+ if (peer->update_out > oc)
+ peer->last_write = bgp_clock ();
+
sockopt_cork (peer->fd, 0);
return 0;
}
@@ -826,6 +949,8 @@ bgp_write_notify (struct peer *peer)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
+ /* Handle Graceful Restart case where the state changes to
+ Connect instead of Idle */
BGP_EVENT_ADD (peer, BGP_Stop);
return 0;
@@ -836,7 +961,6 @@ void
bgp_keepalive_send (struct peer *peer)
{
struct stream *s;
- int length;
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -844,16 +968,13 @@ bgp_keepalive_send (struct peer *peer)
bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
/* Set packet size. */
- length = bgp_packet_set_size (s);
+ (void)bgp_packet_set_size (s);
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
- if (BGP_DEBUG (keepalive, KEEPALIVE))
+ if (bgp_debug_keepalive(peer))
zlog_debug ("%s sending KEEPALIVE", peer->host);
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_KEEPALIVE, length);
/* Add packet to the peer. */
bgp_packet_add (peer, s);
@@ -866,7 +987,6 @@ void
bgp_open_send (struct peer *peer)
{
struct stream *s;
- int length;
u_int16_t send_holdtime;
as_t local_as;
@@ -897,17 +1017,13 @@ bgp_open_send (struct peer *peer)
bgp_open_capability (s, peer);
/* Set BGP packet length. */
- length = bgp_packet_set_size (s);
+ (void)bgp_packet_set_size (s);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
peer->host, BGP_VERSION_4, local_as,
send_holdtime, inet_ntoa (peer->local_id));
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_OPEN, length);
-
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
@@ -984,33 +1100,16 @@ bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
}
}
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_NOTIFY, length);
-
/* peer reset cause */
if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
{
if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
- {
peer->last_reset = PEER_DOWN_USER_RESET;
- zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
- }
else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
- {
peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
- zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
- }
else
- {
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
- zlog_info ("Notification sent to neighbor %s: type %u/%u",
- peer->host, code, sub_code);
- }
}
- else
- zlog_info ("Notification sent to neighbor %s: configuration change",
- peer->host);
/* Call immediately. */
BGP_WRITE_OFF (peer->t_write);
@@ -1031,7 +1130,6 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
u_char orf_type, u_char when_to_refresh, int remove)
{
struct stream *s;
- int length;
struct bgp_filter *filter;
int orf_refresh = 0;
@@ -1074,7 +1172,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
{
UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
@@ -1086,7 +1184,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
ORF_COMMON_PART_DENY);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
@@ -1099,16 +1197,13 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
}
/* Set packet size. */
- length = bgp_packet_set_size (s);
+ (void)bgp_packet_set_size (s);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
if (! orf_refresh)
zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi);
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
- BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
}
/* Add packet to the peer. */
@@ -1123,7 +1218,6 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
int capability_code, int action)
{
struct stream *s;
- int length;
/* Adjust safi code. */
if (safi == SAFI_MPLS_VPN)
@@ -1144,23 +1238,18 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
stream_putc (s, 0);
stream_putc (s, safi);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
peer->host, action == CAPABILITY_ACTION_SET ?
"Advertising" : "Removing", afi, safi);
}
/* Set packet size. */
- length = bgp_packet_set_size (s);
-
+ (void)bgp_packet_set_size (s);
/* Add packet to the peer. */
bgp_packet_add (peer, s);
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_CAPABILITY, length);
-
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
}
@@ -1169,13 +1258,7 @@ static int
bgp_collision_detect (struct peer *new, struct in_addr remote_id)
{
struct peer *peer;
- struct listnode *node, *nnode;
- struct bgp *bgp;
- bgp = bgp_get_default ();
- if (! bgp)
- return 0;
-
/* Upon receipt of an OPEN message, the local system must examine
all of its connections that are in the OpenConfirm state. A BGP
speaker may also examine connections in an OpenSent state if it
@@ -1185,31 +1268,42 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
OPEN message, then the local system performs the following
collision resolution procedure: */
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if ((peer = new->doppelganger) != NULL)
{
- /* Under OpenConfirm status, local peer structure already hold
- remote router ID. */
-
- if (peer != new
- && (peer->status == OpenConfirm || peer->status == OpenSent)
- && sockunion_same (&peer->su, &new->su))
+ /* Do not accept the new connection in Established or Clearing states.
+ * Note that a peer GR is handled by closing the existing connection
+ * upon receipt of new one.
+ */
+ if (peer->status == Established || peer->status == Clearing)
+ {
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return (-1);
+ }
+ else if ((peer->status == OpenConfirm) || (peer->status == OpenSent))
{
/* 1. The BGP Identifier of the local system is compared to
the BGP Identifier of the remote system (as specified in
the OPEN message). */
if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
- {
- /* 2. If the value of the local BGP Identifier is less
- than the remote one, the local system closes BGP
- connection that already exists (the one that is
- already in the OpenConfirm state), and accepts BGP
- connection initiated by the remote system. */
-
- if (peer->fd >= 0)
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
- return 1;
- }
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ {
+ /* 2. If the value of the local BGP Identifier is less
+ than the remote one, the local system closes BGP
+ connection that already exists (the one that is
+ already in the OpenConfirm state), and accepts BGP
+ connection initiated by the remote system. */
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return 1;
+ }
+ else
+ {
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return -1;
+ }
else
{
/* 3. Otherwise, the local system closes newly created
@@ -1217,11 +1311,18 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
received OPEN message), and continues to use the
existing one (the one that is already in the
OpenConfirm state). */
-
- if (new->fd >= 0)
- bgp_notify_send (new, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
- return -1;
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ {
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return 1;
+ }
+ else
+ {
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+ return -1;
+ }
}
}
}
@@ -1238,24 +1339,23 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
u_int16_t send_holdtime;
as_t remote_as;
as_t as4 = 0;
- struct peer *realpeer;
struct in_addr remote_id;
int mp_capability;
u_int8_t notify_data_remote_as[2];
u_int8_t notify_data_remote_id[4];
+ u_int16_t *holdtime_ptr;
- realpeer = NULL;
-
/* Parse open packet. */
version = stream_getc (peer->ibuf);
memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
remote_as = stream_getw (peer->ibuf);
+ holdtime_ptr = (u_int16_t *)stream_pnt (peer->ibuf);
holdtime = stream_getw (peer->ibuf);
memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
/* Receive OPEN message log */
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
" holdtime %d, id %s",
peer->host, version, remote_as, holdtime,
@@ -1294,8 +1394,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_BAD_PEER_AS);
+ bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_BAD_PEER_AS);
return -1;
}
@@ -1325,154 +1425,12 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
}
}
- /* Lookup peer from Open packet. */
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- int as = 0;
-
- realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
-
- if (! realpeer)
- {
- /* Peer's source IP address is check in bgp_accept(), so this
- must be AS number mismatch or remote-id configuration
- mismatch. */
- if (as)
- {
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s bad OPEN, wrong router identifier %s",
- peer->host, inet_ntoa (remote_id));
- bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
- notify_data_remote_id, 4);
- }
- else
- {
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
- peer->host, remote_as, peer->as);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_BAD_PEER_AS,
- notify_data_remote_as, 2);
- }
- return -1;
- }
- }
-
- /* When collision is detected and this peer is closed. Retrun
- immidiately. */
- ret = bgp_collision_detect (peer, remote_id);
- if (ret < 0)
- return ret;
-
- /* Hack part. */
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- if (realpeer->status == Established
- && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
- {
- realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
- SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
- }
- else if (ret == 0 && realpeer->status != Active
- && realpeer->status != OpenSent
- && realpeer->status != OpenConfirm
- && realpeer->status != Connect)
- {
- /* XXX: This is an awful problem..
- *
- * According to the RFC we should just let this connection (of the
- * accepted 'peer') continue on to Established if the other
- * connection (the 'realpeer' one) is in state Connect, and deal
- * with the more larval FSM as/when it gets far enough to receive
- * an Open. We don't do that though, we instead close the (more
- * developed) accepted connection.
- *
- * This means there's a race, which if hit, can loop:
- *
- * FSM for A FSM for B
- * realpeer accept-peer realpeer accept-peer
- *
- * Connect Connect
- * Active
- * OpenSent OpenSent
- * <arrive here,
- * Notify, delete>
- * Idle Active
- * OpenSent OpenSent
- * <arrive here,
- * Notify, delete>
- * Idle
- * <wait> <wait>
- * Connect Connect
- *
- *
- * If both sides are Quagga, they're almost certain to wait for
- * the same amount of time of course (which doesn't preclude other
- * implementations also waiting for same time). The race is
- * exacerbated by high-latency (in bgpd and/or the network).
- *
- * The reason we do this is because our FSM is tied to our peer
- * structure, which carries our configuration information, etc.
- * I.e. we can't let the accepted-peer FSM continue on as it is,
- * cause it's not associated with any actual peer configuration -
- * it's just a dummy.
- *
- * It's possible we could hack-fix this by just bgp_stop'ing the
- * realpeer and continueing on with the 'transfer FSM' below.
- * Ideally, we need to seperate FSMs from struct peer.
- *
- * Setting one side to passive avoids the race, as a workaround.
- */
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s peer status is %s close connection",
- realpeer->host, LOOKUP (bgp_status_msg,
- realpeer->status));
- bgp_notify_send (peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONNECT_REJECT);
-
- return -1;
- }
-
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
- peer->host,
- LOOKUP (bgp_status_msg, realpeer->status));
-
- bgp_stop (realpeer);
-
- /* Transfer file descriptor. */
- realpeer->fd = peer->fd;
- peer->fd = -1;
-
- /* Transfer input buffer. */
- stream_free (realpeer->ibuf);
- realpeer->ibuf = peer->ibuf;
- realpeer->packet_size = peer->packet_size;
- peer->ibuf = NULL;
-
- /* Transfer status. */
- realpeer->status = peer->status;
- bgp_stop (peer);
-
- /* peer pointer change. Open packet send to neighbor. */
- peer = realpeer;
- bgp_open_send (peer);
- if (peer->fd < 0)
- {
- zlog_err ("bgp_open_receive peer's fd is negative value %d",
- peer->fd);
- return -1;
- }
- BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
- }
-
/* remote router-id check. */
if (remote_id.s_addr == 0
|| IPV4_CLASS_DE (ntohl (remote_id.s_addr))
|| ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s bad OPEN, wrong router identifier %s",
peer->host, inet_ntoa (remote_id));
bgp_notify_send_with_data (peer,
@@ -1490,7 +1448,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
u_int16_t maxver = htons(BGP_VERSION_4);
/* XXX this reply may not be correct if version < 4 XXX */
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
peer->host, version, BGP_VERSION_4);
/* Data must be in network byte order here */
@@ -1504,7 +1462,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
/* Check neighbor as number. */
if (remote_as != peer->as)
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
peer->host, remote_as, peer->as);
bgp_notify_send_with_data (peer,
@@ -1522,9 +1480,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (holdtime < 3 && holdtime != 0)
{
- bgp_notify_send (peer,
- BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_UNACEP_HOLDTIME,
+ (u_int8_t *)holdtime_ptr, 2);
return -1;
}
@@ -1559,7 +1518,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
}
else
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
peer->host);
}
@@ -1578,11 +1537,28 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
}
+ /* When collision is detected and this peer is closed. Retrun
+ immidiately. */
+ ret = bgp_collision_detect (peer, remote_id);
+ if (ret < 0)
+ return ret;
+
/* Get sockname. */
- bgp_getsockname (peer);
+ if ((ret = bgp_getsockname (peer)) < 0)
+ {
+ zlog_err("%s: bgp_getsockname() failed for peer: %s", __FUNCTION__,
+ peer->host);
+ return (ret);
+ }
peer->rtt = sockopt_tcp_rtt (peer->fd);
- BGP_EVENT_ADD (peer, Receive_OPEN_message);
+ if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0)
+ {
+ zlog_err("%s: BGP event update failed for peer: %s", __FUNCTION__,
+ peer->host);
+ /* DD: bgp send notify and reset state */
+ return (ret);
+ }
peer->packet_size = 0;
if (peer->ibuf)
@@ -1609,6 +1585,117 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
return -1;
}
+/* Called when there is a change in the EOR(implicit or explicit) status of a peer.
+ Ends the update-delay if all expected peers are done with EORs. */
+void
+bgp_check_update_delay(struct bgp *bgp)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer = NULL;
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Checking update delay, T: %d R: %d I:%d E: %d", bgp->established,
+ bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors);
+
+ if (bgp->established <=
+ bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors)
+ {
+ /* This is an extra sanity check to make sure we wait for all the
+ eligible configured peers. This check is performed if establish wait
+ timer is on, or establish wait option is not given with the
+ update-delay command */
+ if (bgp->t_establish_wait ||
+ (bgp->v_establish_wait == bgp->v_update_delay))
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
+ && !CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
+ && !peer->update_delay_over)
+ {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug (" Peer %s pending, continuing read-only mode",
+ peer->host);
+ return;
+ }
+ }
+
+ zlog_info ("Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d",
+ bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors);
+ bgp_update_delay_end(bgp);
+ }
+}
+
+/* Called if peer is known to have restarted. The restart-state bit in
+ Graceful-Restart capability is used for that */
+void
+bgp_update_restarted_peers (struct peer *peer)
+{
+ if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
+ if (peer->update_delay_over) return; /* This peer has already been considered */
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Peer %s: Checking restarted", peer->host);
+
+ if (peer->status == Established)
+ {
+ peer->update_delay_over = 1;
+ peer->bgp->restarted_peers++;
+ bgp_check_update_delay(peer->bgp);
+ }
+}
+
+/* Called as peer receives a keep-alive. Determines if this occurence can be
+ taken as an implicit EOR for this peer.
+ NOTE: The very first keep-alive after the Established state of a peer is
+ considered implicit EOR for the update-delay purposes */
+void
+bgp_update_implicit_eors (struct peer *peer)
+{
+ if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
+ if (peer->update_delay_over) return; /* This peer has already been considered */
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Peer %s: Checking implicit EORs", peer->host);
+
+ if (peer->status == Established)
+ {
+ peer->update_delay_over = 1;
+ peer->bgp->implicit_eors++;
+ bgp_check_update_delay(peer->bgp);
+ }
+}
+
+/* Should be called only when there is a change in the EOR_RECEIVED status
+ for any afi/safi on a peer */
+static void
+bgp_update_explicit_eors (struct peer *peer)
+{
+ afi_t afi;
+ safi_t safi;
+
+ if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
+ if (peer->update_delay_over) return; /* This peer has already been considered */
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("Peer %s: Checking explicit EORs", peer->host);
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ if (peer->afc_nego[afi][safi] &&
+ !CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED))
+ {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug (" afi %d safi %d didnt receive EOR", afi, safi);
+ return;
+ }
+ }
+
+ peer->update_delay_over = 1;
+ peer->bgp->explicit_eors++;
+ bgp_check_update_delay(peer->bgp);
+}
+
/* Parse BGP Update packet and make attribute object. */
static int
bgp_update_receive (struct peer *peer, bgp_size_t size)
@@ -1646,6 +1733,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
memset (&extra, 0, sizeof (struct attr_extra));
memset (&nlris, 0, sizeof nlris);
attr.extra = &extra;
+ memset (peer->rcvd_attr_str, 0, BUFSIZ);
+ peer->rcvd_attr_printed = 0;
s = peer->ibuf;
end = stream_pnt (s) + size;
@@ -1686,8 +1775,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
nlris[NLRI_WITHDRAW].nlri = stream_pnt (s);
nlris[NLRI_WITHDRAW].length = withdraw_len;
- if (BGP_DEBUG (packet, PACKET_RECV))
- zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
+ zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
stream_forward_getp (s, withdraw_len);
}
@@ -1744,24 +1832,21 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
}
/* Logging the attribute. */
- if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
- || BGP_DEBUG (update, UPDATE_IN))
+ if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW ||
+ BGP_DEBUG (update, UPDATE_IN) ||
+ BGP_DEBUG (update, UPDATE_PREFIX))
{
- char attrstr[BUFSIZ];
- attrstr[0] = '\0';
-
- ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
- int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
- ? LOG_ERR : LOG_DEBUG;
+ ret = bgp_dump_attr (peer, &attr, peer->rcvd_attr_str, BUFSIZ);
if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
- zlog (peer->log, LOG_ERR,
- "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
- peer->host);
+ zlog_err ("%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
+ peer->host);
- if (ret)
- zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
- peer->host, attrstr);
+ if (ret && bgp_debug_update(peer, NULL, 1))
+ {
+ zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str);
+ peer->rcvd_attr_printed = 1;
+ }
}
/* Network Layer Reachability Information. */
@@ -1796,8 +1881,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
*/
if (!bgp_afi_safi_valid_indices (nlris[i].afi, &nlris[i].safi))
{
- plog_info (peer->log,
- "%s [Info] UPDATE with unsupported AFI/SAFI %u/%u",
+ zlog_info ("%s [Info] UPDATE with unsupported AFI/SAFI %u/%u",
peer->host, nlris[i].afi, nlris[i].safi);
continue;
}
@@ -1806,8 +1890,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
Address Family and Subsequent Address Family. */
if (!peer->afc[nlris[i].afi][nlris[i].safi])
{
- plog_info (peer->log,
- "%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u",
+ zlog_info ("%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u",
peer->host, nlris[i].afi, nlris[i].safi);
continue;
}
@@ -1829,8 +1912,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (nlri_ret < 0)
{
- plog_err (peer->log,
- "%s [Error] Error parsing NLRI", peer->host);
+ zlog_err ("%s [Error] Error parsing NLRI", peer->host);
if (peer->status == Established)
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
i <= NLRI_WITHDRAW
@@ -1877,14 +1959,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* End-of-RIB received */
SET_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED);
+ if (!CHECK_FLAG (peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED))
+ {
+ SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
+ PEER_STATUS_EOR_RECEIVED);
+ bgp_update_explicit_eors(peer);
+ }
/* NSF delete stale route */
if (peer->nsf[afi][safi])
bgp_clear_stale_route (peer, afi, safi);
- if (BGP_DEBUG (normal, NORMAL))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for %s from %s",
- peer->host, afi_safi_print (afi, safi));
+ zlog_debug ("rcvd End-of-RIB for %s from %s",
+ peer->host, afi_safi_print (afi, safi));
}
}
@@ -1991,7 +2079,7 @@ bgp_notify_receive (struct peer *peer, bgp_size_t size)
static void
bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
{
- if (BGP_DEBUG (keepalive, KEEPALIVE))
+ if (bgp_debug_keepalive(peer))
zlog_debug ("%s KEEPALIVE rcvd", peer->host);
BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
@@ -2008,7 +2096,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* If peer does not have the capability, send notification. */
if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
{
- plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
+ zlog_err ("%s [Error] BGP route refresh is not enabled",
peer->host);
bgp_notify_send (peer,
BGP_NOTIFY_HEADER_ERR,
@@ -2019,8 +2107,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* Status must be Established. */
if (peer->status != Established)
{
- plog_err (peer->log,
- "%s [Error] Route refresh packet received under status %s",
+ zlog_err ("%s [Error] Route refresh packet received under status %s",
peer->host, LOOKUP (bgp_status_msg, peer->status));
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
return;
@@ -2034,7 +2121,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
stream_getc (s);
safi = stream_getc (s);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_update(peer, NULL, 0))
zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi);
@@ -2043,11 +2130,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|| (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
&& safi != SAFI_MPLS_LABELED_VPN))
{
- if (BGP_DEBUG (normal, NORMAL))
- {
- zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
- peer->host, afi, safi);
- }
+ zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
+ peer->host, afi, safi);
return;
}
@@ -2092,7 +2176,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
char name[BUFSIZ];
int ret;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
peer->host, orf_type, orf_len);
@@ -2119,7 +2203,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* after ++: p_pnt <= p_end */
if (common & ORF_COMMON_PART_REMOVE_ALL)
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
prefix_bgp_orf_remove_all (afi, name);
break;
@@ -2158,7 +2242,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
memcpy (&orfp.p.u.prefix, p_pnt, psize);
p_pnt += psize;
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
{
char buf[INET6_BUFSIZ];
@@ -2179,9 +2263,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
if (!ok || (ok && ret != CMD_SUCCESS))
{
- if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s Received misformatted prefixlist ORF."
- " Remove All pfxlist", peer->host);
+ zlog_info ("%s Received misformatted prefixlist ORF."
+ " Remove All pfxlist", peer->host);
prefix_bgp_orf_remove_all (afi, name);
break;
}
@@ -2191,7 +2274,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
}
stream_forward_getp (s, orf_len);
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
if (when_to_refresh == REFRESH_DEFER)
@@ -2240,7 +2323,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
return -1;
}
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
peer->host, action, hdr->code, hdr->length);
@@ -2267,14 +2350,14 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
if (!bgp_afi_safi_valid_indices (afi, &safi))
{
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
"(%u/%u)", peer->host, afi, safi);
continue;
}
/* Address family check. */
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
peer->host,
action == CAPABILITY_ACTION_SET
@@ -2323,13 +2406,13 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
/* Fetch pointer. */
pnt = stream_pnt (peer->ibuf);
- if (BGP_DEBUG (normal, NORMAL))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s rcv CAPABILITY", peer->host);
/* If peer does not have the capability, send notification. */
if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
{
- plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
+ zlog_err ("%s [Error] BGP dynamic capability is not enabled",
peer->host);
bgp_notify_send (peer,
BGP_NOTIFY_HEADER_ERR,
@@ -2340,8 +2423,8 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
/* Status must be Established. */
if (peer->status != Established)
{
- plog_err (peer->log,
- "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
+ zlog_err ("%s [Error] Dynamic capability packet received under status %s",
+ peer->host, LOOKUP (bgp_status_msg, peer->status));
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
return -1;
}
@@ -2373,8 +2456,8 @@ bgp_read_packet (struct peer *peer)
if (nbytes == -2)
return -1;
- plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
- peer->host, safe_strerror (errno));
+ zlog_err ("%s [Error] bgp_read_packet error: %s",
+ peer->host, safe_strerror (errno));
if (peer->status == Established)
{
@@ -2394,9 +2477,9 @@ bgp_read_packet (struct peer *peer)
/* When read byte is zero : clear bgp peer and return */
if (nbytes == 0)
{
- if (BGP_DEBUG (events, EVENTS))
- plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
- peer->host, peer->fd);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s [Event] BGP connection closed fd %d",
+ peer->host, peer->fd);
if (peer->status == Established)
{
@@ -2451,15 +2534,19 @@ bgp_read (struct thread *thread)
struct peer *peer;
bgp_size_t size;
char notify_data_length[2];
+ u_int32_t notify_out;
/* Yes first of all get peer pointer. */
peer = THREAD_ARG (thread);
peer->t_read = NULL;
+ /* Note notify_out so we can check later to see if we sent another one */
+ notify_out = peer->notify_out;
+
/* For non-blocking IO check. */
if (peer->status == Connect)
{
- bgp_connect_check (peer);
+ bgp_connect_check (peer, 1);
goto done;
}
else
@@ -2490,10 +2577,6 @@ bgp_read (struct thread *thread)
size = stream_getw (peer->ibuf);
type = stream_getc (peer->ibuf);
- if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
- zlog_debug ("%s rcv message type %d, length (excl. header) %d",
- peer->host, type, size - BGP_HEADER_SIZE);
-
/* Marker check */
if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
&& ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
@@ -2511,10 +2594,9 @@ bgp_read (struct thread *thread)
&& type != BGP_MSG_ROUTE_REFRESH_OLD
&& type != BGP_MSG_CAPABILITY)
{
- if (BGP_DEBUG (normal, NORMAL))
- plog_debug (peer->log,
- "%s unknown message type 0x%02x",
- peer->host, type);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s unknown message type 0x%02x",
+ peer->host, type);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESTYPE,
@@ -2532,12 +2614,11 @@ bgp_read (struct thread *thread)
|| (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
|| (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
{
- if (BGP_DEBUG (normal, NORMAL))
- plog_debug (peer->log,
- "%s bad message length - %d for %s",
- peer->host, size,
- type == 128 ? "ROUTE-REFRESH" :
- bgp_type_str[(int) type]);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug ("%s bad message length - %d for %s",
+ peer->host, size,
+ type == 128 ? "ROUTE-REFRESH" :
+ bgp_type_str[(int) type]);
bgp_notify_send_with_data (peer,
BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESLEN,
@@ -2591,17 +2672,30 @@ bgp_read (struct thread *thread)
break;
}
+ /* If reading this packet caused us to send a NOTIFICATION then store a copy
+ * of the packet for troubleshooting purposes
+ */
+ if (notify_out < peer->notify_out)
+ {
+ memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size);
+ peer->last_reset_cause_size = peer->packet_size;
+ notify_out = peer->notify_out;
+ }
+
/* Clear input buffer. */
peer->packet_size = 0;
if (peer->ibuf)
stream_reset (peer->ibuf);
done:
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ /* If reading this packet caused us to send a NOTIFICATION then store a copy
+ * of the packet for troubleshooting purposes
+ */
+ if (notify_out < peer->notify_out)
{
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
- peer_delete (peer);
+ memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size);
+ peer->last_reset_cause_size = peer->packet_size;
}
+
return 0;
}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index 6b0b7f4d..0e490cf7 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -26,6 +26,12 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define BGP_UNFEASIBLE_LEN 2U
#define BGP_WRITE_PACKET_MAX 10U
+/* Size of FIFOs upon which write thread is triggered. Note that write
+ * thread is also triggered upon BGP work-queue completion.
+ */
+#define BGP_ADV_FIFO_QUANTA 500
+#define BGP_WD_FIFO_QUANTA 200
+
/* When to refresh */
#define REFRESH_IMMEDIATE 1
#define REFRESH_DEFER 2
@@ -40,6 +46,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* Packet send and receive function prototypes. */
extern int bgp_read (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_open_send (struct peer *);
@@ -56,4 +63,10 @@ extern int bgp_capability_receive (struct peer *, bgp_size_t);
extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
+extern void bgp_update_restarted_peers (struct peer *);
+extern void bgp_update_implicit_eors (struct peer *);
+extern void bgp_check_update_delay (struct bgp *);
+extern int bgp_peer_wd_fifo_exists (struct peer *);
+extern int bgp_peer_adv_fifo_exists (struct peer *, int);
+extern void bgp_peer_schedule_updates(struct peer *peer);
#endif /* _QUAGGA_BGP_PACKET_H */
diff --git a/bgpd/bgp_regex.c b/bgpd/bgp_regex.c
index 13fa8295..d96f74ce 100644
--- a/bgpd/bgp_regex.c
+++ b/bgpd/bgp_regex.c
@@ -24,6 +24,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "command.h"
#include "memory.h"
#include "filter.h"
+#include "linklist.h"
+#include "prefix.h"
#include "bgpd.h"
#include "bgp_aspath.h"
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index c364372f..4bd6b842 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -55,6 +55,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h"
+#include "bgpd/bgp_nht.h"
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
@@ -126,20 +127,14 @@ bgp_info_extra_get (struct bgp_info *ri)
return ri->extra;
}
-/* Allocate new bgp info structure. */
-static struct bgp_info *
-bgp_info_new (void)
-{
- return XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
-}
-
/* Free bgp route information. */
static void
bgp_info_free (struct bgp_info *binfo)
{
if (binfo->attr)
bgp_attr_unintern (&binfo->attr);
-
+
+ bgp_unlink_nexthop(binfo);
bgp_info_extra_free (&binfo->extra);
bgp_info_mpath_free (&binfo->mpath);
@@ -252,7 +247,7 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
|| ri->peer == ri->peer->bgp->peer_self)
return;
- if (BGP_INFO_HOLDDOWN (ri)
+ if (!BGP_INFO_COUNTABLE (ri)
&& CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
{
@@ -269,7 +264,7 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
zlog_warn ("%s: Please report to Quagga bugzilla", __func__);
}
}
- else if (!BGP_INFO_HOLDDOWN (ri)
+ else if (BGP_INFO_COUNTABLE (ri)
&& !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
{
SET_FLAG (ri->flags, BGP_INFO_COUNTED);
@@ -286,8 +281,8 @@ bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
{
SET_FLAG (ri->flags, flag);
- /* early bath if we know it's not a flag that changes useability state */
- if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+ /* early bath if we know it's not a flag that changes countability state */
+ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED))
return;
bgp_pcount_adjust (rn, ri);
@@ -298,8 +293,8 @@ bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
{
UNSET_FLAG (ri->flags, flag);
- /* early bath if we know it's not a flag that changes useability state */
- if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+ /* early bath if we know it's not a flag that changes countability state */
+ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED))
return;
bgp_pcount_adjust (rn, ri);
@@ -477,6 +472,27 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
if (newm > existm)
return 1;
+ /* 8.1. Same IGP metric. Compare the cluster list length as
+ representative of IGP hops metric. Rewrite the metric value
+ pair (newm, existm) with the cluster list length. Prefer the
+ path with smaller cluster list length. */
+ if (newm == existm)
+ {
+ struct bgp_maxpaths_cfg *mpath_cfg = &bgp->maxpaths[afi][safi];
+ if (peer_sort (new->peer) == BGP_PEER_IBGP
+ && peer_sort (exist->peer) == BGP_PEER_IBGP
+ && CHECK_FLAG (mpath_cfg->ibgp_flags,
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))
+ {
+ newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
+ existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
+ if (newm < existm)
+ ret = 1;
+ if (newm > existm)
+ ret = 0;
+ }
+ }
+
/* 9. Maximum path check. */
if (bgp_mpath_is_configured (bgp, afi, safi))
{
@@ -535,12 +551,8 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
return 1;
/* 12. Cluster length comparision. */
- new_cluster = exist_cluster = 0;
-
- if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- new_cluster = newattre->cluster->length;
- if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- exist_cluster = existattre->cluster->length;
+ new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
+ exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
if (new_cluster < exist_cluster)
return -1;
@@ -582,7 +594,7 @@ bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr,
#define FILTER_EXIST_WARN(F,f,filter) \
if (BGP_DEBUG (update, UPDATE_IN) \
&& !(F ## _IN (filter))) \
- plog_warn (peer->log, "%s: Could not find configured input %s-list %s!", \
+ zlog_warn ("%s: Could not find configured input %s-list %s!", \
peer->host, #f, F ## _IN_NAME(filter));
if (DISTRIBUTE_IN_NAME (filter)) {
@@ -621,7 +633,7 @@ bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr,
#define FILTER_EXIST_WARN(F,f,filter) \
if (BGP_DEBUG (update, UPDATE_OUT) \
&& !(F ## _OUT (filter))) \
- plog_warn (peer->log, "%s: Could not find configured output %s-list %s!", \
+ zlog_warn ("%s: Could not find configured output %s-list %s!", \
peer->host, #f, F ## _OUT_NAME(filter));
if (DISTRIBUTE_OUT_NAME (filter)) {
@@ -694,11 +706,12 @@ bgp_cluster_filter (struct peer *peer, struct attr *attr)
static int
bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi)
+ afi_t afi, safi_t safi, const char *rmap_name)
{
struct bgp_filter *filter;
struct bgp_info info;
route_map_result_t ret;
+ struct route_map *rmap = NULL;
filter = &peer->filter[afi][safi];
@@ -706,8 +719,18 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
if (peer->weight)
(bgp_attr_extra_get (attr))->weight = peer->weight;
+ if (rmap_name)
+ {
+ rmap = route_map_lookup_by_name(rmap_name);
+ }
+ else
+ {
+ if (ROUTE_MAP_IN_NAME(filter))
+ rmap = ROUTE_MAP_IN (filter);
+ }
+
/* Route map apply. */
- if (ROUTE_MAP_IN_NAME (filter))
+ if (rmap)
{
/* Duplicate current value to new strucutre for modification. */
info.peer = peer;
@@ -716,7 +739,56 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN);
/* Apply BGP route map to the attribute. */
- ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info);
+ ret = route_map_apply (rmap, p, RMAP_BGP, &info);
+
+ peer->rmap_type = 0;
+
+ if (ret == RMAP_DENYMATCH)
+ {
+ /* Free newly generated AS path and community by route-map. */
+ bgp_attr_flush (attr);
+ return RMAP_DENY;
+ }
+ }
+ return RMAP_PERMIT;
+}
+
+static int
+bgp_output_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
+ afi_t afi, safi_t safi, const char *rmap_name)
+{
+ struct bgp_filter *filter;
+ struct bgp_info info;
+ route_map_result_t ret;
+ struct route_map *rmap = NULL;
+
+ filter = &peer->filter[afi][safi];
+
+ /* Apply default weight value. */
+ if (peer->weight)
+ (bgp_attr_extra_get (attr))->weight = peer->weight;
+
+ if (rmap_name)
+ {
+ rmap = route_map_lookup_by_name(rmap_name);
+ }
+ else
+ {
+ if (ROUTE_MAP_OUT_NAME(filter))
+ rmap = ROUTE_MAP_OUT (filter);
+ }
+
+ /* Route map apply. */
+ if (rmap)
+ {
+ /* Duplicate current value to new strucutre for modification. */
+ info.peer = peer;
+ info.attr = attr;
+
+ SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT);
+
+ /* Apply BGP route map to the attribute. */
+ ret = route_map_apply (rmap, p, RMAP_BGP, &info);
peer->rmap_type = 0;
@@ -799,6 +871,55 @@ bgp_import_modifier (struct peer *rsclient, struct peer *peer,
return RMAP_PERMIT;
}
+
+/* If this is an EBGP peer with remove-private-AS */
+static void
+bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
+ struct peer *peer, struct attr *attr)
+{
+ if (peer->sort == BGP_PEER_EBGP &&
+ peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))
+ {
+ // Take action on the entire aspath
+ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
+ {
+ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as);
+
+ // The entire aspath consists of private ASNs so create an empty aspath
+ else if (aspath_private_as_check (attr->aspath))
+ attr->aspath = aspath_empty_get ();
+
+ // There are some public and some private ASNs, remove the private ASNs
+ else
+ attr->aspath = aspath_remove_private_asns (attr->aspath);
+ }
+
+ // 'all' was not specified so the entire aspath must be private ASNs
+ // for us to do anything
+ else if (aspath_private_as_check (attr->aspath))
+ {
+ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as);
+ else
+ attr->aspath = aspath_empty_get ();
+ }
+ }
+}
+
+/* If this is an EBGP peer with as-override */
+static void
+bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
+ struct peer *peer, struct attr *attr)
+{
+ if (peer->sort == BGP_PEER_EBGP &&
+ peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
+ {
+ if (aspath_single_asn_check (attr->aspath, peer->as))
+ attr->aspath = aspath_replace_specific_asn (attr->aspath, peer->as, bgp->as);
+ }
+}
+
static int
bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi)
@@ -859,12 +980,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
{
if (IPV4_ADDR_SAME (&peer->remote_id, &riattr->extra->originator_id))
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d originator-id is same as remote router-id",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 0))
+ zlog_debug("%s [Update:SEND] %s/%d originator-id is same as remote router-id",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
return 0;
}
}
@@ -882,12 +1002,11 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
/* Output filter check. */
if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY)
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d is filtered",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 0))
+ zlog_debug("%s [Update:SEND] %s/%d is filtered",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
return 0;
}
@@ -895,10 +1014,9 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
/* AS path loop check. */
if (aspath_loop_check (riattr->aspath, peer->as))
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- peer->host, peer->as);
+ if (bgp_debug_update(peer, p, 0))
+ zlog_debug("%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
+ peer->host, peer->as);
return 0;
}
#endif /* BGP_SEND_ASPATH_CHECK */
@@ -908,11 +1026,10 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
{
if (aspath_loop_check(riattr->aspath, bgp->confed_id))
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- peer->host,
- bgp->confed_id);
+ if (bgp_debug_update(peer, p, 0))
+ zlog_debug("%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
+ peer->host,
+ bgp->confed_id);
return 0;
}
}
@@ -1003,7 +1120,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
|| (NEXTHOP_IS_V6 &&
IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
|| (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. */
if (NEXTHOP_IS_V4)
@@ -1063,11 +1180,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
}
- /* If this is EBGP peer and remove-private-AS is set. */
- if (peer->sort == BGP_PEER_EBGP
- && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
- && aspath_private_as_check (attr->aspath))
- attr->aspath = aspath_empty_get ();
+ bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
+ bgp_peer_as_override(bgp, afi, safi, peer, attr);
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME (filter)
@@ -1084,8 +1198,8 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
/* The route reflector is not allowed to modify the attributes
of the reflected IBGP routes. */
- if (from->sort == BGP_PEER_IBGP
- && peer->sort == BGP_PEER_IBGP)
+ if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) &&
+ !bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY))
{
bgp_attr_dup (&dummy_attr, attr);
info.attr = &dummy_attr;
@@ -1119,9 +1233,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
struct bgp_info info;
struct peer *from;
struct attr *riattr;
+ struct bgp *bgp;
from = ri->peer;
filter = &rsclient->filter[afi][safi];
+ bgp = rsclient->bgp;
riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
if (DISABLE_BGP_ANNOUNCE)
@@ -1153,12 +1269,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
if (IPV4_ADDR_SAME (&rsclient->remote_id,
&riattr->extra->originator_id))
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (rsclient->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d originator-id is same as remote router-id",
- rsclient->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(rsclient, p, 0))
+ zlog_debug ("%s [Update:SEND] %s/%d originator-id is same as remote router-id",
+ rsclient->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
return 0;
}
}
@@ -1176,12 +1291,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
/* Output filter check. */
if (bgp_output_filter (rsclient, p, riattr, afi, safi) == FILTER_DENY)
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (rsclient->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d is filtered",
- rsclient->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(rsclient, p, 0))
+ zlog_debug ("%s [Update:SEND] %s/%d is filtered",
+ rsclient->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
return 0;
}
@@ -1189,10 +1303,9 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
/* AS path loop check. */
if (aspath_loop_check (riattr->aspath, rsclient->as))
{
- if (BGP_DEBUG (filter, FILTER))
- zlog (rsclient->log, LOG_DEBUG,
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- rsclient->host, rsclient->as);
+ if (bgp_debug_update(rsclient, p, 0))
+ zlog_debug ("%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
+ rsclient->host, rsclient->as);
return 0;
}
#endif /* BGP_SEND_ASPATH_CHECK */
@@ -1267,11 +1380,8 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
}
- /* If this is EBGP peer and remove-private-AS is set. */
- if (rsclient->sort == BGP_PEER_EBGP
- && peer_af_flag_check (rsclient, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
- && aspath_private_as_check (attr->aspath))
- attr->aspath = aspath_empty_get ();
+ bgp_peer_remove_private_as(bgp, afi, safi, rsclient, attr);
+ bgp_peer_as_override(bgp, afi, safi, rsclient, attr);
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) )
@@ -1536,8 +1646,23 @@ bgp_process_rsclient (struct work_queue *wq, void *data)
struct bgp_info *old_select;
struct bgp_info_pair old_and_new;
struct listnode *node, *nnode;
- struct peer *rsclient = bgp_node_table (rn)->owner;
-
+ struct peer *rsclient;
+
+ /* Is it end of initial update? (after startup) */
+ if (!rn)
+ {
+ /* This is just to keep the display sane in case all the peers are
+ rsclients only */
+ quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
+ sizeof(bgp->update_delay_zebra_resume_time));
+
+ bgp->rsclient_peers_update_hold = 0;
+ bgp_start_routeadv(bgp);
+ return WQ_SUCCESS;
+ }
+
+ rsclient = bgp_node_table (rn)->owner;
+
/* Best path selection. */
bgp_best_selection (bgp, rn, &old_and_new, afi, safi);
new_select = old_and_new.new;
@@ -1600,20 +1725,38 @@ bgp_process_main (struct work_queue *wq, void *data)
struct bgp_info_pair old_and_new;
struct listnode *node, *nnode;
struct peer *peer;
-
+
+ /* Is it end of initial update? (after startup) */
+ if (!rn)
+ {
+ quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
+ sizeof(bgp->update_delay_zebra_resume_time));
+
+ bgp->main_zebra_update_hold = 0;
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ bgp_zebra_announce_table(bgp, afi, safi);
+ }
+ bgp->main_peers_update_hold = 0;
+
+ bgp_start_routeadv(bgp);
+ return WQ_SUCCESS;
+ }
+
/* Best path selection. */
bgp_best_selection (bgp, rn, &old_and_new, afi, safi);
old_select = old_and_new.old;
new_select = old_and_new.new;
/* Nothing to do. */
- if (old_select && old_select == new_select)
+ if (old_select && old_select == new_select && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR))
{
if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
{
if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) ||
CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG))
- bgp_zebra_announce (p, old_select, bgp, safi);
+ bgp_zebra_announce (p, old_select, bgp, afi, safi);
UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
@@ -1621,6 +1764,9 @@ bgp_process_main (struct work_queue *wq, void *data)
}
}
+ /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set */
+ UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
+
if (old_select)
bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
if (new_select)
@@ -1644,7 +1790,7 @@ bgp_process_main (struct work_queue *wq, void *data)
if (new_select
&& new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_announce (p, new_select, bgp, safi);
+ bgp_zebra_announce (p, new_select, bgp, afi, safi);
else
{
/* Withdraw the route from the kernel. */
@@ -1667,15 +1813,40 @@ static void
bgp_processq_del (struct work_queue *wq, void *data)
{
struct bgp_process_queue *pq = data;
- struct bgp_table *table = bgp_node_table (pq->rn);
-
+ struct bgp_table *table;
+
bgp_unlock (pq->bgp);
- bgp_unlock_node (pq->rn);
- bgp_table_unlock (table);
+ if (pq->rn)
+ {
+ table = bgp_node_table (pq->rn);
+ bgp_unlock_node (pq->rn);
+ bgp_table_unlock (table);
+ }
XFREE (MTYPE_BGP_PROCESS_QUEUE, pq);
}
static void
+bgp_process_queue_complete (struct work_queue *wq)
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ struct listnode *node, *nnode;
+
+ /* Schedule write thread either directly or through the MRAI timer
+ * if needed.
+ */
+ bgp = bgp_get_default ();
+ if (!bgp)
+ return;
+
+ if (BGP_ROUTE_ADV_HOLD(bgp))
+ return;
+
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ bgp_peer_schedule_updates(peer);
+}
+
+void
bgp_process_queue_init (void)
{
bm->process_main_queue
@@ -1691,8 +1862,11 @@ bgp_process_queue_init (void)
bm->process_main_queue->spec.workfunc = &bgp_process_main;
bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
+ bm->process_main_queue->spec.completion_func = &bgp_process_queue_complete;
bm->process_main_queue->spec.max_retries = 0;
bm->process_main_queue->spec.hold = 50;
+ /* Use a higher yield value of 50ms for main queue processing */
+ bm->process_main_queue->spec.yield = 50 * 1000L;
bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
bm->process_rsclient_queue->spec.del_item_data = &bgp_processq_del;
@@ -1753,6 +1927,36 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
return;
}
+void
+bgp_add_eoiu_mark (struct bgp *bgp, bgp_table_t type)
+{
+ struct bgp_process_queue *pqnode;
+
+ if ( (bm->process_main_queue == NULL) ||
+ (bm->process_rsclient_queue == NULL) )
+ bgp_process_queue_init ();
+
+ pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE,
+ sizeof (struct bgp_process_queue));
+ if (!pqnode)
+ return;
+
+ pqnode->rn = NULL;
+ pqnode->bgp = bgp;
+ bgp_lock (bgp);
+ switch (type)
+ {
+ case BGP_TABLE_MAIN:
+ work_queue_add (bm->process_main_queue, pqnode);
+ break;
+ case BGP_TABLE_RSCLIENT:
+ work_queue_add (bm->process_rsclient_queue, pqnode);
+ break;
+ }
+
+ return;
+}
+
static int
bgp_maximum_prefix_restart_timer (struct thread *thread)
{
@@ -1761,11 +1965,11 @@ bgp_maximum_prefix_restart_timer (struct thread *thread)
peer = THREAD_ARG (thread);
peer->t_pmax_restart = NULL;
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Maximum-prefix restart timer expired, restore peering",
peer->host);
- peer_clear (peer);
+ peer_clear (peer, NULL);
return 0;
}
@@ -1783,10 +1987,9 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
&& ! always)
return 0;
- zlog (peer->log, LOG_INFO,
- "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
- "limit %ld", afi_safi_print (afi, safi), peer->host,
- peer->pcount[afi][safi], peer->pmax[afi][safi]);
+ zlog_info ("%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
+ "limit %ld", afi_safi_print (afi, safi), peer->host,
+ peer->pcount[afi][safi], peer->pmax[afi][safi]);
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
@@ -1816,7 +2019,7 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
{
peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60;
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Maximum-prefix restart timer started for %d secs",
peer->host, peer->v_pmax_restart);
@@ -1835,10 +2038,9 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
&& ! always)
return 0;
- zlog (peer->log, LOG_INFO,
- "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
- afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi],
- peer->pmax[afi][safi]);
+ zlog_info ("%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
+ afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi],
+ peer->pmax[afi][safi]);
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);
}
else
@@ -1882,6 +2084,23 @@ bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
bgp_rib_remove (rn, ri, peer, afi, safi);
}
+static struct bgp_info *
+info_make (int type, int sub_type, struct peer *peer, struct attr *attr,
+ struct bgp_node *rn)
+{
+ struct bgp_info *new;
+
+ /* Make new BGP info. */
+ new = XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
+ new->type = type;
+ new->sub_type = sub_type;
+ new->peer = peer;
+ new->attr = attr;
+ new->uptime = bgp_clock ();
+ new->net = rn;
+ return new;
+}
+
static void
bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
struct attr *attr, struct peer *peer, struct prefix *p, int type,
@@ -1974,14 +2193,12 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
&& attrhash_cmp (ri->attr, attr_new))
{
- bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd %s/%d for RS-client %s...duplicate ignored",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen, rsclient->host);
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd %s/%d for RS-client %s...duplicate ignored",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
bgp_unlock_node (rn);
bgp_attr_unintern (&attr_new);
@@ -1994,11 +2211,11 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
bgp_info_restore (rn, ri);
/* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd %s/%d for RS-client %s",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen, rsclient->host);
/* The attribute is changed. */
bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
@@ -2021,21 +2238,15 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
}
/* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
+ if (bgp_debug_update(peer, p, 1))
{
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
+ zlog_debug ("%s rcvd %s/%d for RS-client %s",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen, rsclient->host);
}
- /* Make new BGP info. */
- new = bgp_info_new ();
- new->type = type;
- new->sub_type = sub_type;
- new->peer = peer;
- new->attr = attr_new;
- new->uptime = bgp_clock ();
+ new = info_make(type, sub_type, peer, attr_new, rn);
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
@@ -2057,12 +2268,11 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
filtered:
/* This BGP update is filtered. Log the reason then update BGP entry. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd UPDATE about %s/%d -- DENIED for RS-client %s due to: %s",
- peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host, reason);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd UPDATE about %s/%d -- DENIED for RS-client %s due to: %s",
+ peer->host,
+ inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen, rsclient->host, reason);
if (ri)
bgp_rib_remove (rn, ri, peer, afi, safi);
@@ -2094,11 +2304,10 @@ bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
/* Withdraw specified route from routing table. */
if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
bgp_rib_withdraw (rn, ri, peer, afi, safi, prd);
- else if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s Can't find the route %s/%d", peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ else if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s Can't find the route %s/%d", peer->host,
+ inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
/* Unlock bgp_node_get() lock. */
bgp_unlock_node (rn);
@@ -2120,6 +2329,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
struct bgp_info *new;
const char *reason;
char buf[SU_ADDRSTRLEN];
+ int connected = 0;
memset (&new_attr, 0, sizeof(struct attr));
memset (&new_extra, 0, sizeof(struct attr_extra));
@@ -2190,7 +2400,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
* NB: new_attr may now contain newly allocated values from route-map "set"
* commands, so we need bgp_attr_flush in the error paths, until we intern
* the attr (which takes over the memory references) */
- if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY)
+ if (bgp_input_modifier (peer, p, &new_attr, afi, safi, NULL) == RMAP_DENY)
{
reason = "route-map;";
bgp_attr_flush (&new_attr);
@@ -2200,17 +2410,6 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* IPv4 unicast next hop check. */
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
must not be my own address. */
if (new_attr.nexthop.s_addr == 0
@@ -2234,17 +2433,15 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
&& attrhash_cmp (ri->attr, attr_new))
{
- bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
-
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP
&& CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
{
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd %s/%d",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED)
{
@@ -2254,12 +2451,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
}
else /* Duplicate - odd */
{
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd %s/%d...duplicate ignored",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 1))
+ {
+ if (!peer->rcvd_attr_printed)
+ {
+ zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str);
+ peer->rcvd_attr_printed = 1;
+ }
+
+ zlog_debug ("%s rcvd %s/%d...duplicate ignored",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
+ }
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
@@ -2279,20 +2483,20 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* Withdraw/Announce before we fully processed the withdraw */
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d, flapped quicker than processing",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd %s/%d, flapped quicker than processing",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
bgp_info_restore (rn, ri);
}
/* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd %s/%d",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
@@ -2340,20 +2544,29 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
}
/* Nexthop reachability check. */
- if ((afi == AFI_IP || afi == AFI_IP6)
- && 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 ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
{
- if (bgp_nexthop_lookup (afi, peer, 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);
else
- bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
+ {
+ 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);
+ }
}
else
- bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
bgp_attr_flush (&new_attr);
@@ -2367,38 +2580,48 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
}
/* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
+ if (bgp_debug_update(peer, p, 1))
{
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (!peer->rcvd_attr_printed)
+ {
+ zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str);
+ peer->rcvd_attr_printed = 1;
+ }
+
+ zlog_debug ("%s rcvd %s/%d",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
}
/* Make new BGP info. */
- new = bgp_info_new ();
- new->type = type;
- new->sub_type = sub_type;
- new->peer = peer;
- new->attr = attr_new;
- new->uptime = bgp_clock ();
+ new = info_make(type, sub_type, peer, attr_new, rn);
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
/* Nexthop reachability check. */
- if ((afi == AFI_IP || afi == AFI_IP6)
- && 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_nexthop_lookup (afi, peer, new, NULL, NULL))
+ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
+ {
+ 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);
else
- bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
+ {
+ 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);
@@ -2427,12 +2650,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* This BGP update is filtered. Log the reason then update BGP
entry. */
filtered:
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd UPDATE about %s/%d -- DENIED due to: %s",
- peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, reason);
+ if (bgp_debug_update(peer, p, 1))
+ {
+ if (!peer->rcvd_attr_printed)
+ {
+ zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str);
+ peer->rcvd_attr_printed = 1;
+ }
+
+ zlog_debug ("%s rcvd UPDATE about %s/%d -- DENIED due to: %s",
+ peer->host,
+ inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen, reason);
+ }
if (ri)
bgp_rib_remove (rn, ri, peer, afi, safi);
@@ -2495,11 +2725,11 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
&& peer != bgp->peer_self)
if (!bgp_adj_in_unset (rn, peer))
{
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s withdrawing route %s/%d "
- "not in adj-in", peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update (peer, p, 1))
+ zlog_debug ("%s withdrawing route %s/%d "
+ "not in adj-in", peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
bgp_unlock_node (rn);
return 0;
}
@@ -2512,11 +2742,11 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
}
/* Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd UPDATE about %s/%d -- withdrawn",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s rcvd UPDATE about %s/%d -- withdrawn",
+ peer->host,
+ inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
/* Lookup withdrawn route. */
for (ri = rn->info; ri; ri = ri->next)
@@ -2526,11 +2756,10 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
/* Withdraw specified route from routing table. */
if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
bgp_rib_withdraw (rn, ri, peer, afi, safi, prd);
- else if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s Can't find the route %s/%d", peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ else if (bgp_debug_update(peer, p, 1))
+ zlog_debug ("%s Can't find the route %s/%d", peer->host,
+ inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen);
/* Unlock bgp_node_get() lock. */
bgp_unlock_node (rn);
@@ -2701,6 +2930,12 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi)
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
bgp_announce_table (peer, afi, safi, NULL, 1);
+
+ /*
+ * The write thread needs to be scheduled since it may not be done as
+ * part of building adj_out.
+ */
+ bgp_peer_schedule_updates(peer);
}
void
@@ -3261,8 +3496,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
/* Prefix length check. */
if (p.prefixlen > prefix_blen (&p) * 8)
{
- plog_err (peer->log,
- "%s [Error] Update packet error"
+ zlog_err ("%s [Error] Update packet error"
" (wrong prefix length %u for afi %u)",
peer->host, p.prefixlen, packet->afi);
return -1;
@@ -3274,8 +3508,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
/* When packet overflow occur return immediately. */
if (pnt + psize > lim)
{
- plog_err (peer->log,
- "%s [Error] Update packet error"
+ zlog_err ("%s [Error] Update packet error"
" (prefix length %u overflows packet)",
peer->host, p.prefixlen);
return -1;
@@ -3284,8 +3517,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
/* Defensive coding, double-check the psize fits in a struct prefix */
if (psize > (ssize_t) sizeof(p.u))
{
- plog_err (peer->log,
- "%s [Error] Update packet error"
+ zlog_err ("%s [Error] Update packet error"
" (prefix length %u too large for prefix storage %zu!?!!",
peer->host, p.prefixlen, sizeof(p.u));
return -1;
@@ -3306,9 +3538,8 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
* (e.g., an unexpected multicast IP address), an error SHOULD
* be logged locally, and the prefix SHOULD be ignored.
*/
- zlog (peer->log, LOG_ERR,
- "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
- peer->host, inet_ntoa (p.u.prefix4));
+ zlog_err ("IPv4 unicast NLRI is multicast address %s",
+ inet_ntoa (p.u.prefix4));
continue;
}
}
@@ -3320,18 +3551,15 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
{
char buf[BUFSIZ];
- zlog (peer->log, LOG_ERR,
- "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
- peer->host,
- inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
+ zlog_warn ("IPv6 link-local NLRI received %s ignore this NLRI",
+ inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
continue;
}
if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6))
{
char buf[BUFSIZ];
- zlog (peer->log, LOG_ERR,
- "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
+ zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring",
peer->host,
inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
continue;
@@ -3355,8 +3583,7 @@ bgp_nlri_parse_ip (struct peer *peer, struct attr *attr,
/* Packet length consistency check. */
if (pnt != lim)
{
- plog_err (peer->log,
- "%s [Error] Update packet error"
+ zlog_err ("%s [Error] Update packet error"
" (prefix length mismatch with total length)",
peer->host);
return -1;
@@ -3480,11 +3707,10 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
== RMAP_DENY)
{
/* This BGP update is filtered. Log the reason then update BGP entry. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (rsclient->log, LOG_DEBUG,
- "Static UPDATE about %s/%d -- DENIED for RS-client %s due to: import-policy",
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
+ if (bgp_debug_update(rsclient, p, 1))
+ zlog_debug ("Static UPDATE about %s/%d -- DENIED for RS-client %s due to: import-policy",
+ inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+ p->prefixlen, rsclient->host);
bgp->peer_self->rmap_type = 0;
@@ -3530,6 +3756,23 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
ri->attr = attr_new;
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. */
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
@@ -3538,15 +3781,29 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
return;
}
}
-
+
/* Make new BGP info. */
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_STATIC;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = attr_new;
- new->uptime = bgp_clock ();
+ new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self,
+ attr_new, rn);
+ /* 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. */
bgp_info_add (rn, new);
@@ -3564,7 +3821,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
static void
bgp_static_update_main (struct bgp *bgp, struct prefix *p,
- struct bgp_static *bgp_static, afi_t afi, safi_t safi)
+ struct bgp_static *bgp_static, afi_t afi, safi_t safi)
{
struct bgp_node *rn;
struct bgp_info *ri;
@@ -3648,6 +3905,23 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
ri->attr = attr_new;
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. */
bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi);
@@ -3659,13 +3933,27 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
}
/* Make new BGP info. */
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_STATIC;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = attr_new;
- new->uptime = bgp_clock ();
+ new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, attr_new,
+ rn);
+ /* 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. */
bgp_aggregate_increment (bgp, p, new, afi, safi);
@@ -3706,8 +3994,14 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
{
struct bgp_node *rn;
struct bgp_info *ri;
+ struct bgp_info *new;
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL);
+ /* Make new BGP info. */
+ rn = bgp_node_get (bgp->rib[afi][safi], p);
+ new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self,
+ bgp_attr_default_intern(BGP_ORIGIN_IGP), rn);
+
+ SET_FLAG (new->flags, BGP_INFO_VALID);
/* Check selected route and self inserted route. */
for (ri = rn->info; ri; ri = ri->next)
@@ -3720,6 +4014,7 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+ bgp_unlink_nexthop(ri);
bgp_info_delete (rn, ri);
bgp_process (bgp, rn, afi, safi);
}
@@ -3877,13 +4172,9 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
/* Make new BGP info. */
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_STATIC;
- new->peer = bgp->peer_self;
- new->attr = attr_new;
+ new = info_make (ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self,
+ attr_new, rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
- new->uptime = bgp_clock ();
new->extra = bgp_info_extra_new();
memcpy (new->extra->tag, bgp_static->tag, 3);
@@ -3982,17 +4273,12 @@ bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
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;
-
- if (need_update)
- bgp_static_withdraw (bgp, &p, afi, safi);
+ bgp_static->valid = 1;
+ if (need_update)
+ bgp_static_withdraw (bgp, &p, afi, safi);
- if (! bgp_static->backdoor)
- bgp_static_update (bgp, &p, bgp_static, afi, safi);
- }
+ if (! bgp_static->backdoor)
+ bgp_static_update (bgp, &p, bgp_static, afi, safi);
return CMD_SUCCESS;
}
@@ -4242,6 +4528,84 @@ bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str,
return CMD_SUCCESS;
}
+static int
+bgp_table_map_set (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
+ const char *rmap_name)
+{
+ struct bgp_rmap *rmap;
+
+ rmap = &bgp->table_map[afi][safi];
+ if (rmap_name)
+ {
+ if (rmap->name)
+ free (rmap->name);
+ rmap->name = strdup (rmap_name);
+ rmap->map = route_map_lookup_by_name (rmap_name);
+ }
+ else
+ {
+ if (rmap->name)
+ free (rmap->name);
+ rmap->name = NULL;
+ rmap->map = NULL;
+ }
+
+ bgp_zebra_announce_table(bgp, afi, safi);
+
+ return CMD_SUCCESS;
+}
+
+static int
+bgp_table_map_unset (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
+ const char *rmap_name)
+{
+ struct bgp_rmap *rmap;
+
+ rmap = &bgp->table_map[afi][safi];
+ if (rmap->name)
+ free (rmap->name);
+ rmap->name = NULL;
+ rmap->map = NULL;
+
+ bgp_zebra_announce_table(bgp, afi, safi);
+
+ return CMD_SUCCESS;
+}
+
+int
+bgp_config_write_table_map (struct vty *vty, struct bgp *bgp, afi_t afi,
+ safi_t safi, int *write)
+{
+ if (bgp->table_map[afi][safi].name)
+ {
+ bgp_config_write_family_header (vty, afi, safi, write);
+ vty_out (vty, " table-map %s%s",
+ bgp->table_map[afi][safi].name, VTY_NEWLINE);
+ }
+
+ return 0;
+}
+
+
+DEFUN (bgp_table_map,
+ bgp_table_map_cmd,
+ "table-map WORD",
+ "BGP table to RIB route download filter\n"
+ "Name of the route map\n")
+{
+ return bgp_table_map_set (vty, vty->index,
+ bgp_node_afi (vty), bgp_node_safi (vty), argv[0]);
+}
+DEFUN (no_bgp_table_map,
+ no_bgp_table_map_cmd,
+ "no table-map WORD",
+ "BGP table to RIB route download filter\n"
+ "Name of the route map\n")
+{
+ return bgp_table_map_unset (vty, vty->index,
+ bgp_node_afi (vty), bgp_node_safi (vty), argv[0]);
+}
+
DEFUN (bgp_network,
bgp_network_cmd,
"network A.B.C.D/M",
@@ -4736,6 +5100,7 @@ bgp_aggregate_free (struct bgp_aggregate *aggregate)
XFREE (MTYPE_BGP_AGGREGATE, aggregate);
}
+/* Update an aggregate as routes are added/removed from the BGP table */
static void
bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
afi_t afi, safi_t safi, struct bgp_info *del,
@@ -4753,6 +5118,7 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
struct bgp_info *new;
int first = 1;
unsigned long match = 0;
+ u_char atomic_aggregate = 0;
/* ORIGIN attribute: If at least one route among routes that are
aggregated has ORIGIN with the value INCOMPLETE, then the
@@ -4797,6 +5163,9 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
}
#endif /* AGGREGATE_NEXTHOP_CHECK */
+ if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+ atomic_aggregate = 1;
+
if (ri->sub_type != BGP_ROUTE_AGGREGATE)
{
if (aggregate->summary_only)
@@ -4808,11 +5177,11 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
aggregate->count++;
+ if (origin < ri->attr->origin)
+ origin = ri->attr->origin;
+
if (aggregate->as_set)
{
- if (origin < ri->attr->origin)
- origin = ri->attr->origin;
-
if (aspath)
{
asmerge = aspath_aggregate (aspath, ri->attr->aspath);
@@ -4849,11 +5218,11 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
if (aggregate->summary_only)
(bgp_info_extra_get (rinew))->suppress++;
+ if (origin < rinew->attr->origin)
+ origin = rinew->attr->origin;
+
if (aggregate->as_set)
{
- if (origin < rinew->attr->origin)
- origin = rinew->attr->origin;
-
if (aspath)
{
asmerge = aspath_aggregate (aspath, rinew->attr->aspath);
@@ -4881,13 +5250,11 @@ bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
if (aggregate->count > 0)
{
rn = bgp_node_get (table, p);
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_AGGREGATE;
- new->peer = bgp->peer_self;
+ new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, bgp->peer_self,
+ bgp_attr_aggregate_intern(bgp, origin, aspath, community,
+ aggregate->as_set,
+ atomic_aggregate), rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = bgp_clock ();
bgp_info_add (rn, new);
bgp_unlock_node (rn);
@@ -4976,6 +5343,7 @@ bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p,
bgp_unlock_node (child);
}
+/* Called via bgp_aggregate_set when the user configures aggregate-address */
static void
bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
struct bgp_aggregate *aggregate)
@@ -4991,6 +5359,7 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
struct aspath *asmerge = NULL;
struct community *community = NULL;
struct community *commerge = NULL;
+ u_char atomic_aggregate = 0;
table = bgp->rib[afi][safi];
@@ -5012,6 +5381,9 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
if (BGP_INFO_HOLDDOWN (ri))
continue;
+ if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+ atomic_aggregate = 1;
+
if (ri->sub_type != BGP_ROUTE_AGGREGATE)
{
/* summary-only aggregate route suppress aggregated
@@ -5022,13 +5394,21 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
+
+ /* If at least one route among routes that are aggregated has
+ * ORIGIN with the value INCOMPLETE, then the aggregated route
+ * MUST have the ORIGIN attribute with the value INCOMPLETE.
+ * Otherwise, if at least one route among routes that are
+ * aggregated has ORIGIN with the value EGP, then the aggregated
+ * route MUST have the ORIGIN attribute with the value EGP.
+ */
+ if (origin < ri->attr->origin)
+ origin = ri->attr->origin;
+
/* as-set aggregate route generate origin, as path,
community aggregation. */
if (aggregate->as_set)
{
- if (origin < ri->attr->origin)
- origin = ri->attr->origin;
-
if (aspath)
{
asmerge = aspath_aggregate (aspath, ri->attr->aspath);
@@ -5065,14 +5445,11 @@ bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
if (aggregate->count)
{
rn = bgp_node_get (table, p);
-
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_AGGREGATE;
- new->peer = bgp->peer_self;
+ new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, bgp->peer_self,
+ bgp_attr_aggregate_intern(bgp, origin, aspath, community,
+ aggregate->as_set,
+ atomic_aggregate), rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = bgp_clock ();
bgp_info_add (rn, new);
bgp_unlock_node (rn);
@@ -5602,8 +5979,8 @@ ALIAS (no_ipv6_aggregate_address_summary_only,
/* Redistribute route treatment. */
void
bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
- const struct in6_addr *nexthop6,
- u_int32_t metric, u_char type)
+ const struct in6_addr *nexthop6, unsigned int ifindex,
+ u_int32_t metric, u_char type, u_short tag)
{
struct bgp *bgp;
struct listnode *node, *nnode;
@@ -5620,6 +5997,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
if (nexthop)
attr.nexthop = *nexthop;
+ attr.nh_ifindex = ifindex;
if (nexthop6)
{
@@ -5630,6 +6008,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
attr.med = metric;
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+ attr.extra->tag = tag;
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
{
@@ -5715,16 +6094,12 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
- }
+ }
}
- new = bgp_info_new ();
- new->type = type;
- new->sub_type = BGP_ROUTE_REDISTRIBUTE;
- new->peer = bgp->peer_self;
+ new = info_make(type, BGP_ROUTE_REDISTRIBUTE, bgp->peer_self,
+ new_attr, bn);
SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = new_attr;
- new->uptime = bgp_clock ();
bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
bgp_info_add (bn, new);
@@ -5847,7 +6222,8 @@ route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo)
vty_out (vty, "S");
else if (binfo->extra && binfo->extra->suppress)
vty_out (vty, "s");
- else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+ else if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) &&
+ ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, "*");
else
vty_out (vty, " ");
@@ -6293,7 +6669,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
VTY_NEWLINE);
}
- /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */
+ /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */
vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]);
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
@@ -6306,8 +6682,13 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (attr->extra && attr->extra->weight != 0)
vty_out (vty, ", weight %u", attr->extra->weight);
+
+ if (attr->extra && attr->extra->tag != 0)
+ vty_out (vty, ", tag %d", attr->extra->tag);
- if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+ if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
+ vty_out (vty, ", invalid");
+ else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, ", valid");
if (binfo->peer != bgp->peer_self)
@@ -6756,7 +7137,7 @@ static int
bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
struct bgp_table *rib, const char *ip_str,
afi_t afi, safi_t safi, struct prefix_rd *prd,
- int prefix_check)
+ int prefix_check, enum bgp_path_type pathtype)
{
int ret;
int header;
@@ -6807,7 +7188,12 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
header = 0;
}
display++;
- route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi);
+
+ if (pathtype == BGP_PATH_ALL ||
+ (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
+ (pathtype == BGP_PATH_MULTIPATH &&
+ (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
+ route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi);
}
bgp_unlock_node (rm);
@@ -6831,7 +7217,12 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
header = 0;
}
display++;
- route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
+
+ if (pathtype == BGP_PATH_ALL ||
+ (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
+ (pathtype == BGP_PATH_MULTIPATH &&
+ (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
+ route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
}
}
@@ -6852,7 +7243,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
static int
bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str,
afi_t afi, safi_t safi, struct prefix_rd *prd,
- int prefix_check)
+ int prefix_check, enum bgp_path_type pathtype)
{
struct bgp *bgp;
@@ -6877,7 +7268,7 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str,
}
return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str,
- afi, safi, prd, prefix_check);
+ afi, safi, prd, prefix_check, pathtype);
}
/* BGP route print out function. */
@@ -6916,7 +7307,47 @@ DEFUN (show_ip_bgp_route,
BGP_STR
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
+}
+
+DEFUN (show_ip_bgp_route_pathtype,
+ show_ip_bgp_route_pathtype_cmd,
+ "show ip bgp A.B.C.D (bestpath|multipath)",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[1], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH);
+}
+
+DEFUN (show_bgp_ipv4_safi_route_pathtype,
+ show_bgp_ipv4_safi_route_pathtype_cmd,
+ "show bgp ipv4 (unicast|multicast) A.B.C.D (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_MULTIPATH);
+ else
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH);
}
DEFUN (show_ip_bgp_ipv4_route,
@@ -6931,9 +7362,9 @@ DEFUN (show_ip_bgp_ipv4_route,
"Network in the BGP routing table to display\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_ip_bgp_vpnv4_all_route,
@@ -6946,9 +7377,10 @@ DEFUN (show_ip_bgp_vpnv4_all_route,
"Display information about all VPNv4 NLRIs\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL);
}
+
DEFUN (show_ip_bgp_vpnv4_rd_route,
show_ip_bgp_vpnv4_rd_route_cmd,
"show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D",
@@ -6969,7 +7401,7 @@ DEFUN (show_ip_bgp_vpnv4_rd_route,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL);
}
DEFUN (show_ip_bgp_prefix,
@@ -6980,7 +7412,23 @@ DEFUN (show_ip_bgp_prefix,
BGP_STR
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
+}
+
+DEFUN (show_ip_bgp_prefix_pathtype,
+ show_ip_bgp_prefix_pathtype_cmd,
+ "show ip bgp A.B.C.D/M (bestpath|multipath)",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[1], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH);
}
DEFUN (show_ip_bgp_ipv4_prefix,
@@ -6995,11 +7443,48 @@ DEFUN (show_ip_bgp_ipv4_prefix,
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL);
+
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
+}
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
+DEFUN (show_ip_bgp_ipv4_prefix_pathtype,
+ show_ip_bgp_ipv4_prefix_pathtype_cmd,
+ "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M (bestpath|multipath)",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_MULTIPATH);
+ else
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH);
}
+ALIAS (show_ip_bgp_ipv4_prefix_pathtype,
+ show_bgp_ipv4_safi_prefix_pathtype_cmd,
+ "show bgp ipv4 (unicast|multicast) A.B.C.D/M (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+
DEFUN (show_ip_bgp_vpnv4_all_prefix,
show_ip_bgp_vpnv4_all_prefix_cmd,
"show ip bgp vpnv4 all A.B.C.D/M",
@@ -7010,7 +7495,7 @@ DEFUN (show_ip_bgp_vpnv4_all_prefix,
"Display information about all VPNv4 NLRIs\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_ip_bgp_vpnv4_rd_prefix,
@@ -7033,7 +7518,7 @@ DEFUN (show_ip_bgp_vpnv4_rd_prefix,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1, BGP_PATH_ALL);
}
DEFUN (show_ip_bgp_view,
@@ -7068,7 +7553,7 @@ DEFUN (show_ip_bgp_view_route,
"View name\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_ip_bgp_view_prefix,
@@ -7081,7 +7566,7 @@ DEFUN (show_ip_bgp_view_prefix,
"View name\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp,
@@ -7120,7 +7605,7 @@ DEFUN (show_bgp_route,
BGP_STR
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_safi,
@@ -7150,9 +7635,58 @@ DEFUN (show_bgp_ipv4_safi_route,
"Network in the BGP routing table to display\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL);
+
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
+}
+
+DEFUN (show_bgp_route_pathtype,
+ show_bgp_route_pathtype_cmd,
+ "show bgp X:X::X:X (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Network in the BGP routing table to display\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[1], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH);
+}
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
+ALIAS (show_bgp_route_pathtype,
+ show_bgp_ipv6_route_pathtype_cmd,
+ "show bgp ipv6 X:X::X:X (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Network in the BGP routing table to display\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+
+DEFUN (show_bgp_ipv6_safi_route_pathtype,
+ show_bgp_ipv6_safi_route_pathtype_cmd,
+ "show bgp ipv6 (unicast|multicast) X:X::X:X (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Network in the BGP routing table to display\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_MULTIPATH);
+ else
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_MULTIPATH);
}
DEFUN (show_bgp_ipv4_vpn_route,
@@ -7164,7 +7698,7 @@ DEFUN (show_bgp_ipv4_vpn_route,
"Display VPN NLRI specific information\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_vpn_route,
@@ -7176,7 +7710,7 @@ DEFUN (show_bgp_ipv6_vpn_route,
"Display VPN NLRI specific information\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_vpn_rd_route,
@@ -7199,7 +7733,7 @@ DEFUN (show_bgp_ipv4_vpn_rd_route,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_vpn_rd_route,
@@ -7222,7 +7756,56 @@ DEFUN (show_bgp_ipv6_vpn_rd_route,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MPLS_VPN, &prd, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL);
+}
+
+DEFUN (show_bgp_prefix_pathtype,
+ show_bgp_prefix_pathtype_cmd,
+ "show bgp X:X::X:X/M (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "IPv6 prefix <network>/<length>\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[1], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH);
+}
+
+ALIAS (show_bgp_prefix_pathtype,
+ show_bgp_ipv6_prefix_pathtype_cmd,
+ "show bgp ipv6 X:X::X:X/M (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "IPv6 prefix <network>/<length>\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+
+DEFUN (show_bgp_ipv6_safi_prefix_pathtype,
+ show_bgp_ipv6_safi_prefix_pathtype_cmd,
+ "show bgp ipv6 (unicast|multicast) X:X::X:X/M (bestpath|multipath)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
+ "Display only the bestpath\n"
+ "Display only multipaths\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_MULTIPATH);
+ else
+ if (strncmp (argv[2], "b", 1) == 0)
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_BESTPATH);
+ else
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_MULTIPATH);
}
DEFUN (show_bgp_ipv4_encap_route,
@@ -7234,7 +7817,7 @@ DEFUN (show_bgp_ipv4_encap_route,
"Display ENCAP NLRI specific information\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_encap_route,
@@ -7246,7 +7829,7 @@ DEFUN (show_bgp_ipv6_encap_route,
"Display ENCAP NLRI specific information\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_safi_rd_route,
@@ -7275,7 +7858,7 @@ DEFUN (show_bgp_ipv4_safi_rd_route,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 0);
+ return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_safi_rd_route,
@@ -7304,7 +7887,7 @@ DEFUN (show_bgp_ipv6_safi_rd_route,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[2], AFI_IP6, SAFI_ENCAP, &prd, 0);
+ return bgp_show_route (vty, NULL, argv[2], AFI_IP6, SAFI_ENCAP, &prd, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_prefix,
@@ -7315,7 +7898,7 @@ DEFUN (show_bgp_ipv4_prefix,
IP_STR
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_safi_prefix,
@@ -7329,9 +7912,9 @@ DEFUN (show_bgp_ipv4_safi_prefix,
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_vpn_prefix,
@@ -7343,7 +7926,7 @@ DEFUN (show_bgp_ipv4_vpn_prefix,
"Display VPN NLRI specific information\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_vpn_prefix,
@@ -7355,7 +7938,7 @@ DEFUN (show_bgp_ipv6_vpn_prefix,
"Display VPN NLRI specific information\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MPLS_VPN, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_encap_prefix,
@@ -7368,7 +7951,7 @@ DEFUN (show_bgp_ipv4_encap_prefix,
"Display information about ENCAP NLRIs\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_ENCAP, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_encap_prefix,
@@ -7381,7 +7964,7 @@ DEFUN (show_bgp_ipv6_encap_prefix,
"Display information about ENCAP NLRIs\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_ENCAP, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv4_safi_rd_prefix,
@@ -7411,7 +7994,7 @@ DEFUN (show_bgp_ipv4_safi_rd_prefix,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 1);
+ return bgp_show_route (vty, NULL, argv[2], AFI_IP, safi, &prd, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_safi_rd_prefix,
@@ -7441,7 +8024,7 @@ DEFUN (show_bgp_ipv6_safi_rd_prefix,
vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, NULL, argv[2], AFI_IP6, safi, &prd, 1);
+ return bgp_show_route (vty, NULL, argv[2], AFI_IP6, safi, &prd, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_afi_safi_view,
@@ -7509,7 +8092,7 @@ DEFUN (show_bgp_view_afi_safi_route,
vty_out (vty, "Error: Bad SAFI: %s%s", argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 0);
+ return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_view_afi_safi_prefix,
@@ -7538,7 +8121,7 @@ DEFUN (show_bgp_view_afi_safi_prefix,
vty_out (vty, "Error: Bad SAFI: %s%s", argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
- return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 1);
+ return bgp_show_route (vty, argv[0], argv[3], afi, safi, NULL, 1, BGP_PATH_ALL);
}
/* new001 */
@@ -7584,7 +8167,7 @@ DEFUN (show_bgp_ipv6_route,
"Address family\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_safi_route,
@@ -7598,9 +8181,9 @@ DEFUN (show_bgp_ipv6_safi_route,
"Network in the BGP routing table to display\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
/* old command */
@@ -7612,7 +8195,7 @@ DEFUN (show_ipv6_bgp_route,
BGP_STR
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_prefix,
@@ -7622,7 +8205,7 @@ DEFUN (show_bgp_prefix,
BGP_STR
"IPv6 prefix <network>/<length>\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
@@ -7635,7 +8218,7 @@ DEFUN (show_bgp_ipv6_prefix,
"Address family\n"
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_ipv6_safi_prefix,
show_bgp_ipv6_safi_prefix_cmd,
@@ -7648,9 +8231,9 @@ DEFUN (show_bgp_ipv6_safi_prefix,
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
/* old command */
@@ -7662,7 +8245,7 @@ DEFUN (show_ipv6_bgp_prefix,
BGP_STR
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_view,
@@ -7717,7 +8300,7 @@ DEFUN (show_bgp_view_route,
"View name\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_view_ipv6_route,
@@ -7730,7 +8313,7 @@ DEFUN (show_bgp_view_ipv6_route,
"Address family\n"
"Network in the BGP routing table to display\n")
{
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
/* old command */
@@ -7754,7 +8337,7 @@ DEFUN (show_ipv6_mbgp_route,
MBGP_STR
"Network in the MBGP routing table to display\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0, BGP_PATH_ALL);
}
/* old command */
@@ -7766,7 +8349,7 @@ DEFUN (show_ipv6_mbgp_prefix,
MBGP_STR
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
{
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1);
+ return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_view_prefix,
@@ -7778,7 +8361,7 @@ DEFUN (show_bgp_view_prefix,
"View name\n"
"IPv6 prefix <network>/<length>\n")
{
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_view_ipv6_prefix,
@@ -7791,7 +8374,7 @@ DEFUN (show_bgp_view_ipv6_prefix,
"Address family\n"
"IPv6 prefix <network>/<length>\n")
{
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
+ return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
static int
@@ -11548,8 +12131,13 @@ peer_lookup_in_view (struct vty *vty, const char *view_name,
ret = str2sockunion (ip_str, &su);
if (ret < 0)
{
- vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE);
- return NULL;
+ peer = peer_lookup_by_conf_if (bgp, ip_str);
+ if (!peer)
+ {
+ vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
+ return NULL;
+ }
+ return peer;
}
/* Peer structure lookup. */
@@ -11998,8 +12586,7 @@ bgp_peer_count_walker (struct thread *t)
{
pc->count[PCOUNT_COUNTED]++;
if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
- plog_warn (peer->log,
- "%s [pcount] %s/%d is counted but flags 0x%x",
+ zlog_warn ("%s [pcount] %s/%d is counted but flags 0x%x",
peer->host,
inet_ntop(rn->p.family, &rn->p.u.prefix,
buf, SU_ADDRSTRLEN),
@@ -12009,8 +12596,7 @@ bgp_peer_count_walker (struct thread *t)
else
{
if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
- plog_warn (peer->log,
- "%s [pcount] %s/%d not counted but flags 0x%x",
+ zlog_warn ("%s [pcount] %s/%d not counted but flags 0x%x",
peer->host,
inet_ntop(rn->p.family, &rn->p.u.prefix,
buf, SU_ADDRSTRLEN),
@@ -12068,13 +12654,14 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi)
DEFUN (show_ip_bgp_neighbor_prefix_counts,
show_ip_bgp_neighbor_prefix_counts_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12088,13 +12675,14 @@ DEFUN (show_ip_bgp_neighbor_prefix_counts,
DEFUN (show_bgp_ipv6_neighbor_prefix_counts,
show_bgp_ipv6_neighbor_prefix_counts_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12108,7 +12696,7 @@ DEFUN (show_bgp_ipv6_neighbor_prefix_counts,
DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts,
show_ip_bgp_ipv4_neighbor_prefix_counts_cmd,
- "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
IP_STR
BGP_STR
@@ -12118,6 +12706,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12134,7 +12723,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts,
DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd,
- "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
IP_STR
BGP_STR
@@ -12144,6 +12733,7 @@ DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12157,7 +12747,7 @@ DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
DEFUN (show_bgp_ipv4_safi_neighbor_prefix_counts,
show_bgp_ipv4_safi_neighbor_prefix_counts_cmd,
- "show bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
BGP_STR
"Address family\n"
@@ -12168,6 +12758,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_prefix_counts,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12187,7 +12778,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_prefix_counts,
DEFUN (show_bgp_ipv6_safi_neighbor_prefix_counts,
show_bgp_ipv6_safi_neighbor_prefix_counts_cmd,
- "show bgp ipv6 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show bgp ipv6 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
BGP_STR
"Address family\n"
@@ -12198,6 +12789,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_prefix_counts,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12217,7 +12809,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_prefix_counts,
DEFUN (show_ip_bgp_encap_neighbor_prefix_counts,
show_ip_bgp_encap_neighbor_prefix_counts_cmd,
- "show ip bgp encap all neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ "show ip bgp encap all neighbors (A.B.C.D|X:X::X:X|WORD) prefix-counts",
SHOW_STR
IP_STR
BGP_STR
@@ -12227,6 +12819,7 @@ DEFUN (show_ip_bgp_encap_neighbor_prefix_counts,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display detailed prefix count information\n")
{
struct peer *peer;
@@ -12238,19 +12831,22 @@ DEFUN (show_ip_bgp_encap_neighbor_prefix_counts,
return bgp_peer_counts (vty, peer, AFI_IP, SAFI_ENCAP);
}
-
static void
show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
- int in)
+ int in, const char *rmap_name)
{
struct bgp_table *table;
struct bgp_adj_in *ain;
struct bgp_adj_out *adj;
unsigned long output_count;
+ unsigned long filtered_count;
struct bgp_node *rn;
int header1 = 1;
struct bgp *bgp;
int header2 = 1;
+ struct attr attr;
+ struct attr_extra extra;
+ int ret;
bgp = peer->bgp;
@@ -12259,8 +12855,8 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
table = bgp->rib[afi][safi];
- output_count = 0;
-
+ output_count = filtered_count = 0;
+
if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_DEFAULT_ORIGINATE))
{
@@ -12273,6 +12869,7 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
header1 = 0;
}
+ attr.extra = &extra;
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
if (in)
{
@@ -12292,9 +12889,16 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
header2 = 0;
}
if (ain->attr)
- {
- route_vty_out_tmp (vty, &rn->p, ain->attr, safi);
- output_count++;
+ {
+ bgp_attr_dup(&attr, ain->attr);
+ if (bgp_input_modifier(peer, &rn->p, &attr, afi,
+ safi, rmap_name) != RMAP_DENY)
+ {
+ route_vty_out_tmp (vty, &rn->p, &attr, safi);
+ output_count++;
+ }
+ else
+ filtered_count++;
}
}
}
@@ -12316,9 +12920,26 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
header2 = 0;
}
if (adj->attr)
- {
- route_vty_out_tmp (vty, &rn->p, adj->attr, safi);
- output_count++;
+ {
+ if (!CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_REFLECTOR_CLIENT)
+ || bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY))
+ {
+
+ bgp_attr_dup(&attr, adj->attr);
+ ret = bgp_output_modifier(peer, &rn->p, &attr, afi,
+ safi, rmap_name);
+ }
+ else
+ ret = RMAP_PERMIT;
+
+ if (ret != RMAP_DENY)
+ {
+ route_vty_out_tmp (vty, &rn->p, &attr, safi);
+ output_count++;
+ }
+ else
+ filtered_count++;
}
}
}
@@ -12329,7 +12950,8 @@ show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
}
static int
-peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, int in)
+peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
+ int in, const char *rmap_name)
{
if (! peer || ! peer->afc[afi][safi])
{
@@ -12344,14 +12966,36 @@ peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, int
return CMD_WARNING;
}
- show_adj_route (vty, peer, afi, safi, in);
+ if (!in && (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)
+ && !bgp_flag_check(peer->bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)))
+ {
+ vty_out (vty, "%% Cannot apply outgoing route-map on route-reflector clients%s",
+ VTY_NEWLINE);
+ vty_out (vty, "%% Enable bgp route-reflector allow-outbound-policy flag%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ show_adj_route (vty, peer, afi, safi, in, rmap_name);
return CMD_SUCCESS;
}
+static int
+peer_adj_routes_decode (struct vty *vty, const char *view, const char *ip_str, afi_t afi, safi_t safi, int in, const char *rmap)
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, view, ip_str);
+ if (!peer)
+ return CMD_WARNING;
+
+ return peer_adj_routes (vty, peer, afi, safi, in, rmap);
+}
+
DEFUN (show_ip_bgp_view_neighbor_advertised_route,
show_ip_bgp_view_neighbor_advertised_route_cmd,
- "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
IP_STR
BGP_STR
@@ -12362,33 +13006,63 @@ DEFUN (show_ip_bgp_view_neighbor_advertised_route,
"Neighbor to display information about\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
-
- if (argc == 2)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, NULL);
+}
- if (! peer)
- return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 0);
+DEFUN (show_ip_bgp_view_neighbor_advertised_route_rmap,
+ show_ip_bgp_view_neighbor_advertised_route_rmap_cmd,
+ "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, argv[2]);
}
-ALIAS (show_ip_bgp_view_neighbor_advertised_route,
+DEFUN (show_ip_bgp_neighbor_advertised_route,
show_ip_bgp_neighbor_advertised_route_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL);
+}
-DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route,
- show_ip_bgp_ipv4_neighbor_advertised_route_cmd,
- "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+DEFUN (show_ip_bgp_neighbor_advertised_route_rmap,
+ show_ip_bgp_neighbor_advertised_route_rmap_cmd,
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]);
+}
+
+DEFUN (show_ip_bgp_ipv4_safi_neighbor_advertised_route,
+ show_ip_bgp_ipv4_safi_neighbor_advertised_route_cmd,
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
IP_STR
BGP_STR
@@ -12398,23 +13072,45 @@ DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
+ safi_t safi = SAFI_UNICAST;
- peer = peer_lookup_in_view (vty, NULL, argv[1]);
- if (! peer)
- return CMD_WARNING;
+ if (strncmp (argv[0], "m", 1) == 0)
+ safi = SAFI_MULTICAST;
+
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, NULL);
+}
+
+DEFUN (show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap,
+ show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd,
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ safi_t safi = SAFI_UNICAST;
if (strncmp (argv[0], "m", 1) == 0)
- return peer_adj_routes (vty, peer, AFI_IP, SAFI_MULTICAST, 0);
+ safi = SAFI_MULTICAST;
- return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 0);
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, argv[2]);
}
DEFUN (show_bgp_view_neighbor_advertised_route,
show_bgp_view_neighbor_advertised_route_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -12422,24 +13118,15 @@ DEFUN (show_bgp_view_neighbor_advertised_route,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
-
- if (argc == 2)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
-
- if (! peer)
- return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 0);
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, NULL);
}
-DEFUN (show_bgp_view_neighbor_received_routes,
- show_bgp_view_neighbor_received_routes_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) received-routes",
+DEFUN (show_bgp_view_neighbor_advertised_route_rmap,
+ show_bgp_view_neighbor_advertised_route_rmap_cmd,
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -12447,78 +13134,174 @@ DEFUN (show_bgp_view_neighbor_received_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
- "Display the received routes from neighbor\n")
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
{
- struct peer *peer;
-
- if (argc == 2)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
-
- if (! peer)
- return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 1);
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 0, argv[2]);
}
-ALIAS (show_bgp_view_neighbor_advertised_route,
+DEFUN (show_bgp_neighbor_advertised_route,
show_bgp_neighbor_advertised_route_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
-
-ALIAS (show_bgp_view_neighbor_advertised_route,
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL);
+}
+
+DEFUN (show_bgp_neighbor_advertised_route_rmap,
+ show_bgp_neighbor_advertised_route_rmap_cmd,
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]);
+}
+
+DEFUN (show_bgp_ipv6_neighbor_advertised_route,
show_bgp_ipv6_neighbor_advertised_route_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 0, NULL);
+}
-/* old command */
-ALIAS (show_bgp_view_neighbor_advertised_route,
- ipv6_bgp_neighbor_advertised_route_cmd,
- "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+/*old command */
+ALIAS (show_bgp_ipv6_neighbor_advertised_route,
+ show_ipv6_bgp_neighbor_advertised_route_cmd,
+ "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
IPV6_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
+
+DEFUN (show_bgp_ipv6_neighbor_advertised_route_rmap,
+ show_bgp_ipv6_neighbor_advertised_route_rmap_cmd,
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 0, argv[1]);
+}
+
+/* old command */
+ALIAS (show_bgp_ipv6_neighbor_advertised_route_rmap,
+ show_ipv6_bgp_neighbor_advertised_route_rmap_cmd,
+ "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ IPV6_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
/* old command */
DEFUN (ipv6_mbgp_neighbor_advertised_route,
ipv6_mbgp_neighbor_advertised_route_cmd,
- "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
IPV6_STR
MBGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 0, NULL);
+}
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
- if (! peer)
- return CMD_WARNING;
+DEFUN (ipv6_mbgp_neighbor_advertised_route_rmap,
+ ipv6_mbgp_neighbor_advertised_route_rmap_cmd,
+ "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ IPV6_STR
+ MBGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, 0, argv[1]);
+}
- return peer_adj_routes (vty, peer, AFI_IP6, SAFI_MULTICAST, 0);
+DEFUN (show_bgp_view_neighbor_received_routes,
+ show_bgp_view_neighbor_received_routes_cmd,
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, NULL);
+}
+
+DEFUN (show_bgp_view_neighbor_received_routes_rmap,
+ show_bgp_view_neighbor_received_routes_rmap_cmd,
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, argv[2]);
}
DEFUN (show_ip_bgp_view_neighbor_received_routes,
show_ip_bgp_view_neighbor_received_routes_cmd,
- "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X) received-routes",
+ "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
IP_STR
BGP_STR
@@ -12527,51 +13310,189 @@ DEFUN (show_ip_bgp_view_neighbor_received_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
{
- struct peer *peer;
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, NULL);
+}
- if (argc == 2)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
+DEFUN (show_ip_bgp_view_neighbor_received_routes_rmap,
+ show_ip_bgp_view_neighbor_received_routes_rmap_cmd,
+ "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, 1, argv[2]);
+}
- if (! peer)
- return CMD_WARNING;
+DEFUN (show_bgp_view_ipv6_neighbor_received_routes,
+ show_bgp_view_ipv6_neighbor_received_routes_cmd,
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 1, NULL);
+}
- return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
+DEFUN (show_bgp_view_ipv6_neighbor_received_routes_rmap,
+ show_bgp_view_ipv6_neighbor_received_routes_rmap_cmd,
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 1, argv[2]);
}
-ALIAS (show_ip_bgp_view_neighbor_received_routes,
+DEFUN (show_ip_bgp_neighbor_received_routes,
show_ip_bgp_neighbor_received_routes_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL);
+}
+
+DEFUN (show_ip_bgp_neighbor_received_routes_rmap,
+ show_ip_bgp_neighbor_received_routes_rmap_cmd,
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 1, argv[1]);
+}
-ALIAS (show_bgp_view_neighbor_received_routes,
+DEFUN (show_bgp_ipv6_neighbor_received_routes,
show_bgp_ipv6_neighbor_received_routes_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received-routes",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 1, NULL);
+}
+
+DEFUN (show_bgp_ipv6_neighbor_received_routes_rmap,
+ show_bgp_ipv6_neighbor_received_routes_rmap_cmd,
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 1, argv[1]);
+}
+
+/* old command */
+DEFUN (show_ipv6_bgp_neighbor_received_routes,
+ show_ipv6_bgp_neighbor_received_routes_cmd,
+ "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
+ SHOW_STR
+ IPV6_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, 1, NULL);
+}
+
+/* old command */
+DEFUN (ipv6_mbgp_neighbor_received_routes,
+ ipv6_mbgp_neighbor_received_routes_cmd,
+ "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
+ SHOW_STR
+ IPV6_STR
+ MBGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, 1, NULL);
+}
+
+DEFUN (ipv6_mbgp_neighbor_received_routes_rmap,
+ ipv6_mbgp_neighbor_received_routes_rmap_cmd,
+ "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ IPV6_STR
+ MBGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, 1, argv[1]);
+}
DEFUN (show_bgp_neighbor_received_prefix_filter,
show_bgp_neighbor_received_prefix_filter_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display information received from a BGP neighbor\n"
"Display the prefixlist filter\n")
{
@@ -12602,42 +13523,11 @@ DEFUN (show_bgp_neighbor_received_prefix_filter,
return CMD_SUCCESS;
}
-/* old command */
-ALIAS (show_bgp_view_neighbor_received_routes,
- ipv6_bgp_neighbor_received_routes_cmd,
- "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Detailed information on TCP and BGP neighbor connections\n"
- "Neighbor to display information about\n"
- "Neighbor to display information about\n"
- "Display the received routes from neighbor\n")
-/* old command */
-DEFUN (ipv6_mbgp_neighbor_received_routes,
- ipv6_mbgp_neighbor_received_routes_cmd,
- "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) received-routes",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Detailed information on TCP and BGP neighbor connections\n"
- "Neighbor to display information about\n"
- "Neighbor to display information about\n"
- "Display the received routes from neighbor\n")
-{
- struct peer *peer;
-
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
- if (! peer)
- return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP6, SAFI_MULTICAST, 1);
-}
DEFUN (show_bgp_view_neighbor_received_prefix_filter,
show_bgp_view_neighbor_received_prefix_filter_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -12684,10 +13574,9 @@ DEFUN (show_bgp_view_neighbor_received_prefix_filter,
return CMD_SUCCESS;
}
-
-DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
- show_ip_bgp_ipv4_neighbor_received_routes_cmd,
- "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received-routes",
+DEFUN (show_ip_bgp_ipv4_safi_neighbor_received_routes,
+ show_ip_bgp_ipv4_safi_neighbor_received_routes_cmd,
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
IP_STR
BGP_STR
@@ -12697,23 +13586,49 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
{
- struct peer *peer;
+ safi_t safi;
- peer = peer_lookup_in_view (vty, NULL, argv[1]);
- if (! peer)
+ if (bgp_parse_safi(argv[0], &safi)) {
+ vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
-
- if (strncmp (argv[0], "m", 1) == 0)
- return peer_adj_routes (vty, peer, AFI_IP, SAFI_MULTICAST, 1);
+ }
+
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, NULL);
+}
+
+DEFUN (show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap,
+ show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd,
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Display routes matching the route-map\n"
+ "A route-map to match on\n")
+{
+ safi_t safi;
- return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
+ if (bgp_parse_safi(argv[0], &safi)) {
+ vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, argv[1]);
}
DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route,
show_bgp_ipv4_safi_neighbor_advertised_route_cmd,
- "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"Address Family modifier\n"
@@ -12721,9 +13636,9 @@ DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
safi_t safi;
if (bgp_parse_safi(argv[0], &safi)) {
@@ -12731,16 +13646,37 @@ DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route,
return CMD_WARNING;
}
- peer = peer_lookup_in_view (vty, NULL, argv[1]);
- if (! peer)
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, NULL);
+}
+
+DEFUN (show_bgp_ipv4_safi_neighbor_advertised_route_rmap,
+ show_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd,
+ "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ safi_t safi;
+
+ if (bgp_parse_safi(argv[0], &safi)) {
+ vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
+ }
- return peer_adj_routes (vty, peer, AFI_IP, safi, 0);
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 0, argv[2]);
}
DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route,
show_bgp_ipv6_safi_neighbor_advertised_route_cmd,
- "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"Address Family modifier\n"
@@ -12749,9 +13685,9 @@ DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
safi_t safi;
if (bgp_parse_safi(argv[0], &safi)) {
@@ -12759,16 +13695,38 @@ DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route,
return CMD_WARNING;
}
- peer = peer_lookup_in_view (vty, NULL, argv[1]);
- if (! peer)
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 0, NULL);
+}
+
+DEFUN (show_bgp_ipv6_safi_neighbor_advertised_route_rmap,
+ show_bgp_ipv6_safi_neighbor_advertised_route_rmap_cmd,
+ "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ safi_t safi;
+
+ if (bgp_parse_safi(argv[0], &safi)) {
+ vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
+ }
- return peer_adj_routes (vty, peer, AFI_IP6, safi, 0);
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 0, argv[2]);
}
DEFUN (show_bgp_view_ipv6_neighbor_advertised_route,
show_bgp_view_ipv6_neighbor_advertised_route_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -12777,24 +13735,15 @@ DEFUN (show_bgp_view_ipv6_neighbor_advertised_route,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the routes advertised to a BGP neighbor\n")
{
- struct peer *peer;
-
- if (argc == 2)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
-
- if (! peer)
- return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 0);
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 0, NULL);
}
-DEFUN (show_bgp_view_ipv6_neighbor_received_routes,
- show_bgp_view_ipv6_neighbor_received_routes_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) received-routes",
+DEFUN (show_bgp_view_ipv6_neighbor_advertised_route_rmap,
+ show_bgp_view_ipv6_neighbor_advertised_route_rmap_cmd,
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) advertised-routes route-map WORD",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -12803,24 +13752,17 @@ DEFUN (show_bgp_view_ipv6_neighbor_received_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
- "Display the received routes from neighbor\n")
+ "Neighbor on bgp configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
{
- struct peer *peer;
-
- if (argc == 2)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
-
- if (! peer)
- return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP6, SAFI_UNICAST, 1);
+ return peer_adj_routes_decode (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, 0, argv[2]);
}
DEFUN (show_bgp_ipv4_safi_neighbor_received_routes,
show_bgp_ipv4_safi_neighbor_received_routes_cmd,
- "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received-routes",
+ "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
BGP_STR
"Address family\n"
@@ -12831,9 +13773,9 @@ DEFUN (show_bgp_ipv4_safi_neighbor_received_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
{
- struct peer *peer;
safi_t safi;
if (bgp_parse_safi(argv[0], &safi)) {
@@ -12841,16 +13783,40 @@ DEFUN (show_bgp_ipv4_safi_neighbor_received_routes,
return CMD_WARNING;
}
- peer = peer_lookup_in_view (vty, NULL, argv[1]);
- if (! peer)
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, NULL);
+}
+
+DEFUN (show_bgp_ipv4_safi_neighbor_received_routes_rmap,
+ show_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd,
+ "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ safi_t safi;
+
+ if (bgp_parse_safi(argv[0], &safi)) {
+ vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP, safi, 1);
+ }
+
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP, safi, 1, argv[2]);
}
DEFUN (show_bgp_ipv6_safi_neighbor_received_routes,
show_bgp_ipv6_safi_neighbor_received_routes_cmd,
- "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received-routes",
+ "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
BGP_STR
"Address family\n"
@@ -12861,9 +13827,9 @@ DEFUN (show_bgp_ipv6_safi_neighbor_received_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
{
- struct peer *peer;
safi_t safi;
if (bgp_parse_safi(argv[0], &safi)) {
@@ -12871,16 +13837,40 @@ DEFUN (show_bgp_ipv6_safi_neighbor_received_routes,
return CMD_WARNING;
}
- peer = peer_lookup_in_view (vty, NULL, argv[1]);
- if (! peer)
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 1, NULL);
+}
+
+DEFUN (show_bgp_ipv6_safi_neighbor_received_routes_rmap,
+ show_bgp_ipv6_safi_neighbor_received_routes_rmap_cmd,
+ "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received-routes route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ safi_t safi;
+
+ if (bgp_parse_safi(argv[0], &safi)) {
+ vty_out (vty, "Error: Bad SAFI: %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
-
- return peer_adj_routes (vty, peer, AFI_IP6, safi, 1);
+ }
+
+ return peer_adj_routes_decode (vty, NULL, argv[1], AFI_IP6, safi, 1, argv[2]);
}
DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes,
show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd,
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) (advertised-routes|received-routes)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -12892,35 +13882,63 @@ DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the advertised routes to neighbor\n"
"Display the received routes from neighbor\n")
{
int afi;
int safi;
int in;
- struct peer *peer;
- peer = peer_lookup_in_view (vty, argv[0], argv[3]);
+ afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+ safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0;
+
+ return peer_adj_routes_decode (vty, argv[0], argv[3], afi, safi, in, NULL);
+}
- if (! peer)
- return CMD_WARNING;
+DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes_rmap,
+ show_bgp_view_afi_safi_neighbor_adv_recd_routes_rmap_cmd,
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) (advertised-routes|received-routes) route-map WORD",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "View name\n"
+ "Address family\n"
+ "Address family\n"
+ "Address family modifier\n"
+ "Address family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
+ "Display the advertised routes to neighbor\n"
+ "Display the received routes from neighbor\n"
+ "Route-map to control what is displayed\n"
+ "Route-map name\n")
+{
+ int afi;
+ int safi;
+ int in;
afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0;
- return peer_adj_routes (vty, peer, afi, safi, in);
+ return peer_adj_routes_decode (vty, argv[0], argv[3], afi, safi, in, argv[5]);
}
+
DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
show_ip_bgp_neighbor_received_prefix_filter_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display information received from a BGP neighbor\n"
"Display the prefixlist filter\n")
{
@@ -12932,13 +13950,19 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
ret = str2sockunion (argv[0], &su);
if (ret < 0)
{
- vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
+ peer = peer_lookup_by_conf_if (NULL, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "Malformed address or name: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ peer = peer_lookup (NULL, &su);
+ if (! peer)
+ return CMD_WARNING;
}
-
- peer = peer_lookup (NULL, &su);
- if (! peer)
- return CMD_WARNING;
sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST);
count = prefix_bgp_show_prefix_list (NULL, AFI_IP, name);
@@ -12953,7 +13977,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter,
show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd,
- "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
IP_STR
BGP_STR
@@ -12963,6 +13987,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display information received from a BGP neighbor\n"
"Display the prefixlist filter\n")
{
@@ -12974,13 +13999,19 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter,
ret = str2sockunion (argv[1], &su);
if (ret < 0)
{
- vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE);
- return CMD_WARNING;
+ peer = peer_lookup_by_conf_if (NULL, argv[1]);
+ if (!peer)
+ {
+ vty_out (vty, "Malformed address or name: %s%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ peer = peer_lookup (NULL, &su);
+ if (! peer)
+ return CMD_WARNING;
}
-
- peer = peer_lookup (NULL, &su);
- if (! peer)
- return CMD_WARNING;
if (strncmp (argv[0], "m", 1) == 0)
{
@@ -13006,19 +14037,23 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter,
return CMD_SUCCESS;
}
-ALIAS (show_bgp_view_neighbor_received_routes,
+DEFUN (show_bgp_neighbor_received_routes,
show_bgp_neighbor_received_routes_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) received-routes",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the received routes from neighbor\n")
+{
+ return peer_adj_routes_decode (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL);
+}
DEFUN (show_bgp_ipv4_safi_neighbor_received_prefix_filter,
show_bgp_ipv4_safi_neighbor_received_prefix_filter_cmd,
- "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
BGP_STR
IP_STR
@@ -13066,7 +14101,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_received_prefix_filter,
DEFUN (show_bgp_ipv6_safi_neighbor_received_prefix_filter,
show_bgp_ipv6_safi_neighbor_received_prefix_filter_cmd,
- "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
BGP_STR
IP_STR
@@ -13114,13 +14149,14 @@ DEFUN (show_bgp_ipv6_safi_neighbor_received_prefix_filter,
DEFUN (show_bgp_ipv6_neighbor_received_prefix_filter,
show_bgp_ipv6_neighbor_received_prefix_filter_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display information received from a BGP neighbor\n"
"Display the prefixlist filter\n")
{
@@ -13132,13 +14168,19 @@ DEFUN (show_bgp_ipv6_neighbor_received_prefix_filter,
ret = str2sockunion (argv[0], &su);
if (ret < 0)
{
- vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
+ peer = peer_lookup_by_conf_if (NULL, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "Malformed address or name: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ peer = peer_lookup (NULL, &su);
+ if (! peer)
+ return CMD_WARNING;
}
-
- peer = peer_lookup (NULL, &su);
- if (! peer)
- return CMD_WARNING;
sprintf (name, "%s.%d.%d", peer->host, AFI_IP6, SAFI_UNICAST);
count = prefix_bgp_show_prefix_list (NULL, AFI_IP6, name);
@@ -13153,7 +14195,7 @@ DEFUN (show_bgp_ipv6_neighbor_received_prefix_filter,
DEFUN (show_bgp_view_ipv6_neighbor_received_prefix_filter,
show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) received prefix-filter",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13162,6 +14204,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_received_prefix_filter,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display information received from a BGP neighbor\n"
"Display the prefixlist filter\n")
{
@@ -13182,13 +14225,19 @@ DEFUN (show_bgp_view_ipv6_neighbor_received_prefix_filter,
ret = str2sockunion (argv[1], &su);
if (ret < 0)
{
- vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE);
- return CMD_WARNING;
+ peer = peer_lookup_by_conf_if (bgp, argv[1]);
+ if (!peer)
+ {
+ vty_out (vty, "%% Malformed address or name: %s%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ peer = peer_lookup (bgp, &su);
+ if (! peer)
+ return CMD_WARNING;
}
-
- peer = peer_lookup (bgp, &su);
- if (! peer)
- return CMD_WARNING;
sprintf (name, "%s.%d.%d", peer->host, AFI_IP6, SAFI_UNICAST);
count = prefix_bgp_show_prefix_list (NULL, AFI_IP6, name);
@@ -13215,13 +14264,14 @@ bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi,
}
DEFUN (show_ip_bgp_neighbor_routes,
show_ip_bgp_neighbor_routes_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) routes",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
{
struct peer *peer;
@@ -13234,15 +14284,17 @@ DEFUN (show_ip_bgp_neighbor_routes,
bgp_show_type_neighbor);
}
+
DEFUN (show_ip_bgp_neighbor_flap,
show_ip_bgp_neighbor_flap_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display flap statistics of the routes learned from neighbor\n")
{
struct peer *peer;
@@ -13257,13 +14309,14 @@ DEFUN (show_ip_bgp_neighbor_flap,
DEFUN (show_ip_bgp_neighbor_damp,
show_ip_bgp_neighbor_damp_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the dampened routes received from neighbor\n")
{
struct peer *peer;
@@ -13278,7 +14331,7 @@ DEFUN (show_ip_bgp_neighbor_damp,
DEFUN (show_ip_bgp_ipv4_neighbor_routes,
show_ip_bgp_ipv4_neighbor_routes_cmd,
- "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) routes",
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
IP_STR
BGP_STR
@@ -13288,6 +14341,7 @@ DEFUN (show_ip_bgp_ipv4_neighbor_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
{
struct peer *peer;
@@ -13306,14 +14360,14 @@ DEFUN (show_ip_bgp_ipv4_neighbor_routes,
DEFUN (show_ip_bgp_view_rsclient,
show_ip_bgp_view_rsclient_cmd,
- "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X)",
+ "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
IP_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR)
+ NEIGHBOR_ADDR_STR3)
{
struct bgp_table *table;
struct peer *peer;
@@ -13348,16 +14402,16 @@ DEFUN (show_ip_bgp_view_rsclient,
ALIAS (show_ip_bgp_view_rsclient,
show_ip_bgp_rsclient_cmd,
- "show ip bgp rsclient (A.B.C.D|X:X::X:X)",
+ "show ip bgp rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
IP_STR
BGP_STR
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR)
+ NEIGHBOR_ADDR_STR3)
DEFUN (show_bgp_view_ipv4_safi_rsclient,
show_bgp_view_ipv4_safi_rsclient_cmd,
- "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13366,7 +14420,7 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient,
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR)
+ NEIGHBOR_ADDR_STR3)
{
struct bgp_table *table;
struct peer *peer;
@@ -13405,25 +14459,25 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient,
ALIAS (show_bgp_view_ipv4_safi_rsclient,
show_bgp_ipv4_safi_rsclient_cmd,
- "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR)
+ NEIGHBOR_ADDR_STR3)
DEFUN (show_ip_bgp_view_rsclient_route,
show_ip_bgp_view_rsclient_route_cmd,
- "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+ "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D",
SHOW_STR
IP_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
{
struct bgp *bgp;
@@ -13474,22 +14528,22 @@ DEFUN (show_ip_bgp_view_rsclient_route,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST],
(argc == 3) ? argv[2] : argv[1],
- AFI_IP, SAFI_UNICAST, NULL, 0);
+ AFI_IP, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
ALIAS (show_ip_bgp_view_rsclient_route,
show_ip_bgp_rsclient_route_cmd,
- "show ip bgp rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+ "show ip bgp rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D",
SHOW_STR
IP_STR
BGP_STR
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
DEFUN (show_bgp_ipv4_safi_neighbor_flap,
show_bgp_ipv4_safi_neighbor_flap_cmd,
- "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
@@ -13519,7 +14573,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_flap,
DEFUN (show_bgp_ipv6_safi_neighbor_flap,
show_bgp_ipv6_safi_neighbor_flap_cmd,
- "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
@@ -13549,7 +14603,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_flap,
DEFUN (show_bgp_ipv4_safi_neighbor_damp,
show_bgp_ipv4_safi_neighbor_damp_cmd,
- "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show bgp ipv4 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
@@ -13579,7 +14633,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_damp,
DEFUN (show_bgp_ipv6_safi_neighbor_damp,
show_bgp_ipv6_safi_neighbor_damp_cmd,
- "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show bgp ipv6 (encap|multicast|unicast|vpn) neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
BGP_STR
"Address Family Modifier\n"
@@ -13609,7 +14663,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_damp,
DEFUN (show_bgp_ipv4_safi_neighbor_routes,
show_bgp_ipv4_safi_neighbor_routes_cmd,
- "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) routes",
+ "show bgp ipv4 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
BGP_STR
"Address family\n"
@@ -13638,7 +14692,7 @@ DEFUN (show_bgp_ipv4_safi_neighbor_routes,
DEFUN (show_bgp_ipv6_safi_neighbor_routes,
show_bgp_ipv6_safi_neighbor_routes_cmd,
- "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X) routes",
+ "show bgp ipv6 (multicast|unicast) neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
BGP_STR
"Address family\n"
@@ -13667,7 +14721,7 @@ DEFUN (show_bgp_ipv6_safi_neighbor_routes,
DEFUN (show_bgp_view_ipv4_safi_rsclient_route,
show_bgp_view_ipv4_safi_rsclient_route_cmd,
- "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13676,7 +14730,7 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient_route,
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
{
struct bgp *bgp;
@@ -13731,25 +14785,25 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient_route,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
(argc == 4) ? argv[3] : argv[2],
- AFI_IP, safi, NULL, 0);
+ AFI_IP, safi, NULL, 0, BGP_PATH_ALL);
}
ALIAS (show_bgp_view_ipv4_safi_rsclient_route,
show_bgp_ipv4_safi_rsclient_route_cmd,
- "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+ "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D",
SHOW_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix,
show_bgp_view_ipv4_safi_rsclient_prefix_cmd,
- "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13813,19 +14867,19 @@ DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
(argc == 4) ? argv[3] : argv[2],
- AFI_IP, safi, NULL, 1);
+ AFI_IP, safi, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_ip_bgp_view_rsclient_prefix,
show_ip_bgp_view_rsclient_prefix_cmd,
- "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M",
SHOW_STR
IP_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
struct bgp *bgp;
@@ -13876,34 +14930,34 @@ DEFUN (show_ip_bgp_view_rsclient_prefix,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][SAFI_UNICAST],
(argc == 3) ? argv[2] : argv[1],
- AFI_IP, SAFI_UNICAST, NULL, 1);
+ AFI_IP, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
ALIAS (show_ip_bgp_view_rsclient_prefix,
show_ip_bgp_rsclient_prefix_cmd,
- "show ip bgp rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ "show ip bgp rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M",
SHOW_STR
IP_STR
BGP_STR
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
ALIAS (show_bgp_view_ipv4_safi_rsclient_prefix,
show_bgp_ipv4_safi_rsclient_prefix_cmd,
- "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+ "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) A.B.C.D/M",
SHOW_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
DEFUN (show_bgp_view_ipv6_neighbor_routes,
show_bgp_view_ipv6_neighbor_routes_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) routes",
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13912,6 +14966,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_routes,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
{
struct peer *peer;
@@ -13930,7 +14985,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_routes,
DEFUN (show_bgp_view_neighbor_damp,
show_bgp_view_neighbor_damp_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13938,6 +14993,7 @@ DEFUN (show_bgp_view_neighbor_damp,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the dampened routes received from neighbor\n")
{
struct peer *peer;
@@ -13956,7 +15012,7 @@ DEFUN (show_bgp_view_neighbor_damp,
DEFUN (show_bgp_view_ipv6_neighbor_damp,
show_bgp_view_ipv6_neighbor_damp_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13965,6 +15021,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_damp,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the dampened routes received from neighbor\n")
{
struct peer *peer;
@@ -13983,7 +15040,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_damp,
DEFUN (show_bgp_view_ipv6_neighbor_flap,
show_bgp_view_ipv6_neighbor_flap_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -13992,6 +15049,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_flap,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the dampened routes received from neighbor\n")
{
struct peer *peer;
@@ -14010,7 +15068,7 @@ DEFUN (show_bgp_view_ipv6_neighbor_flap,
DEFUN (show_bgp_view_neighbor_flap,
show_bgp_view_neighbor_flap_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14018,6 +15076,7 @@ DEFUN (show_bgp_view_neighbor_flap,
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display flap statistics of the routes learned from neighbor\n")
{
struct peer *peer;
@@ -14036,7 +15095,7 @@ DEFUN (show_bgp_view_neighbor_flap,
ALIAS (show_bgp_view_neighbor_flap,
show_bgp_neighbor_flap_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
@@ -14046,7 +15105,7 @@ ALIAS (show_bgp_view_neighbor_flap,
ALIAS (show_bgp_view_neighbor_damp,
show_bgp_neighbor_damp_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
@@ -14056,7 +15115,7 @@ ALIAS (show_bgp_view_neighbor_damp,
DEFUN (show_bgp_view_neighbor_routes,
show_bgp_view_neighbor_routes_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X) routes",
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14082,47 +15141,51 @@ DEFUN (show_bgp_view_neighbor_routes,
ALIAS (show_bgp_view_neighbor_routes,
show_bgp_neighbor_routes_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X) routes",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
ALIAS (show_bgp_view_neighbor_routes,
show_bgp_ipv6_neighbor_routes_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) routes",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
/* old command */
ALIAS (show_bgp_view_neighbor_routes,
ipv6_bgp_neighbor_routes_cmd,
- "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) routes",
+ "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
IPV6_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
/* old command */
DEFUN (ipv6_mbgp_neighbor_routes,
ipv6_mbgp_neighbor_routes_cmd,
- "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) routes",
+ "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X|WORD) routes",
SHOW_STR
IPV6_STR
MBGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display routes learned from neighbor\n")
{
struct peer *peer;
@@ -14137,29 +15200,31 @@ DEFUN (ipv6_mbgp_neighbor_routes,
ALIAS (show_bgp_view_neighbor_flap,
show_bgp_ipv6_neighbor_flap_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) flap-statistics",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display flap statistics of the routes learned from neighbor\n")
ALIAS (show_bgp_view_neighbor_damp,
show_bgp_ipv6_neighbor_damp_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD) dampened-routes",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n"
"Display the dampened routes received from neighbor\n")
DEFUN (show_bgp_view_rsclient,
show_bgp_view_rsclient_cmd,
- "show bgp view WORD rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14200,7 +15265,7 @@ DEFUN (show_bgp_view_rsclient,
ALIAS (show_bgp_view_rsclient,
show_bgp_rsclient_cmd,
- "show bgp rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Information about Route Server Client\n"
@@ -14208,7 +15273,7 @@ ALIAS (show_bgp_view_rsclient,
DEFUN (show_bgp_view_ipv4_rsclient,
show_bgp_view_ipv4_rsclient_cmd,
- "show bgp view WORD ipv4 rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD ipv4 rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14249,7 +15314,7 @@ DEFUN (show_bgp_view_ipv4_rsclient,
}
DEFUN (show_bgp_view_ipv6_rsclient,
show_bgp_view_ipv6_rsclient_cmd,
- "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14291,25 +15356,25 @@ DEFUN (show_bgp_view_ipv6_rsclient,
ALIAS (show_bgp_view_ipv4_rsclient,
show_bgp_ipv4_rsclient_cmd,
- "show bgp ipv4 rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp ipv4 rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Address Family\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR2)
+ NEIGHBOR_ADDR_STR3)
ALIAS (show_bgp_view_ipv6_rsclient,
show_bgp_ipv6_rsclient_cmd,
- "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Address Family\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR2)
+ NEIGHBOR_ADDR_STR3)
DEFUN (show_bgp_view_ipv6_safi_rsclient,
show_bgp_view_ipv6_safi_rsclient_cmd,
- "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14318,7 +15383,7 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient,
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR)
+ NEIGHBOR_ADDR_STR3)
{
struct bgp_table *table;
struct peer *peer;
@@ -14357,24 +15422,24 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient,
ALIAS (show_bgp_view_ipv6_safi_rsclient,
show_bgp_ipv6_safi_rsclient_cmd,
- "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+ "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR)
+ NEIGHBOR_ADDR_STR3)
DEFUN (show_bgp_view_rsclient_route,
show_bgp_view_rsclient_route_cmd,
- "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ "show bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X",
SHOW_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
{
struct bgp *bgp;
@@ -14425,12 +15490,12 @@ DEFUN (show_bgp_view_rsclient_route,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST],
(argc == 3) ? argv[2] : argv[1],
- AFI_IP6, SAFI_UNICAST, NULL, 0);
+ AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
DEFUN (show_bgp_view_ipv6_rsclient_route,
show_bgp_view_ipv6_rsclient_route_cmd,
- "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14488,21 +15553,21 @@ DEFUN (show_bgp_view_ipv6_rsclient_route,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST],
(argc == 3) ? argv[2] : argv[1],
- AFI_IP6, SAFI_UNICAST, NULL, 0);
+ AFI_IP6, SAFI_UNICAST, NULL, 0, BGP_PATH_ALL);
}
ALIAS (show_bgp_view_ipv6_rsclient_route,
show_bgp_rsclient_route_cmd,
- "show bgp rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ "show bgp rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X",
SHOW_STR
BGP_STR
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
ALIAS (show_bgp_view_ipv6_rsclient_route,
show_bgp_ipv6_rsclient_route_cmd,
- "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X",
SHOW_STR
BGP_STR
IP6_STR
@@ -14512,7 +15577,7 @@ ALIAS (show_bgp_view_ipv6_rsclient_route,
DEFUN (show_bgp_view_ipv6_safi_rsclient_route,
show_bgp_view_ipv6_safi_rsclient_route_cmd,
- "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14521,7 +15586,7 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_route,
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
{
struct bgp *bgp;
@@ -14576,31 +15641,31 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_route,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
(argc == 4) ? argv[3] : argv[2],
- AFI_IP6, safi, NULL, 0);
+ AFI_IP6, safi, NULL, 0, BGP_PATH_ALL);
}
ALIAS (show_bgp_view_ipv6_safi_rsclient_route,
show_bgp_ipv6_safi_rsclient_route_cmd,
- "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+ "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X",
SHOW_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"Network in the BGP routing table to display\n")
DEFUN (show_bgp_view_rsclient_prefix,
show_bgp_view_rsclient_prefix_cmd,
- "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ "show bgp view WORD rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M",
SHOW_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
{
struct bgp *bgp;
@@ -14651,12 +15716,12 @@ DEFUN (show_bgp_view_rsclient_prefix,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST],
(argc == 3) ? argv[2] : argv[1],
- AFI_IP6, SAFI_UNICAST, NULL, 1);
+ AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
DEFUN (show_bgp_view_ipv6_rsclient_prefix,
show_bgp_view_ipv6_rsclient_prefix_cmd,
- "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ "show bgp view WORD ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14714,21 +15779,21 @@ DEFUN (show_bgp_view_ipv6_rsclient_prefix,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][SAFI_UNICAST],
(argc == 3) ? argv[2] : argv[1],
- AFI_IP6, SAFI_UNICAST, NULL, 1);
+ AFI_IP6, SAFI_UNICAST, NULL, 1, BGP_PATH_ALL);
}
ALIAS (show_bgp_view_ipv6_rsclient_prefix,
show_bgp_rsclient_prefix_cmd,
- "show bgp rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ "show bgp rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M",
SHOW_STR
BGP_STR
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
ALIAS (show_bgp_view_ipv6_rsclient_prefix,
show_bgp_ipv6_rsclient_prefix_cmd,
- "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ "show bgp ipv6 rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M",
SHOW_STR
BGP_STR
"Information about Route Server Client\n"
@@ -14737,7 +15802,7 @@ ALIAS (show_bgp_view_ipv6_rsclient_prefix,
DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix,
show_bgp_view_ipv6_safi_rsclient_prefix_cmd,
- "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -14746,7 +15811,7 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix,
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IP prefix <network>/<length>, e.g., 3ffe::/16\n")
{
struct bgp *bgp;
@@ -14801,19 +15866,19 @@ DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix,
return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
(argc == 4) ? argv[3] : argv[2],
- AFI_IP6, safi, NULL, 1);
+ AFI_IP6, safi, NULL, 1, BGP_PATH_ALL);
}
ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix,
show_bgp_ipv6_safi_rsclient_prefix_cmd,
- "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+ "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X|WORD) X:X::X:X/M",
SHOW_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Client\n"
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR3
"IP prefix <network>/<length>, e.g., 3ffe::/16\n")
struct bgp_table *bgp_distance_table;
@@ -15697,6 +16762,7 @@ bgp_route_init (void)
bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST);
/* IPv4 BGP commands. */
+ install_element (BGP_NODE, &bgp_table_map_cmd);
install_element (BGP_NODE, &bgp_network_cmd);
install_element (BGP_NODE, &bgp_network_mask_cmd);
install_element (BGP_NODE, &bgp_network_mask_natural_cmd);
@@ -15706,6 +16772,7 @@ bgp_route_init (void)
install_element (BGP_NODE, &bgp_network_backdoor_cmd);
install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd);
install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
+ install_element (BGP_NODE, &no_bgp_table_map_cmd);
install_element (BGP_NODE, &no_bgp_network_cmd);
install_element (BGP_NODE, &no_bgp_network_mask_cmd);
install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd);
@@ -15867,9 +16934,13 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_longer_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_longer_cmd);
install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
install_element (VIEW_NODE, &show_bgp_ipv4_safi_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_safi_neighbor_routes_cmd);
@@ -16026,9 +17097,13 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_advertised_route_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv4_safi_neighbor_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_safi_neighbor_routes_cmd);
@@ -16096,8 +17171,10 @@ bgp_route_init (void)
/* New config IPv6 BGP commands. */
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
+ install_element (BGP_IPV6_NODE, &bgp_table_map_cmd);
install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_route_map_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd);
install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_summary_only_cmd);
@@ -16136,6 +17213,8 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_community_list_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_prefix_longer_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_advertised_route_rmap_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd);
@@ -16152,7 +17231,9 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_view_ipv6_route_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_prefix_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_flap_cmd);
@@ -16213,7 +17294,9 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_ipv6_safi_community_list_exact_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_advertised_route_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_flap_cmd);
@@ -16229,7 +17312,9 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_view_ipv6_route_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_advertised_route_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_flap_cmd);
@@ -16264,6 +17349,7 @@ bgp_route_init (void)
install_element (BGP_IPV4_NODE, &bgp_damp_set3_cmd);
install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd);
+ install_element (BGP_IPV4_NODE, &bgp_table_map_cmd);
/* Deprecated AS-Pathlimit commands */
install_element (BGP_NODE, &bgp_network_ttl_cmd);
@@ -16293,13 +17379,15 @@ bgp_route_init (void)
install_element (BGP_IPV4_NODE, &no_bgp_network_backdoor_ttl_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_network_mask_backdoor_ttl_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd);
-
+ install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd);
+
install_element (BGP_IPV4M_NODE, &bgp_network_ttl_cmd);
install_element (BGP_IPV4M_NODE, &bgp_network_mask_ttl_cmd);
install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_ttl_cmd);
install_element (BGP_IPV4M_NODE, &bgp_network_backdoor_ttl_cmd);
install_element (BGP_IPV4M_NODE, &bgp_network_mask_backdoor_ttl_cmd);
install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd);
+ install_element (BGP_IPV4M_NODE, &bgp_table_map_cmd);
install_element (BGP_IPV4M_NODE, &no_bgp_network_ttl_cmd);
install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_ttl_cmd);
@@ -16307,6 +17395,7 @@ bgp_route_init (void)
install_element (BGP_IPV4M_NODE, &no_bgp_network_backdoor_ttl_cmd);
install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_backdoor_ttl_cmd);
install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd);
+ install_element (BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_ttl_cmd);
install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_ttl_cmd);
@@ -16315,11 +17404,16 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_ip_bgp_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_route_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_route_pathtype_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_pathtype_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_prefix_pathtype_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_cmd);
@@ -16359,10 +17453,14 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_list_exact_cmd);
install_element (VIEW_NODE, &show_ip_bgp_prefix_longer_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_advertised_route_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_neighbor_advertised_route_rmap_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
- install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
@@ -16392,15 +17490,22 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_route_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_route_pathtype_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_prefix_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_pathtype_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
install_element (RESTRICTED_NODE, &show_ip_bgp_view_route_cmd);
@@ -16428,11 +17533,16 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_ip_bgp_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_route_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_route_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_route_pathtype_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_prefix_pathtype_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_cmd);
@@ -16473,10 +17583,13 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_ip_bgp_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_advertised_route_cmd);
- install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_neighbor_advertised_route_rmap_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_advertised_route_rmap_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_safi_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
- install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
- install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
@@ -16506,17 +17619,26 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_rmap_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_rmap_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_prefix_counts_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_prefix_counts_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd);
+
install_element (VIEW_NODE, &show_bgp_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_cmd);
install_element (VIEW_NODE, &show_bgp_route_cmd);
install_element (VIEW_NODE, &show_bgp_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_route_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_route_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_route_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_prefix_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_prefix_pathtype_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_pathtype_cmd);
install_element (VIEW_NODE, &show_bgp_regexp_cmd);
install_element (VIEW_NODE, &show_bgp_prefix_list_cmd);
install_element (VIEW_NODE, &show_bgp_filter_list_cmd);
@@ -16536,6 +17658,7 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_ipv6_safi_community_list_exact_cmd);
install_element (VIEW_NODE, &show_bgp_prefix_longer_cmd);
install_element (VIEW_NODE, &show_bgp_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_neighbor_received_routes_cmd);
install_element (VIEW_NODE, &show_bgp_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_bgp_neighbor_received_prefix_filter_cmd);
@@ -16546,7 +17669,9 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_view_route_cmd);
install_element (VIEW_NODE, &show_bgp_view_prefix_cmd);
install_element (VIEW_NODE, &show_bgp_view_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_view_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &show_bgp_view_neighbor_routes_cmd);
install_element (VIEW_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd);
install_element (VIEW_NODE, &show_bgp_view_neighbor_flap_cmd);
@@ -16554,6 +17679,12 @@ bgp_route_init (void)
install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd);
install_element (RESTRICTED_NODE, &show_bgp_route_cmd);
install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_route_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_prefix_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_pathtype_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_pathtype_cmd);
install_element (RESTRICTED_NODE, &show_bgp_community_cmd);
install_element (RESTRICTED_NODE, &show_bgp_community2_cmd);
install_element (RESTRICTED_NODE, &show_bgp_community3_cmd);
@@ -16569,6 +17700,12 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_ipv6_cmd);
install_element (ENABLE_NODE, &show_bgp_route_cmd);
install_element (ENABLE_NODE, &show_bgp_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_route_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_route_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_route_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_prefix_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_pathtype_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_pathtype_cmd);
install_element (ENABLE_NODE, &show_bgp_regexp_cmd);
install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd);
install_element (ENABLE_NODE, &show_bgp_filter_list_cmd);
@@ -16587,6 +17724,7 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_community_list_exact_cmd);
install_element (ENABLE_NODE, &show_bgp_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_bgp_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_neighbor_advertised_route_rmap_cmd);
install_element (ENABLE_NODE, &show_bgp_neighbor_received_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_neighbor_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_neighbor_received_prefix_filter_cmd);
@@ -16597,6 +17735,8 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_bgp_view_route_cmd);
install_element (ENABLE_NODE, &show_bgp_view_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_view_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_neighbor_advertised_route_rmap_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_neighbor_received_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_view_neighbor_received_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_view_neighbor_routes_cmd);
install_element (ENABLE_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd);
@@ -16677,14 +17817,20 @@ bgp_route_init (void)
install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_cmd);
install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_exact_cmd);
install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_longer_cmd);
- install_element (VIEW_NODE, &ipv6_bgp_neighbor_advertised_route_cmd);
- install_element (ENABLE_NODE, &ipv6_bgp_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_ipv6_bgp_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_bgp_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_ipv6_bgp_neighbor_advertised_route_rmap_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_bgp_neighbor_advertised_route_rmap_cmd);
install_element (VIEW_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd);
install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd);
- install_element (VIEW_NODE, &ipv6_bgp_neighbor_received_routes_cmd);
- install_element (ENABLE_NODE, &ipv6_bgp_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &ipv6_mbgp_neighbor_advertised_route_rmap_cmd);
+ install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_advertised_route_rmap_cmd);
+ install_element (VIEW_NODE, &show_ipv6_bgp_neighbor_received_routes_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_bgp_neighbor_received_routes_cmd);
install_element (VIEW_NODE, &ipv6_mbgp_neighbor_received_routes_cmd);
install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_received_routes_cmd);
+ install_element (VIEW_NODE, &ipv6_mbgp_neighbor_received_routes_rmap_cmd);
+ install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_received_routes_rmap_cmd);
install_element (VIEW_NODE, &ipv6_bgp_neighbor_routes_cmd);
install_element (ENABLE_NODE, &ipv6_bgp_neighbor_routes_cmd);
install_element (VIEW_NODE, &ipv6_mbgp_neighbor_routes_cmd);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index c8037592..b54a7941 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -21,8 +21,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#ifndef _QUAGGA_BGP_ROUTE_H
#define _QUAGGA_BGP_ROUTE_H
+#include "queue.h"
#include "bgp_table.h"
+struct bgp_nexthop_cache;
+
/* Ancillary information to struct bgp_info,
* used for uncommonly used data (aggregation, MPLS, etc.)
* and lazily allocated to save memory.
@@ -47,7 +50,16 @@ struct bgp_info
/* For linked list. */
struct bgp_info *next;
struct bgp_info *prev;
-
+
+ /* For nexthop linked list */
+ LIST_ENTRY(bgp_info) nh_thread;
+
+ /* Back pointer to the prefix node */
+ struct bgp_node *net;
+
+ /* Back pointer to the nexthop structure */
+ struct bgp_nexthop_cache *nexthop;
+
/* Peer structure. */
struct peer *peer;
@@ -127,6 +139,10 @@ struct bgp_static
u_char tag[3];
};
+#define BGP_INFO_COUNTABLE(BI) \
+ (! CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \
+ && ! CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED))
+
/* Flags which indicate a route is unuseable in some form */
#define BGP_INFO_UNUSEABLE \
(BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED)
@@ -172,7 +188,15 @@ enum bgp_clear_route_type
BGP_CLEAR_ROUTE_MY_RSCLIENT
};
+enum bgp_path_type
+{
+ BGP_PATH_ALL,
+ BGP_PATH_BESTPATH,
+ BGP_PATH_MULTIPATH
+};
+
/* Prototypes. */
+extern void bgp_process_queue_init (void);
extern void bgp_route_init (void);
extern void bgp_route_finish (void);
extern void bgp_cleanup_routes (void);
@@ -201,8 +225,8 @@ extern int bgp_nlri_parse_ip (struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add (struct prefix *, const struct in_addr *,
- const struct in6_addr *,
- u_int32_t, u_char);
+ const struct in6_addr *, unsigned int ifindex,
+ u_int32_t, u_char, u_short);
extern void bgp_redistribute_delete (struct prefix *, u_char);
extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int);
@@ -226,6 +250,14 @@ extern int bgp_withdraw (struct peer *, struct prefix *, struct attr *,
/* for bgp_nexthop and bgp_damp */
extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
+
+/*
+ * Add an end-of-initial-update marker to the process queue. This is just a
+ * queue element with NULL bgp node.
+ */
+extern void bgp_add_eoiu_mark (struct bgp *, bgp_table_t);
+extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t,
+ int *);
extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *);
extern int bgp_config_write_distance (struct vty *, struct bgp *);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 39fa08c8..18ecc6c8 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -39,12 +39,15 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#endif /* HAVE_LIBPCREPOSIX */
#include "buffer.h"
#include "sockunion.h"
+#include "hash.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_regex.h"
#include "bgpd/bgp_community.h"
#include "bgpd/bgp_clist.h"
@@ -52,6 +55,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_debug.h"
+
/* Memo of route-map commands.
@@ -59,7 +64,7 @@ o Cisco route-map
match as-path : Done
community : Done
- interface : Not yet
+ interface : Done
ip address : Done
ip next-hop : Done
ip route-source : Done
@@ -71,7 +76,8 @@ o Cisco route-map
length : (This will not be implemented by bgpd)
metric : Done
route-type : (This will not be implemented by bgpd)
- tag : (This will not be implemented by bgpd)
+ tag : Done
+ local-preference : Done
set as-path prepend : Done
as-path tag : Not yet
@@ -90,7 +96,7 @@ o Cisco route-map
metric : Done
metric-type : Not yet
origin : Done
- tag : (This will not be implemented by bgpd)
+ tag : Done
weight : Done
o Local extensions
@@ -613,6 +619,72 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd =
route_match_ip_route_source_prefix_list_free
};
+/* `match local-preference LOCAL-PREF' */
+
+/* Match function return 1 if match is success else return zero. */
+static route_map_result_t
+route_match_local_pref (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_int32_t *local_pref;
+ struct bgp_info *bgp_info;
+
+ if (type == RMAP_BGP)
+ {
+ local_pref = rule;
+ bgp_info = object;
+
+ if (bgp_info->attr->local_pref == *local_pref)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Route map `match local-preference' match statement.
+ `arg' is local-pref value */
+static void *
+route_match_local_pref_compile (const char *arg)
+{
+ u_int32_t *local_pref;
+ char *endptr = NULL;
+ unsigned long tmpval;
+
+ /* Locpref value shoud be integer. */
+ if (! all_digit (arg))
+ return NULL;
+
+ errno = 0;
+ tmpval = strtoul (arg, &endptr, 10);
+ if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
+ return NULL;
+
+ local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+
+ if (!local_pref)
+ return local_pref;
+
+ *local_pref = tmpval;
+ return local_pref;
+}
+
+/* Free route map's compiled `match local-preference' value. */
+static void
+route_match_local_pref_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for metric matching. */
+struct route_map_rule_cmd route_match_local_pref_cmd =
+{
+ "local-preference",
+ route_match_local_pref,
+ route_match_local_pref_compile,
+ route_match_local_pref_free
+};
+
/* `match metric METRIC' */
/* Match function return 1 if match is success else return zero. */
@@ -657,9 +729,9 @@ route_match_aspath (void *rule, struct prefix *prefix,
as_list = as_list_lookup ((char *) rule);
if (as_list == NULL)
return RMAP_NOMATCH;
-
+
bgp_info = object;
-
+
/* Perform match. */
return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH);
}
@@ -933,10 +1005,127 @@ struct route_map_rule_cmd route_match_probability_cmd =
route_match_probability_free
};
+/* `match interface IFNAME' */
+/* Match function should return 1 if match is success else return
+ zero. */
+static route_map_result_t
+route_match_interface (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct interface *ifp;
+ struct bgp_info *info;
+
+ if (type == RMAP_BGP)
+ {
+ info = object;
+
+ if (!info || !info->attr)
+ return RMAP_NOMATCH;
+
+ ifp = if_lookup_by_name ((char *)rule);
+
+ if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex)
+ return RMAP_NOMATCH;
+
+ return RMAP_MATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Route map `interface' match statement. `arg' should be
+ interface name. */
+static void *
+route_match_interface_compile (const char *arg)
+{
+ return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `interface' value. */
+static void
+route_match_interface_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_interface_cmd =
+{
+ "interface",
+ route_match_interface,
+ route_match_interface_compile,
+ route_match_interface_free
+};
+
/* } */
/* `set ip next-hop IP_ADDRESS' */
+/* Match function return 1 if match is success else return zero. */
+static route_map_result_t
+route_match_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct bgp_info *bgp_info;
+
+ if (type == RMAP_BGP)
+ {
+ tag = rule;
+ bgp_info = object;
+
+ if (!bgp_info->attr->extra)
+ return RMAP_NOMATCH;
+
+ return ((bgp_info->attr->extra->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
+ }
+
+ return RMAP_NOMATCH;
+}
+
+
+/* Route map `match tag' match statement. `arg' is TAG value */
+static void *
+route_match_tag_compile (const char *arg)
+{
+ u_short *tag;
+ u_short tmp;
+
+ /* tag value shoud be integer. */
+ if (! all_digit (arg))
+ return NULL;
+
+ tmp = atoi(arg);
+ if (tmp < 1)
+ return NULL;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+
+ if (!tag)
+ return tag;
+
+ *tag = tmp;
+
+ return tag;
+}
+
+
+/* Free route map's compiled 'match tag' value. */
+static void
+route_match_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for tag matching. */
+struct route_map_rule_cmd route_match_tag_cmd =
+{
+ "tag",
+ route_match_tag,
+ route_match_tag_compile,
+ route_match_tag_free,
+};
+
+
/* Set nexthop to object. ojbect must be pointer to struct attr. */
struct rmap_ip_nexthop_set
{
@@ -1710,6 +1899,73 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd =
route_set_aggregator_as_free,
};
+/* Set tag to object. object must be pointer to struct bgp_info */
+static route_map_result_t
+route_set_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct bgp_info *bgp_info;
+ struct attr_extra *ae;
+
+ if (type == RMAP_BGP)
+ {
+ tag = rule;
+ bgp_info = object;
+ ae = bgp_attr_extra_get (bgp_info->attr);
+
+ /* Set tag value */
+ ae->tag=*tag;
+
+ }
+
+ return RMAP_OKAY;
+}
+
+/* Route map `tag' compile function. Given string is converted to u_short. */
+static void *
+route_set_tag_compile (const char *arg)
+{
+ u_short *tag;
+ u_short tmp;
+
+ /* tag value shoud be integer. */
+ if (! all_digit (arg))
+ return NULL;
+
+ tmp = atoi(arg);
+
+ if (tmp < 1)
+ return NULL;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+
+ if (!tag)
+ return tag;
+
+ *tag = tmp;
+
+ return tag;
+}
+
+/* Free route map's tag value. */
+static void
+route_set_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+
+/* Route map commands for tag set. */
+struct route_map_rule_cmd route_set_tag_cmd =
+{
+ "tag",
+ route_set_tag,
+ route_set_tag_compile,
+ route_set_tag_free,
+};
+
+
/* `match ipv6 address IP_ACCESS_LIST' */
static route_map_result_t
@@ -2187,7 +2443,8 @@ struct route_map_rule_cmd route_set_originator_id_cmd =
/* Add bgp route map rule. */
static int
bgp_route_match_add (struct vty *vty, struct route_map_index *index,
- const char *command, const char *arg)
+ const char *command, const char *arg,
+ route_map_event_t type)
{
int ret;
@@ -2197,36 +2454,71 @@ bgp_route_match_add (struct vty *vty, struct route_map_index *index,
switch (ret)
{
case RMAP_RULE_MISSING:
- vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+ vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
return CMD_WARNING;
case RMAP_COMPILE_ERROR:
- vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+ vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
return CMD_WARNING;
}
}
+
+ if (type != RMAP_EVENT_MATCH_ADDED)
+ {
+ route_map_upd8_dependency (type, arg, index->map->name);
+ }
+
return CMD_SUCCESS;
}
/* Delete bgp route map rule. */
static int
bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
- const char *command, const char *arg)
+ const char *command, const char *arg,
+ route_map_event_t type)
{
int ret;
+ char *dep_name = (char *)arg;
+ const char *tmpstr;
+ char *rmap_name = NULL;
+
+ if (type != RMAP_EVENT_MATCH_DELETED)
+ {
+ /* ignore the mundane, the types without any dependency */
+ if (arg == NULL)
+ {
+ if ((tmpstr = route_map_get_match_arg(index, command)) != NULL)
+ dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
+ }
+ rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
+ }
- ret = route_map_delete_match (index, command, arg);
+ ret = route_map_delete_match (index, command, dep_name);
if (ret)
{
switch (ret)
{
case RMAP_RULE_MISSING:
- vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
- return CMD_WARNING;
+ vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
+ break;
case RMAP_COMPILE_ERROR:
- vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
- return CMD_WARNING;
+ vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
+ break;
}
+ if (arg == NULL && dep_name)
+ XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+ if (rmap_name)
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+ return CMD_WARNING;
}
+
+ if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
+ route_map_upd8_dependency(type, dep_name, rmap_name);
+
+ if (arg == NULL && dep_name)
+ XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+ if (rmap_name)
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+
return CMD_SUCCESS;
}
@@ -2243,10 +2535,10 @@ bgp_route_set_add (struct vty *vty, struct route_map_index *index,
switch (ret)
{
case RMAP_RULE_MISSING:
- vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+ vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
return CMD_WARNING;
case RMAP_COMPILE_ERROR:
- vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+ vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
return CMD_WARNING;
}
}
@@ -2266,134 +2558,363 @@ bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
switch (ret)
{
case RMAP_RULE_MISSING:
- vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+ vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
return CMD_WARNING;
case RMAP_COMPILE_ERROR:
- vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+ vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
return CMD_WARNING;
}
}
return CMD_SUCCESS;
}
-/* Hook function for updating route_map assignment. */
+/*
+ * This is the workhorse routine for processing in/out/import/export routemap
+ * modifications.
+ */
static void
-bgp_route_map_update (const char *unused)
+bgp_route_map_process_peer (const char *rmap_name, struct peer *peer,
+ int afi, int safi, int route_update)
{
- int i;
- afi_t afi;
- safi_t safi;
- int direct;
- struct listnode *node, *nnode;
- struct listnode *mnode, *mnnode;
- struct bgp *bgp;
- struct peer *peer;
- struct peer_group *group;
+
+ int update;
struct bgp_filter *filter;
- struct bgp_node *bn;
- struct bgp_static *bgp_static;
if (bm->bgp == NULL) /* may be called during cleanup */
return;
- /* For neighbor route-map updates. */
- for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
+ if (!peer || !rmap_name)
+ return;
+
+ filter = &peer->filter[afi][safi];
+ /*
+ * in is for non-route-server clients,
+ * import/export is for route-server clients,
+ * out is for all peers
+ */
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT))
{
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if (filter->map[RMAP_IN].name &&
+ (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0))
{
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- {
- filter = &peer->filter[afi][safi];
-
- for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
- {
- if (filter->map[direct].name)
- filter->map[direct].map =
- route_map_lookup_by_name (filter->map[direct].name);
- else
- filter->map[direct].map = NULL;
- }
-
- if (filter->usmap.name)
- filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
- else
- filter->usmap.map = NULL;
- }
+ filter->map[RMAP_IN].map =
+ route_map_lookup_by_name (filter->map[RMAP_IN].name);
+
+ if (route_update && peer->status == Established)
+ {
+ if (CHECK_FLAG (peer->af_flags[afi][safi],
+ PEER_FLAG_SOFT_RECONFIG))
+ {
+ if (bgp_debug_update(peer, NULL, 1))
+ zlog_debug("Processing route_map %s update on "
+ "peer %s (inbound, soft-reconfig)",
+ rmap_name, peer->host);
+
+ bgp_soft_reconfig_in (peer, afi, safi);
+ }
+ else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
+ || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+ {
+
+ if (bgp_debug_update(peer, NULL, 1))
+ zlog_debug("Processing route_map %s update on "
+ "peer %s (inbound, route-refresh)",
+ rmap_name, peer->host);
+ bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+ }
+ }
+ }
+ }
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT))
+ {
+ update = 0;
+
+ if (filter->map[RMAP_IMPORT].name &&
+ (strcmp(rmap_name, filter->map[RMAP_IMPORT].name) == 0))
+ {
+ filter->map[RMAP_IMPORT].map =
+ route_map_lookup_by_name (filter->map[RMAP_IMPORT].name);
+ update = 1;
}
- for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+
+ if (filter->map[RMAP_EXPORT].name &&
+ (strcmp(rmap_name, filter->map[RMAP_EXPORT].name) == 0))
{
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- {
- filter = &group->conf->filter[afi][safi];
-
- for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
- {
- if (filter->map[direct].name)
- filter->map[direct].map =
- route_map_lookup_by_name (filter->map[direct].name);
- else
- filter->map[direct].map = NULL;
- }
-
- if (filter->usmap.name)
- filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
- else
- filter->usmap.map = NULL;
- }
+ filter->map[RMAP_EXPORT].map =
+ route_map_lookup_by_name (filter->map[RMAP_EXPORT].name);
+
+ update = 1;
+ }
+
+ if (update && route_update && peer->status == Established)
+ {
+ if (CHECK_FLAG (peer->af_flags[afi][safi],
+ PEER_FLAG_SOFT_RECONFIG))
+ {
+ if (bgp_debug_update(peer, NULL, 1))
+ zlog_debug("Processing route_map %s update on "
+ "peer %s (import, soft-reconfig)",
+ rmap_name, peer->host);
+
+ bgp_soft_reconfig_in (peer, afi, safi);
+ }
+ else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
+ || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+ {
+ if (bgp_debug_update(peer, NULL, 1))
+ zlog_debug("Processing route_map %s update on "
+ "peer %s (import, route-refresh)",
+ rmap_name, peer->host);
+ bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+ }
+ /* DD: Else, what else do we do ? Reset peer ? */
}
}
- /* For default-originate route-map updates. */
- for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
- {
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if (filter->map[RMAP_OUT].name &&
+ (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
{
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- {
- if (peer->default_rmap[afi][safi].name)
- peer->default_rmap[afi][safi].map =
- route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
- else
- peer->default_rmap[afi][safi].map = NULL;
- }
+ filter->map[RMAP_OUT].map =
+ route_map_lookup_by_name (filter->map[RMAP_OUT].name);
+
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("Processing route_map %s update on peer %s (outbound)",
+ rmap_name, peer->host);
+
+ if (route_update)
+ bgp_announce_route_all(peer);
}
+
+ if (filter->usmap.name &&
+ (strcmp(rmap_name, filter->usmap.name) == 0))
+ {
+ filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
+ if (route_update)
+ bgp_announce_route_all(peer);
}
+}
- /* For network route-map updates. */
- for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
+static void
+bgp_route_map_update_peer_group(const char *rmap_name, struct bgp *bgp)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+ struct bgp_filter *filter;
+ int afi, safi;
+ int direct;
+
+ if (!bgp)
+ return;
+
+ /* All the peers have been updated correctly already. This is
+ * just updating the placeholder data. No real update required.
+ */
+ for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ filter = &group->conf->filter[afi][safi];
+
+ for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
+ {
+ if ((filter->map[direct].name) &&
+ (strcmp(rmap_name, filter->map[direct].name) == 0))
+ filter->map[direct].map =
+ route_map_lookup_by_name (filter->map[direct].name);
+ }
+
+ if (filter->usmap.name &&
+ (strcmp(rmap_name, filter->usmap.name) == 0))
+ filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
+ }
+}
+
+static int
+bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update)
+{
+ int i;
+ afi_t afi;
+ safi_t safi;
+ struct peer *peer;
+ struct bgp_node *bn;
+ struct bgp_static *bgp_static;
+ struct bgp *bgp = (struct bgp *)arg;
+ struct listnode *node, *nnode;
+ char buf[INET6_ADDRSTRLEN];
+
+ if (!bgp)
+ return -1;
+
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
+
+ /* Ignore dummy peer-group structure */
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ continue;
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
- bn = bgp_route_next (bn))
- if ((bgp_static = bn->info) != NULL)
+ {
+ /* Ignore inactive AFI/SAFI */
+ if (! peer->afc[afi][safi])
+ continue;
+
+ /* process in/out/import/export route-maps */
+ bgp_route_map_process_peer(rmap_name, peer, afi, safi, route_update);
+
+ /* process default-originate route-map */
+ if (peer->default_rmap[afi][safi].name &&
+ (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0))
{
- if (bgp_static->rmap.name)
- bgp_static->rmap.map =
- route_map_lookup_by_name (bgp_static->rmap.name);
- else
- bgp_static->rmap.map = NULL;
+ peer->default_rmap[afi][safi].map =
+ route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
+
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("Processing route_map %s update on "
+ "default-originate", rmap_name);
+
+ if (route_update)
+ bgp_default_originate (peer, afi, safi, 0);
}
+ }
}
+ bgp_route_map_update_peer_group(rmap_name, bgp);
+
+ /* For table route-map updates. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ if (bgp->table_map[afi][safi].name &&
+ (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0))
+ {
+ bgp->table_map[afi][safi].map =
+ route_map_lookup_by_name (bgp->table_map[afi][safi].name);
+ if (BGP_DEBUG (zebra, ZEBRA))
+ zlog_debug("Processing route_map %s update on "
+ "table map", rmap_name);
+ if (route_update)
+ bgp_zebra_announce_table(bgp, afi, safi);
+ }
+ }
+
+ /* For network route-map updates. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
+ bn = bgp_route_next (bn))
+ if ((bgp_static = bn->info) != NULL)
+ {
+ if (bgp_static->rmap.name &&
+ (strcmp(rmap_name, bgp_static->rmap.name) == 0))
+ {
+ bgp_static->rmap.map =
+ route_map_lookup_by_name (bgp_static->rmap.name);
+ if (route_update)
+ if (!bgp_static->backdoor)
+ {
+ if (bgp_debug_zebra(&bn->p))
+ zlog_debug("Processing route_map %s update on "
+ "static route %s", rmap_name,
+ inet_ntop (bn->p.family, &bn->p.u.prefix,
+ buf, INET6_ADDRSTRLEN));
+ bgp_static_update (bgp, &bn->p, bgp_static, afi, safi);
+ }
+ }
+ }
+
/* For redistribute route-map updates. */
- for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ {
+ if (bgp->rmap[afi][i].name &&
+ (strcmp(rmap_name, bgp->rmap[afi][i].name) == 0))
+ {
+ bgp->rmap[afi][i].map =
+ route_map_lookup_by_name (bgp->rmap[afi][i].name);
+
+ if (bgp->redist[afi][i] && route_update)
+ {
+ if (BGP_DEBUG (zebra, ZEBRA))
+ zlog_debug("Processing route_map %s update on "
+ "redistributed routes", rmap_name);
+
+ bgp_redistribute_resend (bgp, afi, i);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+bgp_route_map_process_update_cb (void *arg, char *rmap_name)
+{
+ return bgp_route_map_process_update (arg, rmap_name, 1);
+}
+
+int
+bgp_route_map_update_timer(struct thread *thread)
+{
+ struct bgp *bgp = THREAD_ARG(thread);
+
+ bgp->t_rmap_update = NULL;
+
+ route_map_walk_update_list((void *)bgp, bgp_route_map_process_update_cb);
+
+ return (0);
+}
+
+static void
+bgp_route_map_mark_update (const char *rmap_name)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
{
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (bgp->t_rmap_update == NULL)
{
- if (bgp->rmap[AFI_IP][i].name)
- bgp->rmap[AFI_IP][i].map =
- route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name);
- if (bgp->rmap[AFI_IP6][i].name)
- bgp->rmap[AFI_IP6][i].map =
- route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name);
+ /* rmap_update_timer of 0 means don't do route updates */
+ if (bgp->rmap_update_timer)
+ bgp->t_rmap_update =
+ thread_add_timer(bm->master, bgp_route_map_update_timer, bgp,
+ bgp->rmap_update_timer);
+ else
+ bgp_route_map_process_update((void *)bgp, rmap_name, 0);
}
}
}
+static void
+bgp_route_map_add (const char *rmap_name)
+{
+ if (route_map_mark_updated(rmap_name, 0) == 0)
+ bgp_route_map_mark_update(rmap_name);
+
+ route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
+}
+
+static void
+bgp_route_map_delete (const char *rmap_name)
+{
+ if (route_map_mark_updated(rmap_name, 1) == 0)
+ bgp_route_map_mark_update(rmap_name);
+
+ route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
+}
+
+static void
+bgp_route_map_event (route_map_event_t event, const char *rmap_name)
+{
+ if (route_map_mark_updated(rmap_name, 0) == 0)
+ bgp_route_map_mark_update(rmap_name);
+
+ route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
+}
+
+
DEFUN (match_peer,
match_peer_cmd,
"match peer (A.B.C.D|X:X::X:X)",
@@ -2402,7 +2923,8 @@ DEFUN (match_peer,
"IPv6 address of peer\n"
"IP address of peer\n")
{
- return bgp_route_match_add (vty, vty->index, "peer", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "peer", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
}
DEFUN (match_peer_local,
@@ -2412,7 +2934,8 @@ DEFUN (match_peer_local,
"Match peer address\n"
"Static or Redistributed routes\n")
{
- return bgp_route_match_add (vty, vty->index, "peer", "local");
+ return bgp_route_match_add (vty, vty->index, "peer", "local",
+ RMAP_EVENT_MATCH_DELETED);
}
DEFUN (no_match_peer,
@@ -2423,9 +2946,11 @@ DEFUN (no_match_peer,
"Match peer address\n")
{
if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "peer", NULL);
+ return bgp_route_match_delete (vty, vty->index, "peer", NULL,
+ RMAP_EVENT_MATCH_DELETED);
- return bgp_route_match_delete (vty, vty->index, "peer", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "peer", argv[0],
+ RMAP_EVENT_MATCH_DELETED);
}
ALIAS (no_match_peer,
@@ -2455,7 +2980,8 @@ DEFUN (match_ip_address,
"IP access-list number (expanded range)\n"
"IP Access-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ip address", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ip address", argv[0],
+ RMAP_EVENT_FILTER_ADDED);
}
DEFUN (no_match_ip_address,
@@ -2467,9 +2993,11 @@ DEFUN (no_match_ip_address,
"Match address of route\n")
{
if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "ip address", NULL);
+ return bgp_route_match_delete (vty, vty->index, "ip address", NULL,
+ RMAP_EVENT_FILTER_DELETED);
- return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ip address", argv[0],
+ RMAP_EVENT_FILTER_DELETED);
}
ALIAS (no_match_ip_address,
@@ -2493,7 +3021,8 @@ DEFUN (match_ip_next_hop,
"IP access-list number (expanded range)\n"
"IP Access-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0],
+ RMAP_EVENT_FILTER_ADDED);
}
DEFUN (no_match_ip_next_hop,
@@ -2505,9 +3034,11 @@ DEFUN (no_match_ip_next_hop,
"Match next-hop address of route\n")
{
if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL);
+ return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL,
+ RMAP_EVENT_FILTER_DELETED);
- return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0],
+ RMAP_EVENT_FILTER_DELETED);
}
ALIAS (no_match_ip_next_hop,
@@ -2530,7 +3061,8 @@ DEFUN (match_probability,
"Match portion of routes defined by percentage value\n"
"Percentage of routes\n")
{
- return bgp_route_match_add (vty, vty->index, "probability", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "probability", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_probability,
@@ -2540,7 +3072,8 @@ DEFUN (no_match_probability,
MATCH_STR
"Match portion of routes defined by percentage value\n")
{
- return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL);
+ return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL,
+ RMAP_EVENT_MATCH_DELETED);
}
ALIAS (no_match_probability,
@@ -2563,7 +3096,8 @@ DEFUN (match_ip_route_source,
"IP access-list number (expanded range)\n"
"IP standard access-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0],
+ RMAP_EVENT_FILTER_ADDED);
}
DEFUN (no_match_ip_route_source,
@@ -2575,9 +3109,11 @@ DEFUN (no_match_ip_route_source,
"Match advertising source address of route\n")
{
if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL);
+ return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL,
+ RMAP_EVENT_FILTER_DELETED);
- return bgp_route_match_delete (vty, vty->index, "ip route-source", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ip route-source",
+ argv[0], RMAP_EVENT_FILTER_DELETED);
}
ALIAS (no_match_ip_route_source,
@@ -2600,7 +3136,8 @@ DEFUN (match_ip_address_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ip address prefix-list",
+ argv[0], RMAP_EVENT_PLIST_ADDED);
}
DEFUN (no_match_ip_address_prefix_list,
@@ -2612,10 +3149,9 @@ DEFUN (no_match_ip_address_prefix_list,
"Match address of route\n"
"Match entries of prefix-lists\n")
{
- if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
-
- return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ip address prefix-list",
+ argc == 0 ? NULL : argv[0],
+ RMAP_EVENT_PLIST_DELETED);
}
ALIAS (no_match_ip_address_prefix_list,
@@ -2637,7 +3173,8 @@ DEFUN (match_ip_next_hop_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list",
+ argv[0], RMAP_EVENT_PLIST_ADDED);
}
DEFUN (no_match_ip_next_hop_prefix_list,
@@ -2649,10 +3186,9 @@ DEFUN (no_match_ip_next_hop_prefix_list,
"Match next-hop address of route\n"
"Match entries of prefix-lists\n")
{
- if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
-
- return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
+ argc == 0 ? NULL : argv[0],
+ RMAP_EVENT_PLIST_DELETED);
}
ALIAS (no_match_ip_next_hop_prefix_list,
@@ -2674,7 +3210,8 @@ DEFUN (match_ip_route_source_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list",
+ argv[0], RMAP_EVENT_PLIST_ADDED);
}
DEFUN (no_match_ip_route_source_prefix_list,
@@ -2686,10 +3223,9 @@ DEFUN (no_match_ip_route_source_prefix_list,
"Match advertising source address of route\n"
"Match entries of prefix-lists\n")
{
- if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", NULL);
-
- return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
+ argc == 0 ? NULL : argv[0],
+ RMAP_EVENT_PLIST_DELETED);
}
ALIAS (no_match_ip_route_source_prefix_list,
@@ -2709,7 +3245,8 @@ DEFUN (match_metric,
"Match metric of route\n"
"Metric value\n")
{
- return bgp_route_match_add (vty, vty->index, "metric", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "metric", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_metric,
@@ -2719,10 +3256,9 @@ DEFUN (no_match_metric,
MATCH_STR
"Match metric of route\n")
{
- if (argc == 0)
- return bgp_route_match_delete (vty, vty->index, "metric", NULL);
-
- return bgp_route_match_delete (vty, vty->index, "metric", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "metric",
+ argc == 0 ? NULL : argv[0],
+ RMAP_EVENT_MATCH_DELETED);
}
ALIAS (no_match_metric,
@@ -2733,6 +3269,40 @@ ALIAS (no_match_metric,
"Match metric of route\n"
"Metric value\n")
+DEFUN (match_local_pref,
+ match_local_pref_cmd,
+ "match local-preference <0-4294967295>",
+ MATCH_STR
+ "Match local-preference of route\n"
+ "Metric value\n")
+{
+ return bgp_route_match_add (vty, vty->index, "local-preference", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_local_pref,
+ no_match_local_pref_cmd,
+ "no match local-preference",
+ NO_STR
+ MATCH_STR
+ "Match local preference of route\n")
+{
+ return bgp_route_match_delete (vty, vty->index, "local-preference",
+ argc == 0 ? NULL : argv[0],
+ RMAP_EVENT_MATCH_DELETED);
+
+ return bgp_route_match_delete (vty, vty->index, "local-preference", argv[0],
+ RMAP_EVENT_MATCH_DELETED);
+}
+
+ALIAS (no_match_local_pref,
+ no_match_local_pref_val_cmd,
+ "no match local-preference <0-4294967295>",
+ NO_STR
+ MATCH_STR
+ "Match local preference of route\n"
+ "Local preference value\n")
+
DEFUN (match_community,
match_community_cmd,
"match community (<1-99>|<100-500>|WORD)",
@@ -2742,7 +3312,8 @@ DEFUN (match_community,
"Community-list number (expanded)\n"
"Community-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "community", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "community", argv[0],
+ RMAP_EVENT_CLIST_ADDED);
}
DEFUN (match_community_exact,
@@ -2763,7 +3334,8 @@ DEFUN (match_community_exact,
sprintf (argstr, "%s exact-match", argv[0]);
- ret = bgp_route_match_add (vty, vty->index, "community", argstr);
+ ret = bgp_route_match_add (vty, vty->index, "community", argstr,
+ RMAP_EVENT_CLIST_ADDED);
XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
@@ -2777,7 +3349,8 @@ DEFUN (no_match_community,
MATCH_STR
"Match BGP community list\n")
{
- return bgp_route_match_delete (vty, vty->index, "community", NULL);
+ return bgp_route_match_delete (vty, vty->index, "community", NULL,
+ RMAP_EVENT_CLIST_DELETED);
}
ALIAS (no_match_community,
@@ -2810,7 +3383,8 @@ DEFUN (match_ecommunity,
"Extended community-list number (expanded)\n"
"Extended community-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0],
+ RMAP_EVENT_ECLIST_ADDED);
}
DEFUN (no_match_ecommunity,
@@ -2820,7 +3394,8 @@ DEFUN (no_match_ecommunity,
MATCH_STR
"Match BGP/VPN extended community list\n")
{
- return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL);
+ return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL,
+ RMAP_EVENT_ECLIST_DELETED);
}
ALIAS (no_match_ecommunity,
@@ -2840,7 +3415,8 @@ DEFUN (match_aspath,
"Match BGP AS path list\n"
"AS path access-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "as-path", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "as-path", argv[0],
+ RMAP_EVENT_ASLIST_ADDED);
}
DEFUN (no_match_aspath,
@@ -2850,7 +3426,8 @@ DEFUN (no_match_aspath,
MATCH_STR
"Match BGP AS path list\n")
{
- return bgp_route_match_delete (vty, vty->index, "as-path", NULL);
+ return bgp_route_match_delete (vty, vty->index, "as-path", NULL,
+ RMAP_EVENT_ASLIST_DELETED);
}
ALIAS (no_match_aspath,
@@ -2871,11 +3448,14 @@ DEFUN (match_origin,
"unknown heritage\n")
{
if (strncmp (argv[0], "igp", 2) == 0)
- return bgp_route_match_add (vty, vty->index, "origin", "igp");
+ return bgp_route_match_add (vty, vty->index, "origin", "igp",
+ RMAP_EVENT_MATCH_ADDED);
if (strncmp (argv[0], "egp", 1) == 0)
- return bgp_route_match_add (vty, vty->index, "origin", "egp");
+ return bgp_route_match_add (vty, vty->index, "origin", "egp",
+ RMAP_EVENT_MATCH_ADDED);
if (strncmp (argv[0], "incomplete", 2) == 0)
- return bgp_route_match_add (vty, vty->index, "origin", "incomplete");
+ return bgp_route_match_add (vty, vty->index, "origin", "incomplete",
+ RMAP_EVENT_MATCH_ADDED);
return CMD_WARNING;
}
@@ -2887,7 +3467,8 @@ DEFUN (no_match_origin,
MATCH_STR
"BGP origin code\n")
{
- return bgp_route_match_delete (vty, vty->index, "origin", NULL);
+ return bgp_route_match_delete (vty, vty->index, "origin", NULL,
+ RMAP_EVENT_MATCH_DELETED);
}
ALIAS (no_match_origin,
@@ -2900,6 +3481,75 @@ ALIAS (no_match_origin,
"local IGP\n"
"unknown heritage\n")
+DEFUN (match_interface,
+ match_interface_cmd,
+ "match interface WORD",
+ MATCH_STR
+ "Match first hop interface of route\n"
+ "Interface name\n")
+{
+ return bgp_route_match_add (vty, vty->index, "interface", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_interface,
+ no_match_interface_cmd,
+ "no match interface",
+ NO_STR
+ MATCH_STR
+ "Match first hop interface of route\n")
+{
+ if (argc == 0)
+ return bgp_route_match_delete (vty, vty->index, "interface", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+
+ return bgp_route_match_delete (vty, vty->index, "interface", argv[0],
+ RMAP_EVENT_MATCH_DELETED);
+}
+
+ALIAS (no_match_interface,
+ no_match_interface_val_cmd,
+ "no match interface WORD",
+ NO_STR
+ MATCH_STR
+ "Match first hop interface of route\n"
+ "Interface name\n")
+
+DEFUN (match_tag,
+ match_tag_cmd,
+ "match tag <1-65535>",
+ MATCH_STR
+ "Match tag of route\n"
+ "Tag value\n")
+{
+ return bgp_route_match_add (vty, vty->index, "tag", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_tag,
+ no_match_tag_cmd,
+ "no match tag",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n")
+{
+ if (argc == 0)
+ return bgp_route_match_delete (vty, vty->index, "tag", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+
+ return bgp_route_match_delete (vty, vty->index, "tag", argv[0],
+ RMAP_EVENT_MATCH_DELETED);
+}
+
+ALIAS (no_match_tag,
+ no_match_tag_val_cmd,
+ "no match tag <1-65535>",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n"
+ "Tag value\n")
+
+
DEFUN (set_ip_nexthop,
set_ip_nexthop_cmd,
"set ip next-hop A.B.C.D",
@@ -3313,7 +3963,7 @@ DEFUN (set_community_delete,
SET_STR
"set BGP community list (for deletion)\n"
"Community-list number (standard)\n"
- "Communitly-list number (expanded)\n"
+ "Community-list number (expanded)\n"
"Community-list name\n"
"Delete matching communities\n")
{
@@ -3346,7 +3996,7 @@ ALIAS (no_set_community_delete,
SET_STR
"set BGP community list (for deletion)\n"
"Community-list number (standard)\n"
- "Communitly-list number (expanded)\n"
+ "Community-list number (expanded)\n"
"Community-list name\n"
"Delete matching communities\n")
@@ -3565,6 +4215,38 @@ ALIAS (no_set_aggregator_as,
"AS number\n"
"IP address of aggregator\n")
+DEFUN (set_tag,
+ set_tag_cmd,
+ "set tag <1-65535>",
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+{
+ return bgp_route_set_add (vty, vty->index, "tag", argv[0]);
+}
+
+DEFUN (no_set_tag,
+ no_set_tag_cmd,
+ "no set tag",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n")
+{
+ if (argc == 0)
+ bgp_route_set_delete(vty, vty->index, "tag", NULL);
+
+ return bgp_route_set_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_set_tag,
+ no_set_tag_val_cmd,
+ "no set tag <1-65535>",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+
+
DEFUN (match_ipv6_address,
match_ipv6_address_cmd,
"match ipv6 address WORD",
@@ -3573,7 +4255,8 @@ DEFUN (match_ipv6_address,
"Match IPv6 address of route\n"
"IPv6 access-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0],
+ RMAP_EVENT_FILTER_ADDED);
}
DEFUN (no_match_ipv6_address,
@@ -3585,7 +4268,8 @@ DEFUN (no_match_ipv6_address,
"Match IPv6 address of route\n"
"IPv6 access-list name\n")
{
- return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0],
+ RMAP_EVENT_FILTER_DELETED);
}
DEFUN (match_ipv6_next_hop,
@@ -3596,7 +4280,8 @@ DEFUN (match_ipv6_next_hop,
"Match IPv6 next-hop address of route\n"
"IPv6 address of next hop\n")
{
- return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0],
+ RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_ipv6_next_hop,
@@ -3608,7 +4293,8 @@ DEFUN (no_match_ipv6_next_hop,
"Match IPv6 next-hop address of route\n"
"IPv6 address of next hop\n")
{
- return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0],
+ RMAP_EVENT_MATCH_DELETED);
}
DEFUN (match_ipv6_address_prefix_list,
@@ -3620,7 +4306,8 @@ DEFUN (match_ipv6_address_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
- return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]);
+ return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list",
+ argv[0], RMAP_EVENT_PLIST_ADDED);
}
DEFUN (no_match_ipv6_address_prefix_list,
@@ -3633,7 +4320,8 @@ DEFUN (no_match_ipv6_address_prefix_list,
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
- return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
+ return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list",
+ argv[0], RMAP_EVENT_PLIST_DELETED);
}
DEFUN (set_ipv6_nexthop_peer,
@@ -3863,10 +4551,12 @@ bgp_route_map_init (void)
{
route_map_init ();
route_map_init_vty ();
- route_map_add_hook (bgp_route_map_update);
- route_map_delete_hook (bgp_route_map_update);
+ route_map_add_hook (bgp_route_map_add);
+ route_map_delete_hook (bgp_route_map_delete);
+ route_map_event_hook (bgp_route_map_event);
route_map_install_match (&route_match_peer_cmd);
+ route_map_install_match (&route_match_local_pref_cmd);
route_map_install_match (&route_match_ip_address_cmd);
route_map_install_match (&route_match_ip_next_hop_cmd);
route_map_install_match (&route_match_ip_route_source_cmd);
@@ -3876,9 +4566,12 @@ bgp_route_map_init (void)
route_map_install_match (&route_match_aspath_cmd);
route_map_install_match (&route_match_community_cmd);
route_map_install_match (&route_match_ecommunity_cmd);
+ route_map_install_match (&route_match_local_pref_cmd);
route_map_install_match (&route_match_metric_cmd);
route_map_install_match (&route_match_origin_cmd);
route_map_install_match (&route_match_probability_cmd);
+ route_map_install_match (&route_match_interface_cmd);
+ route_map_install_match (&route_match_tag_cmd);
route_map_install_set (&route_set_ip_nexthop_cmd);
route_map_install_set (&route_set_local_pref_cmd);
@@ -3895,6 +4588,7 @@ bgp_route_map_init (void)
route_map_install_set (&route_set_originator_id_cmd);
route_map_install_set (&route_set_ecommunity_rt_cmd);
route_map_install_set (&route_set_ecommunity_soo_cmd);
+ route_map_install_set (&route_set_tag_cmd);
install_element (RMAP_NODE, &match_peer_cmd);
install_element (RMAP_NODE, &match_peer_local_cmd);
@@ -3926,6 +4620,9 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &match_metric_cmd);
install_element (RMAP_NODE, &no_match_metric_cmd);
install_element (RMAP_NODE, &no_match_metric_val_cmd);
+ install_element (RMAP_NODE, &match_local_pref_cmd);
+ install_element (RMAP_NODE, &no_match_local_pref_cmd);
+ install_element (RMAP_NODE, &no_match_local_pref_val_cmd);
install_element (RMAP_NODE, &match_community_cmd);
install_element (RMAP_NODE, &match_community_exact_cmd);
install_element (RMAP_NODE, &no_match_community_cmd);
@@ -3940,6 +4637,12 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &match_probability_cmd);
install_element (RMAP_NODE, &no_match_probability_cmd);
install_element (RMAP_NODE, &no_match_probability_val_cmd);
+ install_element (RMAP_NODE, &match_interface_cmd);
+ install_element (RMAP_NODE, &no_match_interface_cmd);
+ install_element (RMAP_NODE, &no_match_interface_val_cmd);
+ install_element (RMAP_NODE, &match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_val_cmd);
install_element (RMAP_NODE, &set_ip_nexthop_cmd);
install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
@@ -3991,6 +4694,9 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &set_originator_id_cmd);
install_element (RMAP_NODE, &no_set_originator_id_cmd);
install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
+ install_element (RMAP_NODE, &set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_val_cmd);
route_map_install_match (&route_match_ipv6_address_cmd);
route_map_install_match (&route_match_ipv6_next_hop_cmd);
@@ -4024,3 +4730,15 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &no_match_pathlimit_as_cmd);
install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd);
}
+
+void
+bgp_route_map_terminate (void)
+{
+ /* ToDo: Cleanup all the used memory */
+
+ route_map_add_hook (NULL);
+ route_map_delete_hook (NULL);
+ route_map_event_hook (NULL);
+ route_map_finish();
+
+}
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 92bb9575..e66e0451 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "sockunion.h"
#include "vty.h"
#include "filter.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index bee12963..9531b69a 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -65,6 +65,7 @@ struct bgp_node
u_char flags;
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
+#define BGP_NODE_USER_CLEAR (1 << 1)
};
/*
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 6db3dcb1..5476a669 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -50,6 +50,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h"
+#include "bgpd/bgp_packet.h"
extern struct in_addr router_id_zebra;
@@ -166,15 +167,22 @@ peer_lookup_vty (struct vty *vty, const char *ip_str)
ret = str2sockunion (ip_str, &su);
if (ret < 0)
{
- vty_out (vty, "%% Malformed address: %s%s", ip_str, VTY_NEWLINE);
- return NULL;
+ peer = peer_lookup_by_conf_if (bgp, ip_str);
+ if (!peer)
+ {
+ vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
+ return NULL;
+ }
}
-
- peer = peer_lookup (bgp, &su);
- if (! peer)
+ else
{
- vty_out (vty, "%% Specify remote-as or peer-group commands first%s", VTY_NEWLINE);
- return NULL;
+ peer = peer_lookup (bgp, &su);
+ if (! peer)
+ {
+ vty_out (vty, "%% Specify remote-as or peer-group commands first%s",
+ VTY_NEWLINE);
+ return NULL;
+ }
}
return peer;
}
@@ -200,6 +208,10 @@ peer_and_group_lookup_vty (struct vty *vty, const char *peer_str)
}
else
{
+ peer = peer_lookup_by_conf_if (bgp, peer_str);
+ if (peer)
+ return peer;
+
group = peer_group_lookup (bgp, peer_str);
if (group)
return group->conf;
@@ -264,7 +276,7 @@ bgp_vty_return (struct vty *vty, int ret)
str = "Invalid command. Not an internal neighbor";
break;
case BGP_ERR_REMOVE_PRIVATE_AS:
- str = "Private AS cannot be removed for IBGP peers";
+ str = "remove-private-AS cannot be configured for IBGP peers";
break;
case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP:
str = "Local-AS allowed only for EBGP peers";
@@ -281,6 +293,9 @@ bgp_vty_return (struct vty *vty, int ret)
case BGP_ERR_NO_IBGP_WITH_TTLHACK:
str = "ttl-security only allowed for EBGP peers";
break;
+ case BGP_ERR_AS_OVERRIDE:
+ str = "as-override cannot be configured for IBGP peers";
+ break;
}
if (str)
{
@@ -712,87 +727,408 @@ DEFUN (no_bgp_confederation_peers,
return CMD_SUCCESS;
}
-/* Maximum-paths configuration */
-DEFUN (bgp_maxpaths,
- bgp_maxpaths_cmd,
- "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
- "Forward packets over multiple paths\n"
- "Number of paths\n")
+/**
+ * Central routine for maximum-paths configuration.
+ * @peer_type: BGP_PEER_EBGP or BGP_PEER_IBGP
+ * @set: 1 for setting values, 0 for removing the max-paths config.
+ */
+static int
+bgp_maxpaths_config_vty (struct vty *vty, int peer_type, const char *mpaths,
+ u_int16_t options, int set)
{
struct bgp *bgp;
- u_int16_t maxpaths;
+ u_int16_t maxpaths = 0;
int ret;
+ afi_t afi;
+ safi_t safi;
bgp = vty->index;
+ afi = bgp_node_afi (vty);
+ safi = bgp_node_safi (vty);
- VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, argv[0], 1, 255);
+ if (set)
+ {
+ VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, mpaths, 1,
+ BGP_MAXIMUM_MAXPATHS);
+ ret = bgp_maximum_paths_set (bgp, afi, safi, peer_type, maxpaths,
+ options);
+ }
+ else
+ ret = bgp_maximum_paths_unset (bgp, afi, safi, peer_type);
- ret = bgp_maximum_paths_set (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_EBGP, maxpaths);
if (ret < 0)
{
vty_out (vty,
- "%% Failed to set maximum-paths %u for afi %u, safi %u%s",
- maxpaths, bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
+ "%% Failed to %sset maximum-paths %s %u for afi %u, safi %u%s",
+ (set == 1) ? "" : "un",
+ (peer_type == BGP_PEER_EBGP) ? "ebgp" : "ibgp",
+ maxpaths, afi, safi, VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
-DEFUN (bgp_maxpaths_ibgp,
- bgp_maxpaths_ibgp_cmd,
- "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM),
- "Forward packets over multiple paths\n"
- "iBGP-multipath\n"
- "Number of paths\n")
+DEFUN (bgp_maxmed_admin,
+ bgp_maxmed_admin_cmd,
+ "bgp max-med administrative ",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n")
{
struct bgp *bgp;
- u_int16_t maxpaths;
- int ret;
bgp = vty->index;
- VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, argv[0], 1, 255);
+ bgp->v_maxmed_admin = 1;
+ bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT;
- ret = bgp_maximum_paths_set (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_IBGP, maxpaths);
- if (ret < 0)
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_maxmed_admin_medv,
+ bgp_maxmed_admin_medv_cmd,
+ "bgp max-med administrative <0-4294967294>",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n"
+ "Max MED value to be used\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ bgp->v_maxmed_admin = 1;
+ VTY_GET_INTEGER ("max-med admin med-value", bgp->maxmed_admin_value, argv[0]);
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_maxmed_admin,
+ no_bgp_maxmed_admin_cmd,
+ "no bgp max-med administrative",
+ NO_STR
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED;
+ bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT;
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_maxmed_admin,
+ no_bgp_maxmed_admin_medv_cmd,
+ "no bgp max-med administrative <0-4294967294>",
+ NO_STR
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n"
+ "Max MED value to be used\n")
+
+
+DEFUN (bgp_maxmed_onstartup,
+ bgp_maxmed_onstartup_cmd,
+ "bgp max-med on-startup <5-86400>",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n"
+ "Time (seconds) period for max-med\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ if (argc != 1)
{
- vty_out (vty,
- "%% Failed to set maximum-paths ibgp %u for afi %u, safi %u%s",
- maxpaths, bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
+ vty_out (vty, "%% Must supply max-med on-startup period");
return CMD_WARNING;
}
+ VTY_GET_INTEGER ("max-med on-startup period", bgp->v_maxmed_onstartup, argv[0]);
+ bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT;
+
+ bgp_maxmed_update(bgp);
+
return CMD_SUCCESS;
}
-DEFUN (no_bgp_maxpaths,
- no_bgp_maxpaths_cmd,
- "no maximum-paths",
+DEFUN (bgp_maxmed_onstartup_medv,
+ bgp_maxmed_onstartup_medv_cmd,
+ "bgp max-med on-startup <5-86400> <0-4294967294>",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n"
+ "Time (seconds) period for max-med\n"
+ "Max MED value to be used\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ if (argc != 2)
+ {
+ vty_out (vty, "%% Must supply max-med on-startup period and med value");
+ return CMD_WARNING;
+ }
+
+ VTY_GET_INTEGER ("max-med on-startup period", bgp->v_maxmed_onstartup, argv[0]);
+ VTY_GET_INTEGER ("max-med on-startup med-value", bgp->maxmed_onstartup_value, argv[1]);
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_maxmed_onstartup,
+ no_bgp_maxmed_onstartup_cmd,
+ "no bgp max-med on-startup",
NO_STR
- "Forward packets over multiple paths\n"
- "Number of paths\n")
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n")
{
struct bgp *bgp;
- int ret;
bgp = vty->index;
- ret = bgp_maximum_paths_unset (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_EBGP);
- if (ret < 0)
+ /* Cancel max-med onstartup if its on */
+ if (bgp->t_maxmed_onstartup)
{
- vty_out (vty,
- "%% Failed to unset maximum-paths for afi %u, safi %u%s",
- bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
+ THREAD_TIMER_OFF (bgp->t_maxmed_onstartup);
+ bgp->maxmed_onstartup_over = 1;
+ }
+
+ bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED;
+ bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT;
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_maxmed_onstartup,
+ no_bgp_maxmed_onstartup_period_cmd,
+ "no bgp max-med on-startup <5-86400>",
+ NO_STR
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n"
+ "Time (seconds) period for max-med\n")
+
+ALIAS (no_bgp_maxmed_onstartup,
+ no_bgp_maxmed_onstartup_period_medv_cmd,
+ "no bgp max-med on-startup <5-86400> <0-4294967294>",
+ NO_STR
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n"
+ "Time (seconds) period for max-med\n"
+ "Max MED value to be used\n")
+
+static int
+bgp_update_delay_config_vty (struct vty *vty, const char *delay,
+ const char *wait)
+{
+ struct bgp *bgp;
+ u_int16_t update_delay;
+ u_int16_t establish_wait;
+
+
+ bgp = vty->index;
+
+ VTY_GET_INTEGER_RANGE ("update-delay", update_delay, delay,
+ BGP_UPDATE_DELAY_MIN, BGP_UPDATE_DELAY_MAX);
+
+ if (!wait) /* update-delay <delay> */
+ {
+ bgp->v_update_delay = update_delay;
+ bgp->v_establish_wait = bgp->v_update_delay;
+ return CMD_SUCCESS;
+ }
+
+ /* update-delay <delay> <establish-wait> */
+ establish_wait = atoi (wait);
+ if (update_delay < establish_wait)
+ {
+ vty_out (vty, "%%Failed: update-delay less than the establish-wait!%s",
+ VTY_NEWLINE);
return CMD_WARNING;
}
+ bgp->v_update_delay = update_delay;
+ bgp->v_establish_wait = establish_wait;
+
+ return CMD_SUCCESS;
+}
+
+static int
+bgp_update_delay_deconfig_vty (struct vty *vty)
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
+ bgp->v_establish_wait = bgp->v_update_delay;
+
+ return CMD_SUCCESS;
+}
+
+int
+bgp_config_write_update_delay (struct vty *vty, struct bgp *bgp)
+{
+ if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF)
+ {
+ vty_out (vty, " update-delay %d", bgp->v_update_delay);
+ if (bgp->v_update_delay != bgp->v_establish_wait)
+ vty_out (vty, " %d", bgp->v_establish_wait);
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+
+ return 0;
+}
+
+
+/* Update-delay configuration */
+DEFUN (bgp_update_delay,
+ bgp_update_delay_cmd,
+ "update-delay <0-3600>",
+ "Force initial delay for best-path and updates\n"
+ "Seconds\n")
+{
+ return bgp_update_delay_config_vty(vty, argv[0], NULL);
+}
+
+DEFUN (bgp_update_delay_establish_wait,
+ bgp_update_delay_establish_wait_cmd,
+ "update-delay <0-3600> <1-3600>",
+ "Force initial delay for best-path and updates\n"
+ "Seconds\n"
+ "Wait for peers to be established\n"
+ "Seconds\n")
+{
+ return bgp_update_delay_config_vty(vty, argv[0], argv[1]);
+}
+
+/* Update-delay deconfiguration */
+DEFUN (no_bgp_update_delay,
+ no_bgp_update_delay_cmd,
+ "no update-delay <0-3600>",
+ "Force initial delay for best-path and updates\n"
+ "Seconds\n")
+{
+ return bgp_update_delay_deconfig_vty(vty);
+}
+
+ALIAS (no_bgp_update_delay,
+ no_bgp_update_delay_establish_wait_cmd,
+ "no update-delay <0-3600> <1-3600>",
+ "Force initial delay for best-path and updates\n"
+ "Seconds\n"
+ "Wait for peers to be established\n"
+ "Seconds\n")
+
+static int
+bgp_wpkt_quanta_config_vty (struct vty *vty, const char *num, char set)
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ if (set)
+ VTY_GET_INTEGER_RANGE ("write-quanta", bgp->wpkt_quanta, num,
+ 1, 10000);
+ else
+ bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
+
return CMD_SUCCESS;
}
+int
+bgp_config_write_wpkt_quanta (struct vty *vty, struct bgp *bgp)
+{
+ if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX)
+ vty_out (vty, " write-quanta %d%s",
+ bgp->wpkt_quanta, VTY_NEWLINE);
+
+ return 0;
+}
+
+
+/* Update-delay configuration */
+DEFUN (bgp_wpkt_quanta,
+ bgp_wpkt_quanta_cmd,
+ "write-quanta <1-10000>",
+ "How many packets to write to peer socket per run\n"
+ "Number of packets\n")
+{
+ return bgp_wpkt_quanta_config_vty(vty, argv[0], 1);
+}
+
+/* Update-delay deconfiguration */
+DEFUN (no_bgp_wpkt_quanta,
+ no_bgp_wpkt_quanta_cmd,
+ "no write-quanta <1-10000>",
+ "How many packets to write to peer socket per run\n"
+ "Number of packets\n")
+{
+ return bgp_wpkt_quanta_config_vty(vty, argv[0], 0);
+}
+
+/* Maximum-paths configuration */
+DEFUN (bgp_maxpaths,
+ bgp_maxpaths_cmd,
+ "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, argv[0], 0, 1);
+}
+
+DEFUN (bgp_maxpaths_ibgp,
+ bgp_maxpaths_ibgp_cmd,
+ "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM),
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[0], 0, 1);
+}
+
+DEFUN (bgp_maxpaths_ibgp_cluster,
+ bgp_maxpaths_ibgp_cluster_cmd,
+ "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM) " equal-cluster-length",
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[0],
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN, 1);
+}
+
+DEFUN (no_bgp_maxpaths,
+ no_bgp_maxpaths_cmd,
+ "no maximum-paths",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, NULL, 0, 0);
+}
+
ALIAS (no_bgp_maxpaths,
no_bgp_maxpaths_arg_cmd,
"no maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
@@ -808,22 +1144,7 @@ DEFUN (no_bgp_maxpaths_ibgp,
"iBGP-multipath\n"
"Number of paths\n")
{
- struct bgp *bgp;
- int ret;
-
- bgp = vty->index;
-
- ret = bgp_maximum_paths_unset (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_IBGP);
- if (ret < 0)
- {
- vty_out (vty,
- "%% Failed to unset maximum-paths ibgp for afi %u, safi %u%s",
- bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, NULL, 0, 0);
}
ALIAS (no_bgp_maxpaths_ibgp,
@@ -834,6 +1155,15 @@ ALIAS (no_bgp_maxpaths_ibgp,
"iBGP-multipath\n"
"Number of paths\n")
+ALIAS (no_bgp_maxpaths_ibgp,
+ no_bgp_maxpaths_ibgp_cluster_cmd,
+ "no maximum-paths ibgp <1-255> equal-cluster-length",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+
int
bgp_config_write_maxpaths (struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi, int *write)
@@ -848,8 +1178,12 @@ bgp_config_write_maxpaths (struct vty *vty, struct bgp *bgp, afi_t afi,
if (bgp->maxpaths[afi][safi].maxpaths_ibgp != BGP_DEFAULT_MAXPATHS)
{
bgp_config_write_family_header (vty, afi, safi, write);
- vty_out (vty, " maximum-paths ibgp %d%s",
- bgp->maxpaths[afi][safi].maxpaths_ibgp, VTY_NEWLINE);
+ vty_out (vty, " maximum-paths ibgp %d",
+ bgp->maxpaths[afi][safi].maxpaths_ibgp);
+ if (CHECK_FLAG (bgp->maxpaths[afi][safi].ibgp_flags,
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))
+ vty_out (vty, " equal-cluster-length");
+ vty_out (vty, "%s", VTY_NEWLINE);
}
return 0;
@@ -1483,6 +1817,80 @@ ALIAS (no_bgp_default_local_preference,
"local preference (higher=more preferred)\n"
"Configure default local preference value\n")
+static void
+peer_announce_routes_if_rmap_out (struct bgp *bgp)
+{
+ struct peer *peer;
+ struct listnode *node, *nnode;
+ struct bgp_filter *filter;
+ afi_t afi;
+ safi_t safi;
+
+ /* Reannounce all routes to appropriate neighbors */
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+ {
+ /* check if there's an out route-map on this client */
+ filter = &peer->filter[afi][safi];
+ if (ROUTE_MAP_OUT_NAME(filter))
+ {
+ if (bgp_debug_update(peer, NULL, 0))
+ zlog_debug("%s: Announcing routes again for peer %s"
+ "(afi=%d, safi=%d", __func__, peer->host, afi,
+ safi);
+
+ bgp_announce_route_all(peer);
+ }
+ }
+ }
+ }
+}
+
+DEFUN (bgp_rr_allow_outbound_policy,
+ bgp_rr_allow_outbound_policy_cmd,
+ "bgp route-reflector allow-outbound-policy",
+ "BGP specific commands\n"
+ "Allow modifications made by out route-map\n"
+ "on ibgp neighbors\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ if (!bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY))
+ {
+ bgp_flag_set(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY);
+ peer_announce_routes_if_rmap_out(bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_rr_allow_outbound_policy,
+ no_bgp_rr_allow_outbound_policy_cmd,
+ "no bgp route-reflector allow-outbound-policy",
+ NO_STR
+ "BGP specific commands\n"
+ "Allow modifications made by out route-map\n"
+ "on ibgp neighbors\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+
+ if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY))
+ {
+ bgp_flag_unset(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY);
+ peer_announce_routes_if_rmap_out(bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
static int
peer_remote_as_vty (struct vty *vty, const char *peer_str,
const char *as_str, afi_t afi, safi_t safi)
@@ -1501,24 +1909,31 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str,
ret = str2sockunion (peer_str, &su);
if (ret < 0)
{
- ret = peer_group_remote_as (bgp, peer_str, &as);
+ /* Check for peer by interface */
+ ret = peer_remote_as (bgp, NULL, peer_str, &as, afi, safi);
if (ret < 0)
- {
- vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return CMD_SUCCESS;
+ {
+ ret = peer_group_remote_as (bgp, peer_str, &as);
+ if (ret < 0)
+ {
+ vty_out (vty, "%% Create the peer-group or interface first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return CMD_SUCCESS;
+ }
}
-
- if (peer_address_self_check (&su))
+ else
{
- vty_out (vty, "%% Can not configure the local system as neighbor%s",
- VTY_NEWLINE);
- return CMD_WARNING;
+ if (peer_address_self_check (&su))
+ {
+ vty_out (vty, "%% Can not configure the local system as neighbor%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ ret = peer_remote_as (bgp, &su, NULL, &as, afi, safi);
}
- ret = peer_remote_as (bgp, &su, &as, afi, safi);
-
/* This peer belongs to peer group. */
switch (ret)
{
@@ -1543,17 +1958,51 @@ DEFUN (neighbor_remote_as,
return peer_remote_as_vty (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST);
}
+DEFUN (neighbor_interface_config,
+ neighbor_interface_config_cmd,
+ "neighbor WORD interface",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ struct peer_group *group;
+
+ bgp = vty->index;
+ group = peer_group_lookup (bgp, argv[0]);
+ if (group)
+ {
+ vty_out (vty, "%% Name conflict with peer-group %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ peer = peer_conf_interface_get (bgp, argv[0], AFI_IP, SAFI_UNICAST);
+ if (!peer)
+ return CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
+
DEFUN (neighbor_peer_group,
neighbor_peer_group_cmd,
"neighbor WORD peer-group",
NEIGHBOR_STR
- "Neighbor tag\n"
+ "Interface name or neighbor tag\n"
"Configure peer-group\n")
{
struct bgp *bgp;
+ struct peer *peer;
struct peer_group *group;
bgp = vty->index;
+ peer = peer_lookup_by_conf_if (bgp, argv[0]);
+ if (peer)
+ {
+ vty_out (vty, "%% Name conflict with interface: %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
group = peer_group_get (bgp, argv[0]);
if (! group)
@@ -1573,10 +2022,19 @@ DEFUN (no_neighbor,
union sockunion su;
struct peer_group *group;
struct peer *peer;
+ struct peer *other;
ret = str2sockunion (argv[0], &su);
if (ret < 0)
{
+ /* look up for neighbor by interface name config. */
+ peer = peer_lookup_by_conf_if (vty->index, argv[0]);
+ if (peer)
+ {
+ peer_delete (peer);
+ return CMD_SUCCESS;
+ }
+
group = peer_group_lookup (vty->index, argv[0]);
if (group)
peer_group_delete (group);
@@ -1590,7 +2048,12 @@ DEFUN (no_neighbor,
{
peer = peer_lookup (vty->index, &su);
if (peer)
- peer_delete (peer);
+ {
+ other = peer->doppelganger;
+ peer_delete (peer);
+ if (other && other->status != Deleted)
+ peer_delete(other);
+ }
}
return CMD_SUCCESS;
@@ -1605,6 +2068,30 @@ ALIAS (no_neighbor,
"Specify a BGP neighbor\n"
AS_STR)
+DEFUN (no_neighbor_interface_config,
+ no_neighbor_interface_config_cmd,
+ "no neighbor WORD interface",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name\n"
+ "Configure BGP on interface\n")
+{
+ struct peer *peer;
+
+ /* look up for neighbor by interface name config. */
+ peer = peer_lookup_by_conf_if (vty->index, argv[0]);
+ if (peer)
+ {
+ peer_delete (peer);
+ }
+ else
+ {
+ vty_out (vty, "%% Create the bgp interface first%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (no_neighbor_peer_group,
no_neighbor_peer_group_cmd,
"no neighbor WORD peer-group",
@@ -1626,23 +2113,32 @@ DEFUN (no_neighbor_peer_group,
return CMD_SUCCESS;
}
-DEFUN (no_neighbor_peer_group_remote_as,
- no_neighbor_peer_group_remote_as_cmd,
+DEFUN (no_neighbor_interface_peer_group_remote_as,
+ no_neighbor_interface_peer_group_remote_as_cmd,
"no neighbor WORD remote-as " CMD_AS_RANGE,
NO_STR
NEIGHBOR_STR
- "Neighbor tag\n"
+ "Interface name or neighbor tag\n"
"Specify a BGP neighbor\n"
AS_STR)
{
struct peer_group *group;
+ struct peer *peer;
+
+ /* look up for neighbor by interface name config. */
+ peer = peer_lookup_by_conf_if (vty->index, argv[0]);
+ if (peer)
+ {
+ peer_as_change (peer, 0);
+ return CMD_SUCCESS;
+ }
group = peer_group_lookup (vty->index, argv[0]);
if (group)
peer_group_remote_as_delete (group);
else
{
- vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE);
+ vty_out (vty, "%% Create the peer-group or interface first%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
@@ -1837,9 +2333,9 @@ DEFUN (no_neighbor_activate,
DEFUN (neighbor_set_peer_group,
neighbor_set_peer_group_cmd,
- NEIGHBOR_CMD "peer-group WORD",
+ NEIGHBOR_CMD2 "peer-group WORD",
NEIGHBOR_STR
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR2
"Member of the peer-group\n"
"peer-group name\n")
{
@@ -1847,15 +2343,30 @@ DEFUN (neighbor_set_peer_group,
as_t as;
union sockunion su;
struct bgp *bgp;
+ struct peer *peer;
struct peer_group *group;
bgp = vty->index;
+ peer = NULL;
ret = str2sockunion (argv[0], &su);
if (ret < 0)
{
- vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
+ peer = peer_lookup_by_conf_if (bgp, argv[0]);
+ if (!peer)
+ {
+ vty_out (vty, "%% Malformed address or name: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ if (peer_address_self_check (&su))
+ {
+ vty_out (vty, "%% Can not configure the local system as neighbor%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
group = peer_group_lookup (bgp, argv[1]);
@@ -1865,14 +2376,7 @@ DEFUN (neighbor_set_peer_group,
return CMD_WARNING;
}
- if (peer_address_self_check (&su))
- {
- vty_out (vty, "%% Can not configure the local system as neighbor%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- ret = peer_group_bind (bgp, &su, group, bgp_node_afi (vty),
+ ret = peer_group_bind (bgp, &su, peer, group, bgp_node_afi (vty),
bgp_node_safi (vty), &as);
if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT)
@@ -1886,10 +2390,10 @@ DEFUN (neighbor_set_peer_group,
DEFUN (no_neighbor_set_peer_group,
no_neighbor_set_peer_group_cmd,
- NO_NEIGHBOR_CMD "peer-group WORD",
+ NO_NEIGHBOR_CMD2 "peer-group WORD",
NO_STR
NEIGHBOR_STR
- NEIGHBOR_ADDR_STR
+ NEIGHBOR_ADDR_STR2
"Member of the peer-group\n"
"peer-group name\n")
{
@@ -2191,32 +2695,143 @@ DEFUN (no_neighbor_nexthop_self,
PEER_FLAG_NEXTHOP_SELF|PEER_FLAG_NEXTHOP_SELF_ALL);
}
+/* neighbor as-override */
+DEFUN (neighbor_as_override,
+ neighbor_as_override_cmd,
+ NEIGHBOR_CMD2 "as-override",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Override ASNs in outbound updates if aspath equals remote-as\n")
+{
+ return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_AS_OVERRIDE);
+}
+
+DEFUN (no_neighbor_as_override,
+ no_neighbor_as_override_cmd,
+ NO_NEIGHBOR_CMD2 "as-override",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Override ASNs in outbound updates if aspath equals remote-as\n")
+{
+ return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_AS_OVERRIDE);
+}
+
/* neighbor remove-private-AS. */
DEFUN (neighbor_remove_private_as,
neighbor_remove_private_as_cmd,
NEIGHBOR_CMD2 "remove-private-AS",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
- "Remove private AS number from outbound updates\n")
+ "Remove private ASNs in outbound updates\n")
{
+ peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS);
}
+DEFUN (neighbor_remove_private_as_all,
+ neighbor_remove_private_as_all_cmd,
+ NEIGHBOR_CMD2 "remove-private-AS all",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers")
+{
+ peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
+ return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS|
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
+}
+
+DEFUN (neighbor_remove_private_as_replace_as,
+ neighbor_remove_private_as_replace_as_cmd,
+ NEIGHBOR_CMD2 "remove-private-AS replace-AS",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+{
+ peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
+ return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS|
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
+}
+
+DEFUN (neighbor_remove_private_as_all_replace_as,
+ neighbor_remove_private_as_all_replace_as_cmd,
+ NEIGHBOR_CMD2 "remove-private-AS all replace-AS",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers"
+ "Replace private ASNs with our ASN in outbound updates\n")
+{
+ return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+ bgp_node_safi (vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS|
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
+}
+
DEFUN (no_neighbor_remove_private_as,
no_neighbor_remove_private_as_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
- "Remove private AS number from outbound updates\n")
+ "Remove private ASNs in outbound updates\n")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
- PEER_FLAG_REMOVE_PRIVATE_AS);
+ PEER_FLAG_REMOVE_PRIVATE_AS|
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
}
+ALIAS (no_neighbor_remove_private_as,
+ no_neighbor_remove_private_as_all_cmd,
+ NO_NEIGHBOR_CMD2 "remove-private-AS all",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers")
+
+ALIAS (no_neighbor_remove_private_as,
+ no_neighbor_remove_private_as_replace_as_cmd,
+ NO_NEIGHBOR_CMD2 "remove-private-AS replace-AS",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+
+ALIAS (no_neighbor_remove_private_as,
+ no_neighbor_remove_private_as_all_replace_as_cmd,
+ NO_NEIGHBOR_CMD2 "remove-private-AS all replace-AS",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers"
+ "Replace private ASNs with our ASN in outbound updates\n")
+
+
/* neighbor send-community. */
DEFUN (neighbor_send_community,
neighbor_send_community_cmd,
@@ -3090,6 +3705,9 @@ peer_update_source_vty (struct vty *vty, const char *peer_str,
if (! peer)
return CMD_WARNING;
+ if (peer->conf_if)
+ return CMD_WARNING;
+
if (source_str)
{
union sockunion su;
@@ -3539,6 +4157,54 @@ ALIAS (no_neighbor_advertise_interval,
"Minimum interval between sending BGP routing updates\n"
"time in seconds\n")
+/* Time to wait before processing route-map updates */
+DEFUN (bgp_set_route_map_delay_timer,
+ bgp_set_route_map_delay_timer_cmd,
+ "bgp route-map delay-timer <0-600>",
+ SET_STR
+ "BGP route-map delay timer\n"
+ "Time in secs to wait before processing route-map changes\n"
+ "0 disables the timer and no route updates happen when\n"
+ "route-maps change")
+{
+ u_int32_t rmap_delay_timer;
+ struct bgp *bgp;
+
+ bgp = vty->index;
+ if (argv[0])
+ {
+ VTY_GET_INTEGER_RANGE ("delay-timer", rmap_delay_timer, argv[0], 0, 600);
+ bgp->rmap_update_timer = rmap_delay_timer;
+
+ /* if the dynamic update handling is being disabled, and a timer is
+ * running, stop the timer and act as if the timer has already fired.
+ */
+ if (!rmap_delay_timer && bgp->t_rmap_update )
+ {
+ BGP_TIMER_OFF(bgp->t_rmap_update);
+ thread_execute (bm->master, bgp_route_map_update_timer, &bgp, 0);
+ }
+ return CMD_SUCCESS;
+ }
+ else
+ return CMD_WARNING;
+}
+
+DEFUN (no_bgp_set_route_map_delay_timer,
+ no_bgp_set_route_map_delay_timer_cmd,
+ "no bgp route-map delay-timer",
+ NO_STR
+ "Default BGP route-map delay timer\n"
+ "Reset to default time to wait for processing route-map changes")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+ bgp->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
+
+ return CMD_SUCCESS;
+}
+
/* neighbor interface */
static int
peer_interface_vty (struct vty *vty, const char *ip_str, const char *str)
@@ -3547,7 +4213,7 @@ peer_interface_vty (struct vty *vty, const char *ip_str, const char *str)
struct peer *peer;
peer = peer_lookup_vty (vty, ip_str);
- if (! peer)
+ if (! peer || peer->conf_if)
return CMD_WARNING;
if (str)
@@ -4437,18 +5103,27 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
struct listnode *node, *nnode;
/* Clear all neighbors. */
+ /*
+ * Pass along pointer to next node to peer_clear() when walking all nodes
+ * on the BGP instance as that may get freed if it is a doppelganger
+ */
if (sort == clear_all)
{
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear (peer);
+ ret = peer_clear (peer, &nnode);
else
ret = peer_clear_soft (peer, afi, safi, stype);
if (ret < 0)
bgp_clear_vty_error (vty, peer, afi, safi, ret);
}
+
+ /* This is to apply read-only mode on this clear. */
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ bgp->update_delay_over = 0;
+
return CMD_SUCCESS;
}
@@ -4461,19 +5136,26 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
/* Make sockunion for lookup. */
ret = str2sockunion (arg, &su);
if (ret < 0)
- {
- vty_out (vty, "Malformed address: %s%s", arg, VTY_NEWLINE);
- return CMD_WARNING;
- }
- peer = peer_lookup (bgp, &su);
- if (! peer)
- {
- vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ {
+ peer = peer_lookup_by_conf_if (bgp, arg);
+ if (!peer)
+ {
+ vty_out (vty, "Malformed address or name: %s%s", arg, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ peer = peer_lookup (bgp, &su);
+ if (! peer)
+ {
+ vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear (peer);
+ ret = peer_clear (peer, NULL);
else
ret = peer_clear_soft (peer, afi, safi, stype);
@@ -4499,7 +5181,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
{
if (stype == BGP_CLEAR_SOFT_NONE)
{
- ret = peer_clear (peer);
+ ret = peer_clear (peer, NULL);
continue;
}
@@ -4522,7 +5204,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
continue;
if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear (peer);
+ ret = peer_clear (peer, &nnode);
else
ret = peer_clear_soft (peer, afi, safi, stype);
@@ -4546,7 +5228,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
find = 1;
if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear (peer);
+ ret = peer_clear (peer, &nnode);
else
ret = peer_clear_soft (peer, afi, safi, stype);
@@ -4562,6 +5244,87 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
return CMD_SUCCESS;
}
+/* Recalculate bestpath and re-advertise a prefix */
+static int
+bgp_clear_prefix (struct vty *vty, char *view_name, const char *ip_str,
+ afi_t afi, safi_t safi, struct prefix_rd *prd)
+{
+ int ret;
+ struct prefix match;
+ struct bgp_node *rn;
+ struct bgp_node *rm;
+ struct bgp *bgp;
+ struct bgp_table *table;
+ struct bgp_table *rib;
+
+ /* BGP structure lookup. */
+ if (view_name)
+ {
+ bgp = bgp_lookup_by_name (view_name);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "%% Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ bgp = bgp_get_default ();
+ if (bgp == NULL)
+ {
+ vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ /* Check IP address argument. */
+ ret = str2prefix (ip_str, &match);
+ if (! ret)
+ {
+ vty_out (vty, "%% address is malformed%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ match.family = afi2family (afi);
+ rib = bgp->rib[afi][safi];
+
+ if (safi == SAFI_MPLS_VPN)
+ {
+ for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
+ {
+ if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+ continue;
+
+ if ((table = rn->info) != NULL)
+ {
+ if ((rm = bgp_node_match (table, &match)) != NULL)
+ {
+ if (rm->p.prefixlen == match.prefixlen)
+ {
+ SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR);
+ bgp_process (bgp, rm, afi, safi);
+ }
+ bgp_unlock_node (rm);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((rn = bgp_node_match (rib, &match)) != NULL)
+ {
+ if (rn->p.prefixlen == match.prefixlen)
+ {
+ SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR);
+ bgp_process (bgp, rn, afi, safi);
+ }
+ bgp_unlock_node (rn);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
static int
bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi,
enum clear_sort sort, enum bgp_clear_type stype,
@@ -4642,32 +5405,35 @@ ALIAS (clear_ip_bgp_all,
DEFUN (clear_ip_bgp_peer,
clear_ip_bgp_peer_cmd,
- "clear ip bgp (A.B.C.D|X:X::X:X)",
+ "clear ip bgp (A.B.C.D|X:X::X:X|WORD)",
CLEAR_STR
IP_STR
BGP_STR
"BGP neighbor IP address to clear\n"
- "BGP IPv6 neighbor to clear\n")
+ "BGP IPv6 neighbor to clear\n"
+ "BGP neighbor on interface to clear\n")
{
return bgp_clear_vty (vty, NULL, 0, 0, clear_peer, BGP_CLEAR_SOFT_NONE, argv[0]);
}
ALIAS (clear_ip_bgp_peer,
clear_bgp_peer_cmd,
- "clear bgp (A.B.C.D|X:X::X:X)",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD)",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
- "BGP IPv6 neighbor to clear\n")
+ "BGP IPv6 neighbor to clear\n"
+ "BGP neighbor on interface to clear\n")
ALIAS (clear_ip_bgp_peer,
clear_bgp_ipv6_peer_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X)",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD)",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
- "BGP IPv6 neighbor to clear\n")
+ "BGP IPv6 neighbor to clear\n"
+ "BGP neighbor on interface to clear\n")
DEFUN (clear_ip_bgp_peer_group,
clear_ip_bgp_peer_group_cmd,
@@ -4724,6 +5490,27 @@ ALIAS (clear_ip_bgp_external,
"Address family\n"
"Clear all external peers\n")
+DEFUN (clear_ip_bgp_prefix,
+ clear_ip_bgp_prefix_cmd,
+ "clear ip bgp prefix A.B.C.D/M",
+ CLEAR_STR
+ IP_STR
+ BGP_STR
+ "Clear bestpath and re-advertise\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+ return bgp_clear_prefix (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL);
+}
+
+ALIAS (clear_ip_bgp_prefix,
+ clear_bgp_prefix_cmd,
+ "clear bgp prefix A.B.C.D/M",
+ CLEAR_STR
+ BGP_STR
+ "Clear bestpath and re-advertise\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+
+
DEFUN (clear_ip_bgp_as,
clear_ip_bgp_as_cmd,
"clear ip bgp " CMD_AS_RANGE,
@@ -4758,8 +5545,8 @@ DEFUN (clear_ip_bgp_all_soft_out,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
@@ -4776,7 +5563,7 @@ ALIAS (clear_ip_bgp_all_soft_out,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
ALIAS (clear_ip_bgp_all_soft_out,
clear_ip_bgp_instance_all_soft_out_cmd,
@@ -4787,8 +5574,8 @@ ALIAS (clear_ip_bgp_all_soft_out,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_all_ipv4_soft_out,
clear_ip_bgp_all_ipv4_soft_out_cmd,
@@ -4800,8 +5587,8 @@ DEFUN (clear_ip_bgp_all_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
@@ -4821,7 +5608,7 @@ ALIAS (clear_ip_bgp_all_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_instance_all_ipv4_soft_out,
clear_ip_bgp_instance_all_ipv4_soft_out_cmd,
@@ -4835,7 +5622,7 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all,
@@ -4854,8 +5641,8 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft_out,
"Clear all peers\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all,
BGP_CLEAR_SOFT_OUT, NULL);
@@ -4870,7 +5657,7 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_out,
"Clear all peers\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_all_encap_soft_out,
clear_ip_bgp_all_encap_soft_out_cmd,
@@ -4905,8 +5692,8 @@ DEFUN (clear_bgp_all_soft_out,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
@@ -4924,8 +5711,8 @@ ALIAS (clear_bgp_all_soft_out,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_all_soft_out,
clear_bgp_all_out_cmd,
@@ -4933,7 +5720,7 @@ ALIAS (clear_bgp_all_soft_out,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_all_soft_out,
clear_bgp_ipv6_all_soft_out_cmd,
@@ -4942,8 +5729,8 @@ ALIAS (clear_bgp_all_soft_out,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_all_soft_out,
clear_bgp_ipv6_all_out_cmd,
@@ -4952,7 +5739,23 @@ ALIAS (clear_bgp_all_soft_out,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
+
+DEFUN (clear_bgp_ipv6_safi_prefix,
+ clear_bgp_ipv6_safi_prefix_cmd,
+ "clear bgp ipv6 (unicast|multicast) prefix X:X::X:X/M",
+ CLEAR_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family Modifier\n"
+ "Clear bestpath and re-advertise\n"
+ "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_clear_prefix (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL);
+ else
+ return bgp_clear_prefix (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL);
+}
DEFUN (clear_ip_bgp_peer_soft_out,
clear_ip_bgp_peer_soft_out_cmd,
@@ -4961,8 +5764,8 @@ DEFUN (clear_ip_bgp_peer_soft_out,
IP_STR
BGP_STR
"BGP neighbor address to clear\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -4975,7 +5778,7 @@ ALIAS (clear_ip_bgp_peer_soft_out,
IP_STR
BGP_STR
"BGP neighbor address to clear\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_peer_ipv4_soft_out,
clear_ip_bgp_peer_ipv4_soft_out_cmd,
@@ -4987,8 +5790,8 @@ DEFUN (clear_ip_bgp_peer_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
@@ -5008,7 +5811,7 @@ ALIAS (clear_ip_bgp_peer_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_peer_vpnv4_soft_out,
clear_ip_bgp_peer_vpnv4_soft_out_cmd,
@@ -5019,8 +5822,8 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft_out,
"BGP neighbor address to clear\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5035,7 +5838,7 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_out,
"BGP neighbor address to clear\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_peer_encap_soft_out,
clear_ip_bgp_peer_encap_soft_out_cmd,
@@ -5066,13 +5869,14 @@ ALIAS (clear_ip_bgp_peer_encap_soft_out,
DEFUN (clear_bgp_peer_soft_out,
clear_bgp_peer_soft_out_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) soft out",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) soft out",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5080,33 +5884,36 @@ DEFUN (clear_bgp_peer_soft_out,
ALIAS (clear_bgp_peer_soft_out,
clear_bgp_ipv6_peer_soft_out_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft out",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) soft out",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_peer_soft_out,
clear_bgp_peer_out_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) out",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) out",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig outbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_peer_soft_out,
clear_bgp_ipv6_peer_out_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) out",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) out",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig outbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_peer_group_soft_out,
clear_ip_bgp_peer_group_soft_out_cmd,
@@ -5116,8 +5923,8 @@ DEFUN (clear_ip_bgp_peer_group_soft_out,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5131,7 +5938,7 @@ ALIAS (clear_ip_bgp_peer_group_soft_out,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_peer_group_ipv4_soft_out,
clear_ip_bgp_peer_group_ipv4_soft_out_cmd,
@@ -5144,8 +5951,8 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
@@ -5166,7 +5973,7 @@ ALIAS (clear_ip_bgp_peer_group_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_bgp_peer_group_soft_out,
clear_bgp_peer_group_soft_out_cmd,
@@ -5175,8 +5982,8 @@ DEFUN (clear_bgp_peer_group_soft_out,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5190,8 +5997,8 @@ ALIAS (clear_bgp_peer_group_soft_out,
"Address family\n"
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_peer_group_soft_out,
clear_bgp_peer_group_out_cmd,
@@ -5200,7 +6007,7 @@ ALIAS (clear_bgp_peer_group_soft_out,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_peer_group_soft_out,
clear_bgp_ipv6_peer_group_out_cmd,
@@ -5210,7 +6017,7 @@ ALIAS (clear_bgp_peer_group_soft_out,
"Address family\n"
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_external_soft_out,
clear_ip_bgp_external_soft_out_cmd,
@@ -5219,8 +6026,8 @@ DEFUN (clear_ip_bgp_external_soft_out,
IP_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
BGP_CLEAR_SOFT_OUT, NULL);
@@ -5233,7 +6040,7 @@ ALIAS (clear_ip_bgp_external_soft_out,
IP_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_external_ipv4_soft_out,
clear_ip_bgp_external_ipv4_soft_out_cmd,
@@ -5245,8 +6052,8 @@ DEFUN (clear_ip_bgp_external_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
@@ -5266,7 +6073,7 @@ ALIAS (clear_ip_bgp_external_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_bgp_external_soft_out,
clear_bgp_external_soft_out_cmd,
@@ -5274,8 +6081,8 @@ DEFUN (clear_bgp_external_soft_out,
CLEAR_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
BGP_CLEAR_SOFT_OUT, NULL);
@@ -5288,8 +6095,8 @@ ALIAS (clear_bgp_external_soft_out,
BGP_STR
"Address family\n"
"Clear all external peers\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_external_soft_out,
clear_bgp_external_out_cmd,
@@ -5297,7 +6104,7 @@ ALIAS (clear_bgp_external_soft_out,
CLEAR_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_external_soft_out,
clear_bgp_ipv6_external_out_cmd,
@@ -5306,7 +6113,7 @@ ALIAS (clear_bgp_external_soft_out,
BGP_STR
"Address family\n"
"Clear all external peers\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_as_soft_out,
clear_ip_bgp_as_soft_out_cmd,
@@ -5315,8 +6122,8 @@ DEFUN (clear_ip_bgp_as_soft_out,
IP_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5329,7 +6136,7 @@ ALIAS (clear_ip_bgp_as_soft_out,
IP_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_as_ipv4_soft_out,
clear_ip_bgp_as_ipv4_soft_out_cmd,
@@ -5341,8 +6148,8 @@ DEFUN (clear_ip_bgp_as_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
@@ -5362,7 +6169,7 @@ ALIAS (clear_ip_bgp_as_ipv4_soft_out,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
clear_ip_bgp_as_vpnv4_soft_out_cmd,
@@ -5373,8 +6180,8 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
"Clear peers with the AS number\n"
"Address family\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5389,7 +6196,7 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
"Clear peers with the AS number\n"
"Address family\n"
"Address Family modifier\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
DEFUN (clear_ip_bgp_as_encap_soft_out,
clear_ip_bgp_as_encap_soft_out_cmd,
@@ -5424,8 +6231,8 @@ DEFUN (clear_bgp_as_soft_out,
CLEAR_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
BGP_CLEAR_SOFT_OUT, argv[0]);
@@ -5438,8 +6245,8 @@ ALIAS (clear_bgp_as_soft_out,
BGP_STR
"Address family\n"
"Clear peers with the AS number\n"
- "Soft reconfig\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_as_soft_out,
clear_bgp_as_out_cmd,
@@ -5447,7 +6254,7 @@ ALIAS (clear_bgp_as_soft_out,
CLEAR_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
ALIAS (clear_bgp_as_soft_out,
clear_bgp_ipv6_as_out_cmd,
@@ -5456,7 +6263,7 @@ ALIAS (clear_bgp_as_soft_out,
BGP_STR
"Address family\n"
"Clear peers with the AS number\n"
- "Soft reconfig outbound update\n")
+ BGP_SOFT_OUT_STR)
/* Inbound soft-reconfiguration */
DEFUN (clear_ip_bgp_all_soft_in,
@@ -5466,8 +6273,8 @@ DEFUN (clear_ip_bgp_all_soft_in,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
@@ -5486,8 +6293,8 @@ ALIAS (clear_ip_bgp_all_soft_in,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_ip_bgp_all_soft_in,
clear_ip_bgp_all_in_cmd,
@@ -5496,7 +6303,7 @@ ALIAS (clear_ip_bgp_all_soft_in,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_all_in_prefix_filter,
clear_ip_bgp_all_in_prefix_filter_cmd,
@@ -5505,7 +6312,7 @@ DEFUN (clear_ip_bgp_all_in_prefix_filter,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
if (argc== 1)
@@ -5525,7 +6332,7 @@ ALIAS (clear_ip_bgp_all_in_prefix_filter,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
@@ -5539,8 +6346,8 @@ DEFUN (clear_ip_bgp_all_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
@@ -5560,7 +6367,7 @@ ALIAS (clear_ip_bgp_all_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_instance_all_ipv4_soft_in,
clear_ip_bgp_instance_all_ipv4_soft_in_cmd,
@@ -5574,8 +6381,8 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all,
@@ -5595,7 +6402,7 @@ DEFUN (clear_ip_bgp_all_ipv4_in_prefix_filter,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
if (strncmp (argv[0], "m", 1) == 0)
@@ -5616,7 +6423,7 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_in_prefix_filter,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
if (strncmp (argv[1], "m", 1) == 0)
@@ -5636,8 +6443,8 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft_in,
"Clear all peers\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all,
BGP_CLEAR_SOFT_IN, NULL);
@@ -5652,7 +6459,7 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_in,
"Clear all peers\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_all_encap_soft_in,
clear_ip_bgp_all_encap_soft_in_cmd,
@@ -5687,8 +6494,8 @@ DEFUN (clear_bgp_all_soft_in,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
@@ -5706,8 +6513,8 @@ ALIAS (clear_bgp_all_soft_in,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_all_soft_in,
clear_bgp_ipv6_all_soft_in_cmd,
@@ -5716,8 +6523,8 @@ ALIAS (clear_bgp_all_soft_in,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_all_soft_in,
clear_bgp_all_in_cmd,
@@ -5725,7 +6532,7 @@ ALIAS (clear_bgp_all_soft_in,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_all_soft_in,
clear_bgp_ipv6_all_in_cmd,
@@ -5734,7 +6541,7 @@ ALIAS (clear_bgp_all_soft_in,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_bgp_all_in_prefix_filter,
clear_bgp_all_in_prefix_filter_cmd,
@@ -5742,7 +6549,7 @@ DEFUN (clear_bgp_all_in_prefix_filter,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
@@ -5756,7 +6563,7 @@ ALIAS (clear_bgp_all_in_prefix_filter,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
DEFUN (clear_ip_bgp_peer_soft_in,
@@ -5766,8 +6573,8 @@ DEFUN (clear_ip_bgp_peer_soft_in,
IP_STR
BGP_STR
"BGP neighbor address to clear\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -5780,7 +6587,7 @@ ALIAS (clear_ip_bgp_peer_soft_in,
IP_STR
BGP_STR
"BGP neighbor address to clear\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_peer_in_prefix_filter,
clear_ip_bgp_peer_in_prefix_filter_cmd,
@@ -5789,7 +6596,7 @@ DEFUN (clear_ip_bgp_peer_in_prefix_filter,
IP_STR
BGP_STR
"BGP neighbor address to clear\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out the existing ORF prefix-list\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
@@ -5806,8 +6613,8 @@ DEFUN (clear_ip_bgp_peer_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
@@ -5827,7 +6634,7 @@ ALIAS (clear_ip_bgp_peer_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_peer_ipv4_in_prefix_filter,
clear_ip_bgp_peer_ipv4_in_prefix_filter_cmd,
@@ -5839,7 +6646,7 @@ DEFUN (clear_ip_bgp_peer_ipv4_in_prefix_filter,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out the existing ORF prefix-list\n")
{
if (strncmp (argv[1], "m", 1) == 0)
@@ -5859,8 +6666,8 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft_in,
"BGP neighbor address to clear\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -5875,7 +6682,7 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_in,
"BGP neighbor address to clear\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_peer_encap_soft_in,
clear_ip_bgp_peer_encap_soft_in_cmd,
@@ -5906,13 +6713,14 @@ ALIAS (clear_ip_bgp_peer_encap_soft_in,
DEFUN (clear_bgp_peer_soft_in,
clear_bgp_peer_soft_in_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) soft in",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) soft in",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -5920,42 +6728,46 @@ DEFUN (clear_bgp_peer_soft_in,
ALIAS (clear_bgp_peer_soft_in,
clear_bgp_ipv6_peer_soft_in_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft in",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) soft in",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_peer_soft_in,
clear_bgp_peer_in_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) in",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) in",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig inbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_peer_soft_in,
clear_bgp_ipv6_peer_in_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) in",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) in",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig inbound update\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_IN_STR)
DEFUN (clear_bgp_peer_in_prefix_filter,
clear_bgp_peer_in_prefix_filter_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) in prefix-filter",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) in prefix-filter",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig inbound update\n"
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_IN_STR
"Push out the existing ORF prefix-list\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
@@ -5964,13 +6776,14 @@ DEFUN (clear_bgp_peer_in_prefix_filter,
ALIAS (clear_bgp_peer_in_prefix_filter,
clear_bgp_ipv6_peer_in_prefix_filter_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) in prefix-filter",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) in prefix-filter",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig inbound update\n"
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_IN_STR
"Push out the existing ORF prefix-list\n")
DEFUN (clear_ip_bgp_peer_group_soft_in,
@@ -5981,8 +6794,8 @@ DEFUN (clear_ip_bgp_peer_group_soft_in,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -5996,7 +6809,7 @@ ALIAS (clear_ip_bgp_peer_group_soft_in,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_peer_group_in_prefix_filter,
clear_ip_bgp_peer_group_in_prefix_filter_cmd,
@@ -6006,7 +6819,7 @@ DEFUN (clear_ip_bgp_peer_group_in_prefix_filter,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
@@ -6024,8 +6837,8 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
@@ -6046,7 +6859,7 @@ ALIAS (clear_ip_bgp_peer_group_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_peer_group_ipv4_in_prefix_filter,
clear_ip_bgp_peer_group_ipv4_in_prefix_filter_cmd,
@@ -6059,7 +6872,7 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_in_prefix_filter,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
if (strncmp (argv[1], "m", 1) == 0)
@@ -6077,8 +6890,8 @@ DEFUN (clear_bgp_peer_group_soft_in,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -6092,8 +6905,8 @@ ALIAS (clear_bgp_peer_group_soft_in,
"Address family\n"
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_peer_group_soft_in,
clear_bgp_peer_group_in_cmd,
@@ -6102,7 +6915,7 @@ ALIAS (clear_bgp_peer_group_soft_in,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_peer_group_soft_in,
clear_bgp_ipv6_peer_group_in_cmd,
@@ -6112,7 +6925,7 @@ ALIAS (clear_bgp_peer_group_soft_in,
"Address family\n"
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_bgp_peer_group_in_prefix_filter,
clear_bgp_peer_group_in_prefix_filter_cmd,
@@ -6121,7 +6934,7 @@ DEFUN (clear_bgp_peer_group_in_prefix_filter,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
@@ -6136,7 +6949,7 @@ ALIAS (clear_bgp_peer_group_in_prefix_filter,
"Address family\n"
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
DEFUN (clear_ip_bgp_external_soft_in,
@@ -6146,8 +6959,8 @@ DEFUN (clear_ip_bgp_external_soft_in,
IP_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
BGP_CLEAR_SOFT_IN, NULL);
@@ -6160,7 +6973,7 @@ ALIAS (clear_ip_bgp_external_soft_in,
IP_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_external_in_prefix_filter,
clear_ip_bgp_external_in_prefix_filter_cmd,
@@ -6169,7 +6982,7 @@ DEFUN (clear_ip_bgp_external_in_prefix_filter,
IP_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
@@ -6186,8 +6999,8 @@ DEFUN (clear_ip_bgp_external_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
@@ -6207,7 +7020,7 @@ ALIAS (clear_ip_bgp_external_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_external_ipv4_in_prefix_filter,
clear_ip_bgp_external_ipv4_in_prefix_filter_cmd,
@@ -6219,7 +7032,7 @@ DEFUN (clear_ip_bgp_external_ipv4_in_prefix_filter,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
if (strncmp (argv[0], "m", 1) == 0)
@@ -6236,8 +7049,8 @@ DEFUN (clear_bgp_external_soft_in,
CLEAR_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
BGP_CLEAR_SOFT_IN, NULL);
@@ -6250,8 +7063,8 @@ ALIAS (clear_bgp_external_soft_in,
BGP_STR
"Address family\n"
"Clear all external peers\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_external_soft_in,
clear_bgp_external_in_cmd,
@@ -6259,7 +7072,7 @@ ALIAS (clear_bgp_external_soft_in,
CLEAR_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_external_soft_in,
clear_bgp_ipv6_external_in_cmd,
@@ -6268,7 +7081,7 @@ ALIAS (clear_bgp_external_soft_in,
BGP_STR
"Address family\n"
"Clear all external peers\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_bgp_external_in_prefix_filter,
clear_bgp_external_in_prefix_filter_cmd,
@@ -6276,7 +7089,7 @@ DEFUN (clear_bgp_external_in_prefix_filter,
CLEAR_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
@@ -6290,7 +7103,7 @@ ALIAS (clear_bgp_external_in_prefix_filter,
BGP_STR
"Address family\n"
"Clear all external peers\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
DEFUN (clear_ip_bgp_as_soft_in,
@@ -6300,8 +7113,8 @@ DEFUN (clear_ip_bgp_as_soft_in,
IP_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -6314,7 +7127,7 @@ ALIAS (clear_ip_bgp_as_soft_in,
IP_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_as_in_prefix_filter,
clear_ip_bgp_as_in_prefix_filter_cmd,
@@ -6323,7 +7136,7 @@ DEFUN (clear_ip_bgp_as_in_prefix_filter,
IP_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
@@ -6340,8 +7153,8 @@ DEFUN (clear_ip_bgp_as_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
@@ -6361,7 +7174,7 @@ ALIAS (clear_ip_bgp_as_ipv4_soft_in,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
clear_ip_bgp_as_ipv4_in_prefix_filter_cmd,
@@ -6373,7 +7186,7 @@ DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
if (strncmp (argv[1], "m", 1) == 0)
@@ -6393,8 +7206,8 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft_in,
"Clear peers with the AS number\n"
"Address family\n"
"Address Family modifier\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -6409,7 +7222,7 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
"Clear peers with the AS number\n"
"Address family\n"
"Address Family modifier\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_ip_bgp_as_encap_soft_in,
clear_ip_bgp_as_encap_soft_in_cmd,
@@ -6444,8 +7257,8 @@ DEFUN (clear_bgp_as_soft_in,
CLEAR_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
BGP_CLEAR_SOFT_IN, argv[0]);
@@ -6458,8 +7271,8 @@ ALIAS (clear_bgp_as_soft_in,
BGP_STR
"Address family\n"
"Clear peers with the AS number\n"
- "Soft reconfig\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_as_soft_in,
clear_bgp_as_in_cmd,
@@ -6467,7 +7280,7 @@ ALIAS (clear_bgp_as_soft_in,
CLEAR_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
ALIAS (clear_bgp_as_soft_in,
clear_bgp_ipv6_as_in_cmd,
@@ -6476,7 +7289,7 @@ ALIAS (clear_bgp_as_soft_in,
BGP_STR
"Address family\n"
"Clear peers with the AS number\n"
- "Soft reconfig inbound update\n")
+ BGP_SOFT_IN_STR)
DEFUN (clear_bgp_as_in_prefix_filter,
clear_bgp_as_in_prefix_filter_cmd,
@@ -6484,7 +7297,7 @@ DEFUN (clear_bgp_as_in_prefix_filter,
CLEAR_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
@@ -6498,7 +7311,7 @@ ALIAS (clear_bgp_as_in_prefix_filter,
BGP_STR
"Address family\n"
"Clear peers with the AS number\n"
- "Soft reconfig inbound update\n"
+ BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n")
/* Both soft-reconfiguration */
@@ -6509,7 +7322,7 @@ DEFUN (clear_ip_bgp_all_soft,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
@@ -6528,7 +7341,7 @@ ALIAS (clear_ip_bgp_all_soft,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
DEFUN (clear_ip_bgp_all_ipv4_soft,
@@ -6541,7 +7354,7 @@ DEFUN (clear_ip_bgp_all_ipv4_soft,
"Address family\n"
"Address Family Modifier\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
@@ -6563,7 +7376,7 @@ DEFUN (clear_ip_bgp_instance_all_ipv4_soft,
"Address family\n"
"Address Family Modifier\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
@@ -6582,7 +7395,7 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft,
"Clear all peers\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6609,7 +7422,7 @@ DEFUN (clear_bgp_all_soft,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
@@ -6627,7 +7440,7 @@ ALIAS (clear_bgp_all_soft,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
ALIAS (clear_bgp_all_soft,
clear_bgp_ipv6_all_soft_cmd,
@@ -6636,7 +7449,7 @@ ALIAS (clear_bgp_all_soft,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
DEFUN (clear_ip_bgp_peer_soft,
clear_ip_bgp_peer_soft_cmd,
@@ -6645,7 +7458,7 @@ DEFUN (clear_ip_bgp_peer_soft,
IP_STR
BGP_STR
"BGP neighbor address to clear\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6661,7 +7474,7 @@ DEFUN (clear_ip_bgp_peer_ipv4_soft,
"Address family\n"
"Address Family Modifier\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
@@ -6680,7 +7493,7 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft,
"BGP neighbor address to clear\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6703,12 +7516,13 @@ DEFUN (clear_ip_bgp_peer_encap_soft,
DEFUN (clear_bgp_peer_soft,
clear_bgp_peer_soft_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) soft",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) soft",
CLEAR_STR
BGP_STR
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6716,13 +7530,14 @@ DEFUN (clear_bgp_peer_soft,
ALIAS (clear_bgp_peer_soft,
clear_bgp_ipv6_peer_soft_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) soft",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_STR)
DEFUN (clear_ip_bgp_peer_group_soft,
clear_ip_bgp_peer_group_soft_cmd,
@@ -6732,7 +7547,7 @@ DEFUN (clear_ip_bgp_peer_group_soft,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6749,7 +7564,7 @@ DEFUN (clear_ip_bgp_peer_group_ipv4_soft,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
@@ -6766,7 +7581,7 @@ DEFUN (clear_bgp_peer_group_soft,
BGP_STR
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6780,7 +7595,7 @@ ALIAS (clear_bgp_peer_group_soft,
"Address family\n"
"Clear all members of peer-group\n"
"BGP peer-group name\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
DEFUN (clear_ip_bgp_external_soft,
clear_ip_bgp_external_soft_cmd,
@@ -6789,7 +7604,7 @@ DEFUN (clear_ip_bgp_external_soft,
IP_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
BGP_CLEAR_SOFT_BOTH, NULL);
@@ -6805,7 +7620,7 @@ DEFUN (clear_ip_bgp_external_ipv4_soft,
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
@@ -6821,7 +7636,7 @@ DEFUN (clear_bgp_external_soft,
CLEAR_STR
BGP_STR
"Clear all external peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
BGP_CLEAR_SOFT_BOTH, NULL);
@@ -6834,7 +7649,7 @@ ALIAS (clear_bgp_external_soft,
BGP_STR
"Address family\n"
"Clear all external peers\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
DEFUN (clear_ip_bgp_as_soft,
clear_ip_bgp_as_soft_cmd,
@@ -6843,7 +7658,7 @@ DEFUN (clear_ip_bgp_as_soft,
IP_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6859,7 +7674,7 @@ DEFUN (clear_ip_bgp_as_ipv4_soft,
"Address family\n"
"Address Family Modifier\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
@@ -6878,7 +7693,7 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft,
"Clear peers with the AS number\n"
"Address family\n"
"Address Family Modifier\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6905,7 +7720,7 @@ DEFUN (clear_bgp_as_soft,
CLEAR_STR
BGP_STR
"Clear peers with the AS number\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
{
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
BGP_CLEAR_SOFT_BOTH, argv[0]);
@@ -6918,7 +7733,7 @@ ALIAS (clear_bgp_as_soft,
BGP_STR
"Address family\n"
"Clear peers with the AS number\n"
- "Soft reconfig\n")
+ BGP_SOFT_STR)
/* RS-client soft reconfiguration. */
DEFUN (clear_bgp_all_rsclient,
@@ -6927,7 +7742,7 @@ DEFUN (clear_bgp_all_rsclient,
CLEAR_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig for rsclient RIB\n")
+ BGP_SOFT_RSCLIENT_RIB_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
@@ -6944,7 +7759,7 @@ ALIAS (clear_bgp_all_rsclient,
BGP_STR
"Address family\n"
"Clear all peers\n"
- "Soft reconfig for rsclient RIB\n")
+ BGP_SOFT_RSCLIENT_RIB_STR)
ALIAS (clear_bgp_all_rsclient,
clear_bgp_instance_all_rsclient_cmd,
@@ -6954,7 +7769,7 @@ ALIAS (clear_bgp_all_rsclient,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig for rsclient RIB\n")
+ BGP_SOFT_RSCLIENT_RIB_STR)
ALIAS (clear_bgp_all_rsclient,
clear_bgp_ipv6_instance_all_rsclient_cmd,
@@ -6965,7 +7780,7 @@ ALIAS (clear_bgp_all_rsclient,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig for rsclient RIB\n")
+ BGP_SOFT_RSCLIENT_RIB_STR)
DEFUN (clear_ip_bgp_all_rsclient,
clear_ip_bgp_all_rsclient_cmd,
@@ -6974,7 +7789,7 @@ DEFUN (clear_ip_bgp_all_rsclient,
IP_STR
BGP_STR
"Clear all peers\n"
- "Soft reconfig for rsclient RIB\n")
+ BGP_SOFT_RSCLIENT_RIB_STR)
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
@@ -6993,16 +7808,17 @@ ALIAS (clear_ip_bgp_all_rsclient,
"BGP view\n"
"view name\n"
"Clear all peers\n"
- "Soft reconfig for rsclient RIB\n")
+ BGP_SOFT_RSCLIENT_RIB_STR)
DEFUN (clear_bgp_peer_rsclient,
clear_bgp_peer_rsclient_cmd,
- "clear bgp (A.B.C.D|X:X::X:X) rsclient",
+ "clear bgp (A.B.C.D|X:X::X:X|WORD) rsclient",
CLEAR_STR
BGP_STR
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig for rsclient RIB\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_RSCLIENT_RIB_STR)
{
if (argc == 2)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_peer,
@@ -7014,28 +7830,30 @@ DEFUN (clear_bgp_peer_rsclient,
ALIAS (clear_bgp_peer_rsclient,
clear_bgp_ipv6_peer_rsclient_cmd,
- "clear bgp ipv6 (A.B.C.D|X:X::X:X) rsclient",
+ "clear bgp ipv6 (A.B.C.D|X:X::X:X|WORD) rsclient",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig for rsclient RIB\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_RSCLIENT_RIB_STR)
ALIAS (clear_bgp_peer_rsclient,
clear_bgp_instance_peer_rsclient_cmd,
- "clear bgp view WORD (A.B.C.D|X:X::X:X) rsclient",
+ "clear bgp view WORD (A.B.C.D|X:X::X:X|WORD) rsclient",
CLEAR_STR
BGP_STR
"BGP view\n"
"view name\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig for rsclient RIB\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_RSCLIENT_RIB_STR)
ALIAS (clear_bgp_peer_rsclient,
clear_bgp_ipv6_instance_peer_rsclient_cmd,
- "clear bgp ipv6 view WORD (A.B.C.D|X:X::X:X) rsclient",
+ "clear bgp ipv6 view WORD (A.B.C.D|X:X::X:X|WORD) rsclient",
CLEAR_STR
BGP_STR
"Address family\n"
@@ -7043,17 +7861,19 @@ ALIAS (clear_bgp_peer_rsclient,
"view name\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig for rsclient RIB\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_RSCLIENT_RIB_STR)
DEFUN (clear_ip_bgp_peer_rsclient,
clear_ip_bgp_peer_rsclient_cmd,
- "clear ip bgp (A.B.C.D|X:X::X:X) rsclient",
+ "clear ip bgp (A.B.C.D|X:X::X:X|WORD) rsclient",
CLEAR_STR
IP_STR
BGP_STR
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig for rsclient RIB\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_RSCLIENT_RIB_STR)
{
if (argc == 2)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_peer,
@@ -7065,7 +7885,7 @@ DEFUN (clear_ip_bgp_peer_rsclient,
ALIAS (clear_ip_bgp_peer_rsclient,
clear_ip_bgp_instance_peer_rsclient_cmd,
- "clear ip bgp view WORD (A.B.C.D|X:X::X:X) rsclient",
+ "clear ip bgp view WORD (A.B.C.D|X:X::X:X|WORD) rsclient",
CLEAR_STR
IP_STR
BGP_STR
@@ -7073,7 +7893,8 @@ ALIAS (clear_ip_bgp_peer_rsclient,
"view name\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
- "Soft reconfig for rsclient RIB\n")
+ "BGP neighbor on interface to clear\n"
+ BGP_SOFT_RSCLIENT_RIB_STR)
DEFUN (show_bgp_views,
show_bgp_views_cmd,
@@ -7252,6 +8073,9 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
if (peer->afc[afi][safi])
{
if (!count)
@@ -7263,6 +8087,39 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
vty_out (vty,
"BGP router identifier %s, local AS number %u%s",
inet_ntoa (bgp->router_id), bgp->as, VTY_NEWLINE);
+ if (bgp_update_delay_configured(bgp))
+ {
+ vty_out (vty, "Read-only mode update-delay limit: %d seconds%s",
+ bgp->v_update_delay, VTY_NEWLINE);
+ if (bgp->v_update_delay != bgp->v_establish_wait)
+ vty_out (vty, " Establish wait: %d seconds%s",
+ bgp->v_establish_wait, VTY_NEWLINE);
+ if (bgp_update_delay_active(bgp))
+ {
+ vty_out (vty, " First neighbor established: %s%s",
+ bgp->update_delay_begin_time, VTY_NEWLINE);
+ vty_out (vty, " Delay in progress%s", VTY_NEWLINE);
+ }
+ else
+ {
+ if (bgp->update_delay_over)
+ {
+ vty_out (vty, " First neighbor established: %s%s",
+ bgp->update_delay_begin_time, VTY_NEWLINE);
+ vty_out (vty, " Best-paths resumed: %s%s",
+ bgp->update_delay_end_time, VTY_NEWLINE);
+ vty_out (vty, " zebra update resumed: %s%s",
+ bgp->update_delay_zebra_resume_time, VTY_NEWLINE);
+ vty_out (vty, " peers update resumed: %s%s",
+ bgp->update_delay_peers_resume_time, VTY_NEWLINE);
+ }
+ }
+ }
+
+ if (bgp_maxmed_onstartup_configured(bgp) && bgp->maxmed_active)
+ vty_out (vty, "Max-med on-startup active%s", VTY_NEWLINE);
+ if (bgp->v_maxmed_admin)
+ vty_out (vty, "Max-med administrative active%s", VTY_NEWLINE);
ents = bgp_table_count (bgp->rib[afi][safi]);
vty_out (vty, "RIB entries %ld, using %s of memory%s", ents,
@@ -7308,14 +8165,16 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
vty_out (vty, "4 ");
- vty_out (vty, "%5u %7d %7d %8d %4d %4lu ",
+ vty_out (vty, "%5u %7d %7d %8d %4d %4d ",
peer->as,
peer->open_in + peer->update_in + peer->keepalive_in
+ peer->notify_in + peer->refresh_in + peer->dynamic_cap_in,
peer->open_out + peer->update_out + peer->keepalive_out
+ peer->notify_out + peer->refresh_out
+ peer->dynamic_cap_out,
- 0, 0, (unsigned long) peer->obuf->count);
+ 0, 0,
+ peer->sync[afi][safi]->update.count +
+ peer->sync[afi][safi]->withdraw.count);
vty_out (vty, "%8s",
peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
@@ -7344,6 +8203,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
else
vty_out (vty, "No %s neighbor is configured%s",
afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -7983,9 +8843,16 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi)
vty_out (vty, " Route-Server Client%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
vty_out (vty, " Inbound soft reconfiguration allowed%s", VTY_NEWLINE);
- if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
- vty_out (vty, " Private AS number removed from updates to this neighbor%s", VTY_NEWLINE);
- if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF))
+ if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ vty_out (vty, " Private AS numbers replaced in updates to this neighbor%s", VTY_NEWLINE);
+ else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
+ vty_out (vty, " Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE);
+
+ if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
+ vty_out (vty, " Override ASNs in outbound updates if aspath equals remote-as%s", VTY_NEWLINE);
+
+ if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) ||
+ CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF_ALL))
vty_out (vty, " NEXT_HOP is always this router%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED))
vty_out (vty, " AS_PATH is propagated unchanged to this neighbor%s", VTY_NEWLINE);
@@ -8122,15 +8989,21 @@ static void
bgp_show_peer (struct vty *vty, struct peer *p)
{
struct bgp *bgp;
- char buf1[BUFSIZ];
+ char buf1[BUFSIZ], buf[SU_ADDRSTRLEN];
char timebuf[BGP_UPTIME_LEN];
afi_t afi;
safi_t safi;
+ u_int16_t i;
+ u_char *msg;
bgp = p->bgp;
- /* Configured IP address. */
- vty_out (vty, "BGP neighbor is %s, ", p->host);
+ if (p->conf_if) /* Configured interface name. */
+ vty_out (vty, "BGP neighbor on %s: %s, ", p->conf_if,
+ BGP_PEER_SU_UNSPEC(p) ? "None" :
+ sockunion2str (&p->su, buf, SU_ADDRSTRLEN));
+ else /* Configured IP address. */
+ vty_out (vty, "BGP neighbor is %s, ", p->host);
vty_out (vty, "remote AS %u, ", p->as);
vty_out (vty, "local AS %u%s%s, ",
p->change_local_as ? p->change_local_as : p->local_as,
@@ -8183,9 +9056,11 @@ bgp_show_peer (struct vty *vty, struct peer *p)
/* read timer */
vty_out (vty, " Last read %s", peer_uptime (p->readtime, timebuf, BGP_UPTIME_LEN));
+ vty_out (vty, ", Last write %s%s",
+ peer_uptime (p->last_write, timebuf, BGP_UPTIME_LEN), VTY_NEWLINE);
/* Configured timer values. */
- vty_out (vty, ", hold time is %d, keepalive interval is %d seconds%s",
+ vty_out (vty, " Hold time is %d, keepalive interval is %d seconds%s",
p->v_holdtime, p->v_keepalive, VTY_NEWLINE);
if (CHECK_FLAG (p->config, PEER_CONFIG_TIMER))
{
@@ -8404,12 +9279,33 @@ bgp_show_peer (struct vty *vty, struct peer *p)
p->established, p->dropped,
VTY_NEWLINE);
- if (! p->dropped)
+ if (! p->last_reset)
vty_out (vty, " Last reset never%s", VTY_NEWLINE);
else
- vty_out (vty, " Last reset %s, due to %s%s",
- peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN),
- peer_down_str[(int) p->last_reset], VTY_NEWLINE);
+ {
+ vty_out (vty, " Last reset %s, due to %s%s",
+ peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN),
+ peer_down_str[(int) p->last_reset], VTY_NEWLINE);
+
+ if (p->last_reset_cause_size)
+ {
+ msg = p->last_reset_cause;
+ vty_out(vty, " Message received that caused BGP to send a NOTIFICATION:%s ", VTY_NEWLINE);
+ for (i = 1; i <= p->last_reset_cause_size; i++)
+ {
+ vty_out(vty, "%02X", *msg++);
+
+ if (i != p->last_reset_cause_size)
+ {
+ if (i % 16 == 0)
+ vty_out(vty, "%s ", VTY_NEWLINE);
+ else if (i % 4 == 0)
+ vty_out(vty, " ");
+ }
+ }
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
+ }
if (CHECK_FLAG (p->sflags, PEER_STATUS_PREFIX_OVERFLOW))
{
@@ -8488,8 +9384,12 @@ bgp_show_peer (struct vty *vty, struct peer *p)
if (p->t_connect)
vty_out (vty, "Next connect timer due in %ld seconds%s",
thread_timer_remain_second (p->t_connect), VTY_NEWLINE);
-
- vty_out (vty, "Read thread: %s Write thread: %s%s",
+ if (p->t_routeadv)
+ vty_out (vty, "MRAI (interval %d) timer expires in %ld seconds%s",
+ p->v_routeadv, thread_timer_remain_second (p->t_routeadv),
+ VTY_NEWLINE);
+
+ vty_out (vty, "Read thread: %s Write thread: %s%s",
p->t_read ? "on" : "off",
p->t_write ? "on" : "off",
VTY_NEWLINE);
@@ -8503,7 +9403,7 @@ bgp_show_peer (struct vty *vty, struct peer *p)
static int
bgp_show_neighbor (struct vty *vty, struct bgp *bgp,
- enum show_type type, union sockunion *su)
+ enum show_type type, union sockunion *su, const char *conf_if)
{
struct listnode *node, *nnode;
struct peer *peer;
@@ -8511,17 +9411,31 @@ bgp_show_neighbor (struct vty *vty, struct bgp *bgp,
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
switch (type)
{
case show_all:
bgp_show_peer (vty, peer);
break;
case show_peer:
- if (sockunion_same (&peer->su, su))
- {
- find = 1;
- bgp_show_peer (vty, peer);
- }
+ if (conf_if)
+ {
+ if (peer->conf_if && !strcmp(peer->conf_if, conf_if))
+ {
+ find = 1;
+ bgp_show_peer (vty, peer);
+ }
+ }
+ else
+ {
+ if (sockunion_same (&peer->su, su))
+ {
+ find = 1;
+ bgp_show_peer (vty, peer);
+ }
+ }
break;
}
}
@@ -8540,35 +9454,35 @@ bgp_show_neighbor_vty (struct vty *vty, const char *name,
struct bgp *bgp;
union sockunion su;
- if (ip_str)
- {
- ret = str2sockunion (ip_str, &su);
- if (ret < 0)
- {
- vty_out (vty, "%% Malformed address: %s%s", ip_str, VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
-
if (name)
{
bgp = bgp_lookup_by_name (name);
-
if (! bgp)
{
vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
return CMD_WARNING;
}
-
- bgp_show_neighbor (vty, bgp, type, &su);
-
- return CMD_SUCCESS;
}
-
- bgp = bgp_get_default ();
+ else
+ {
+ bgp = bgp_get_default ();
+ }
if (bgp)
- bgp_show_neighbor (vty, bgp, type, &su);
+ {
+ if (ip_str)
+ {
+ ret = str2sockunion (ip_str, &su);
+ if (ret < 0)
+ bgp_show_neighbor (vty, bgp, type, NULL, ip_str);
+ else
+ bgp_show_neighbor (vty, bgp, type, &su, NULL);
+ }
+ else
+ {
+ bgp_show_neighbor (vty, bgp, type, NULL, NULL);
+ }
+ }
return CMD_SUCCESS;
}
@@ -8626,20 +9540,21 @@ ALIAS (show_ip_bgp_neighbors,
DEFUN (show_ip_bgp_neighbors_peer,
show_ip_bgp_neighbors_peer_cmd,
- "show ip bgp neighbors (A.B.C.D|X:X::X:X)",
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
IP_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
{
return bgp_show_neighbor_vty (vty, NULL, show_peer, argv[argc - 1]);
}
ALIAS (show_ip_bgp_neighbors_peer,
show_ip_bgp_ipv4_neighbors_peer_cmd,
- "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X)",
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
IP_STR
BGP_STR
@@ -8648,7 +9563,8 @@ ALIAS (show_ip_bgp_neighbors_peer,
"Address Family modifier\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
ALIAS (show_ip_bgp_neighbors_peer,
show_ip_bgp_vpnv4_all_neighbors_peer_cmd,
@@ -8674,13 +9590,14 @@ ALIAS (show_ip_bgp_neighbors_peer,
ALIAS (show_ip_bgp_neighbors_peer,
show_bgp_ipv6_neighbors_peer_cmd,
- "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X)",
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
DEFUN (show_ip_bgp_instance_neighbors,
show_ip_bgp_instance_neighbors_cmd,
@@ -8707,7 +9624,7 @@ ALIAS (show_ip_bgp_instance_neighbors,
DEFUN (show_ip_bgp_instance_neighbors_peer,
show_ip_bgp_instance_neighbors_peer_cmd,
- "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X)",
+ "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
IP_STR
BGP_STR
@@ -8715,7 +9632,8 @@ DEFUN (show_ip_bgp_instance_neighbors_peer,
"View name\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
{
return bgp_show_neighbor_vty (vty, argv[0], show_peer, argv[1]);
}
@@ -8765,12 +9683,13 @@ DEFUN (show_bgp_neighbors,
DEFUN (show_bgp_neighbors_peer,
show_bgp_neighbors_peer_cmd,
- "show bgp neighbors (A.B.C.D|X:X::X:X)",
+ "show bgp neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
{
return bgp_show_neighbor_vty (vty, NULL, show_peer, argv[argc - 1]);
}
@@ -8789,21 +9708,22 @@ DEFUN (show_bgp_instance_neighbors,
DEFUN (show_bgp_instance_neighbors_peer,
show_bgp_instance_neighbors_peer_cmd,
- "show bgp view WORD neighbors (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
"View name\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
{
return bgp_show_neighbor_vty (vty, argv[0], show_peer, argv[1]);
}
ALIAS (show_bgp_instance_neighbors_peer,
show_bgp_instance_ipv6_neighbors_peer_cmd,
- "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X)",
+ "show bgp view WORD ipv6 neighbors (A.B.C.D|X:X::X:X|WORD)",
SHOW_STR
BGP_STR
"BGP view\n"
@@ -8811,7 +9731,8 @@ ALIAS (show_bgp_instance_neighbors_peer,
"Address family\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
- "Neighbor to display information about\n")
+ "Neighbor to display information about\n"
+ "Neighbor on bgp configured interface\n")
/* Show BGP's AS paths internal data. There are both `show ip bgp
paths' and `show ip mbgp paths'. Those functions results are the
@@ -9407,7 +10328,7 @@ DEFUN (no_bgp_redistribute_ipv4,
return bgp_redistribute_unset (vty->index, AFI_IP, type);
}
-DEFUN (no_bgp_redistribute_ipv4_rmap,
+ALIAS (no_bgp_redistribute_ipv4,
no_bgp_redistribute_ipv4_rmap_cmd,
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD",
NO_STR
@@ -9415,21 +10336,8 @@ DEFUN (no_bgp_redistribute_ipv4_rmap,
QUAGGA_IP_REDIST_HELP_STR_BGPD
"Route map reference\n"
"Pointer to route-map entries\n")
-{
- int type;
-
- type = proto_redistnum (AFI_IP, argv[0]);
- if (type < 0 || type == ZEBRA_ROUTE_BGP)
- {
- vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- bgp_redistribute_routemap_unset (vty->index, AFI_IP, type);
- return CMD_SUCCESS;
-}
-DEFUN (no_bgp_redistribute_ipv4_metric,
+ALIAS (no_bgp_redistribute_ipv4,
no_bgp_redistribute_ipv4_metric_cmd,
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295>",
NO_STR
@@ -9437,21 +10345,8 @@ DEFUN (no_bgp_redistribute_ipv4_metric,
QUAGGA_IP_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n")
-{
- int type;
- type = proto_redistnum (AFI_IP, argv[0]);
- if (type < 0 || type == ZEBRA_ROUTE_BGP)
- {
- vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- bgp_redistribute_metric_unset (vty->index, AFI_IP, type);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
+ALIAS (no_bgp_redistribute_ipv4,
no_bgp_redistribute_ipv4_rmap_metric_cmd,
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>",
NO_STR
@@ -9461,22 +10356,8 @@ DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
"Pointer to route-map entries\n"
"Metric for redistributed routes\n"
"Default metric\n")
-{
- int type;
- type = proto_redistnum (AFI_IP, argv[0]);
- if (type < 0 || type == ZEBRA_ROUTE_BGP)
- {
- vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- bgp_redistribute_metric_unset (vty->index, AFI_IP, type);
- bgp_redistribute_routemap_unset (vty->index, AFI_IP, type);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_bgp_redistribute_ipv4_rmap_metric,
+ALIAS (no_bgp_redistribute_ipv4,
no_bgp_redistribute_ipv4_metric_rmap_cmd,
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD",
NO_STR
@@ -9620,7 +10501,7 @@ DEFUN (no_bgp_redistribute_ipv6,
return bgp_redistribute_unset (vty->index, AFI_IP6, type);
}
-DEFUN (no_bgp_redistribute_ipv6_rmap,
+ALIAS (no_bgp_redistribute_ipv6,
no_bgp_redistribute_ipv6_rmap_cmd,
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD",
NO_STR
@@ -9628,21 +10509,8 @@ DEFUN (no_bgp_redistribute_ipv6_rmap,
QUAGGA_IP6_REDIST_HELP_STR_BGPD
"Route map reference\n"
"Pointer to route-map entries\n")
-{
- int type;
- type = proto_redistnum (AFI_IP6, argv[0]);
- if (type < 0 || type == ZEBRA_ROUTE_BGP)
- {
- vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- bgp_redistribute_routemap_unset (vty->index, AFI_IP6, type);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_bgp_redistribute_ipv6_metric,
+ALIAS (no_bgp_redistribute_ipv6,
no_bgp_redistribute_ipv6_metric_cmd,
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295>",
NO_STR
@@ -9650,21 +10518,8 @@ DEFUN (no_bgp_redistribute_ipv6_metric,
QUAGGA_IP6_REDIST_HELP_STR_BGPD
"Metric for redistributed routes\n"
"Default metric\n")
-{
- int type;
-
- type = proto_redistnum (AFI_IP6, argv[0]);
- if (type < 0 || type == ZEBRA_ROUTE_BGP)
- {
- vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- bgp_redistribute_metric_unset (vty->index, AFI_IP6, type);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
+ALIAS (no_bgp_redistribute_ipv6,
no_bgp_redistribute_ipv6_rmap_metric_cmd,
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>",
NO_STR
@@ -9674,22 +10529,8 @@ DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
"Pointer to route-map entries\n"
"Metric for redistributed routes\n"
"Default metric\n")
-{
- int type;
-
- type = proto_redistnum (AFI_IP6, argv[0]);
- if (type < 0 || type == ZEBRA_ROUTE_BGP)
- {
- vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- bgp_redistribute_metric_unset (vty->index, AFI_IP6, type);
- bgp_redistribute_routemap_unset (vty->index, AFI_IP6, type);
- return CMD_SUCCESS;
-}
-
-ALIAS (no_bgp_redistribute_ipv6_rmap_metric,
+ALIAS (no_bgp_redistribute_ipv6,
no_bgp_redistribute_ipv6_metric_rmap_cmd,
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD",
NO_STR
@@ -9864,6 +10705,26 @@ bgp_vty_init (void)
install_element (BGP_NODE, &bgp_confederation_peers_cmd);
install_element (BGP_NODE, &no_bgp_confederation_peers_cmd);
+ /* bgp max-med command */
+ install_element (BGP_NODE, &bgp_maxmed_admin_cmd);
+ install_element (BGP_NODE, &no_bgp_maxmed_admin_cmd);
+ install_element (BGP_NODE, &bgp_maxmed_admin_medv_cmd);
+ install_element (BGP_NODE, &no_bgp_maxmed_admin_medv_cmd);
+ install_element (BGP_NODE, &bgp_maxmed_onstartup_cmd);
+ install_element (BGP_NODE, &no_bgp_maxmed_onstartup_cmd);
+ install_element (BGP_NODE, &no_bgp_maxmed_onstartup_period_cmd);
+ install_element (BGP_NODE, &bgp_maxmed_onstartup_medv_cmd);
+ install_element (BGP_NODE, &no_bgp_maxmed_onstartup_period_medv_cmd);
+
+ /* bgp update-delay command */
+ install_element (BGP_NODE, &bgp_update_delay_cmd);
+ install_element (BGP_NODE, &no_bgp_update_delay_cmd);
+ install_element (BGP_NODE, &bgp_update_delay_establish_wait_cmd);
+ install_element (BGP_NODE, &no_bgp_update_delay_establish_wait_cmd);
+
+ install_element (BGP_NODE, &bgp_wpkt_quanta_cmd);
+ install_element (BGP_NODE, &no_bgp_wpkt_quanta_cmd);
+
/* "maximum-paths" commands. */
install_element (BGP_NODE, &bgp_maxpaths_cmd);
install_element (BGP_NODE, &no_bgp_maxpaths_cmd);
@@ -9871,18 +10732,34 @@ bgp_vty_init (void)
install_element (BGP_IPV4_NODE, &bgp_maxpaths_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_arg_cmd);
+ install_element (BGP_IPV6_NODE, &bgp_maxpaths_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_arg_cmd);
install_element (BGP_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cmd);
install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
+ install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd);
+ install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
+ install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd);
/* "timers bgp" commands. */
install_element (BGP_NODE, &bgp_timers_cmd);
install_element (BGP_NODE, &no_bgp_timers_cmd);
install_element (BGP_NODE, &no_bgp_timers_arg_cmd);
+ /* route-map delay-timer commands */
+ install_element (BGP_NODE, &bgp_set_route_map_delay_timer_cmd);
+ install_element (BGP_NODE, &no_bgp_set_route_map_delay_timer_cmd);
+
/* "bgp client-to-client reflection" commands */
install_element (BGP_NODE, &no_bgp_client_to_client_reflection_cmd);
install_element (BGP_NODE, &bgp_client_to_client_reflection_cmd);
@@ -9951,15 +10828,21 @@ bgp_vty_init (void)
install_element (BGP_NODE, &no_bgp_default_local_preference_cmd);
install_element (BGP_NODE, &no_bgp_default_local_preference_val_cmd);
+ /* bgp ibgp-allow-policy-mods command */
+ install_element (BGP_NODE, &bgp_rr_allow_outbound_policy_cmd);
+ install_element (BGP_NODE, &no_bgp_rr_allow_outbound_policy_cmd);
+
/* "neighbor remote-as" commands. */
install_element (BGP_NODE, &neighbor_remote_as_cmd);
+ install_element (BGP_NODE, &neighbor_interface_config_cmd);
install_element (BGP_NODE, &no_neighbor_cmd);
install_element (BGP_NODE, &no_neighbor_remote_as_cmd);
+ install_element (BGP_NODE, &no_neighbor_interface_config_cmd);
/* "neighbor peer-group" commands. */
install_element (BGP_NODE, &neighbor_peer_group_cmd);
install_element (BGP_NODE, &no_neighbor_peer_group_cmd);
- install_element (BGP_NODE, &no_neighbor_peer_group_remote_as_cmd);
+ install_element (BGP_NODE, &no_neighbor_interface_peer_group_remote_as_cmd);
/* "neighbor local-as" commands. */
install_element (BGP_NODE, &neighbor_local_as_cmd);
@@ -10270,17 +11153,61 @@ bgp_vty_init (void)
install_element (BGP_ENCAPV6_NODE, &neighbor_nexthop_self_cmd);
install_element (BGP_ENCAPV6_NODE, &no_neighbor_nexthop_self_cmd);
+ /* "neighbor as-override" commands. */
+ install_element (BGP_NODE, &neighbor_as_override_cmd);
+ install_element (BGP_NODE, &no_neighbor_as_override_cmd);
+ install_element (BGP_IPV4_NODE, &neighbor_as_override_cmd);
+ install_element (BGP_IPV4_NODE, &no_neighbor_as_override_cmd);
+ install_element (BGP_IPV4M_NODE, &neighbor_as_override_cmd);
+ install_element (BGP_IPV4M_NODE, &no_neighbor_as_override_cmd);
+ install_element (BGP_IPV6_NODE, &neighbor_as_override_cmd);
+ install_element (BGP_IPV6_NODE, &no_neighbor_as_override_cmd);
+ install_element (BGP_IPV6M_NODE, &neighbor_as_override_cmd);
+ install_element (BGP_IPV6M_NODE, &no_neighbor_as_override_cmd);
+ install_element (BGP_VPNV4_NODE, &neighbor_as_override_cmd);
+ install_element (BGP_VPNV4_NODE, &no_neighbor_as_override_cmd);
+
/* "neighbor remove-private-AS" commands. */
install_element (BGP_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element (BGP_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element (BGP_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element (BGP_NODE, &neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element (BGP_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_cmd);
@@ -10289,6 +11216,12 @@ bgp_vty_init (void)
install_element (BGP_ENCAP_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_ENCAPV6_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_ENCAPV6_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
/* "neighbor send-community" commands.*/
install_element (BGP_NODE, &neighbor_send_community_cmd);
@@ -10856,6 +11789,10 @@ bgp_vty_init (void)
install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_cmd);
install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_prefix_filter_cmd);
+ /* clear ip bgp prefix */
+ install_element (ENABLE_NODE, &clear_ip_bgp_prefix_cmd);
+ install_element (ENABLE_NODE, &clear_bgp_ipv6_safi_prefix_cmd);
+
/* "clear ip bgp neighbor soft out" */
install_element (ENABLE_NODE, &clear_ip_bgp_all_soft_out_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_soft_out_cmd);
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 7329c5fd..fdbbb782 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -21,10 +21,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#ifndef _QUAGGA_BGP_VTY_H
#define _QUAGGA_BGP_VTY_H
+#include "bgpd/bgpd.h"
+
#define CMD_AS_RANGE "<1-4294967295>"
extern void bgp_vty_init (void);
extern const char *afi_safi_print (afi_t, safi_t);
+extern int bgp_config_write_update_delay (struct vty *, struct bgp *);
+extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
extern int
bgp_parse_afi(const char *str, afi_t *afi);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d0b9216a..92883d5d 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_mpath.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_nht.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
@@ -46,6 +48,44 @@ struct in_addr router_id_zebra;
/* Growable buffer for nexthops sent to zebra */
struct stream *bgp_nexthop_buf = NULL;
+struct stream *bgp_ifindices_buf = NULL;
+
+/* These array buffers are used in making a copy of the attributes for
+ route-map apply. Arrays are being used here to minimize mallocs and
+ frees for the temporary copy of the attributes.
+ Given the zapi api expects the nexthop buffer to contain pointer to
+ pointers for nexthops, we couldnt have used a single nexthop variable
+ on the stack, hence we had two options:
+ 1. maintain a linked-list and free it after zapi_*_route call
+ 2. use an array to avoid number of mallocs.
+ Number of supported next-hops are finite, use of arrays should be ok. */
+struct attr attr_cp[BGP_MAXIMUM_MAXPATHS];
+struct attr_extra attr_extra_cp[BGP_MAXIMUM_MAXPATHS];
+int attr_index = 0;
+
+/* Once per address-family initialization of the attribute array */
+#define BGP_INFO_ATTR_BUF_INIT()\
+do {\
+ memset(attr_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr));\
+ memset(attr_extra_cp, 0, BGP_MAXIMUM_MAXPATHS * sizeof(struct attr_extra));\
+ attr_index = 0;\
+} while (0)
+
+#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\
+do { \
+ *info_dst = *info_src; \
+ assert(attr_index != BGP_MAXIMUM_MAXPATHS);\
+ attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \
+ bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \
+ bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \
+ info_dst->attr = &attr_cp[attr_index]; \
+ attr_index++;\
+} while (0)
+
+#define BGP_INFO_ATTR_BUF_FREE(info) \
+do { \
+ bgp_attr_deep_free(info->attr); \
+} while (0)
/* Router-id update message from zebra. */
static int
@@ -58,7 +98,7 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
zebra_router_id_update_read(zclient->ibuf,&router_id);
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (BGP_DEBUG (zebra, ZEBRA))
{
char buf[128];
prefix2str(&router_id, buf, sizeof(buf));
@@ -76,6 +116,55 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
return 0;
}
+/* Nexthop update message from zebra. */
+static int
+bgp_read_nexthop_update (int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ bgp_parse_nexthop_update();
+ return 0;
+}
+
+static void
+bgp_nbr_connected_add (struct nbr_connected *ifc)
+{
+ struct listnode *node, *nnode, *mnode;
+ struct bgp *bgp;
+ struct peer *peer;
+
+ for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
+ {
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ {
+ if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
+ {
+ if (peer_active(peer))
+ BGP_EVENT_ADD (peer, BGP_Stop);
+ BGP_EVENT_ADD (peer, BGP_Start);
+ }
+ }
+ }
+}
+
+static void
+bgp_nbr_connected_delete (struct nbr_connected *ifc)
+{
+ struct listnode *node, *nnode, *mnode;
+ struct bgp *bgp;
+ struct peer *peer;
+
+ for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
+ {
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ {
+ if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
+ {
+ BGP_EVENT_ADD (peer, BGP_Stop);
+ }
+ }
+ }
+}
+
/* Inteface addition message from zebra. */
static int
bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
@@ -85,7 +174,7 @@ bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
- if (BGP_DEBUG(zebra, ZEBRA) && ifp)
+ if (BGP_DEBUG (zebra, ZEBRA) && ifp)
zlog_debug("Zebra rcvd: interface add %s", ifp->name);
return 0;
@@ -102,7 +191,7 @@ bgp_interface_delete (int command, struct zclient *zclient,
ifp = zebra_interface_state_read (s, vrf_id);
ifp->ifindex = IFINDEX_INTERNAL;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
return 0;
@@ -115,6 +204,7 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
struct stream *s;
struct interface *ifp;
struct connected *c;
+ struct nbr_connected *nc;
struct listnode *node, *nnode;
s = zclient->ibuf;
@@ -123,12 +213,15 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
if (! ifp)
return 0;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Zebra rcvd: interface %s up", ifp->name);
for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
bgp_connected_add (c);
+ for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc))
+ bgp_nbr_connected_add (nc);
+
return 0;
}
@@ -139,6 +232,7 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
struct stream *s;
struct interface *ifp;
struct connected *c;
+ struct nbr_connected *nc;
struct listnode *node, *nnode;
s = zclient->ibuf;
@@ -146,12 +240,15 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
if (! ifp)
return 0;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Zebra rcvd: interface %s down", ifp->name);
for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
bgp_connected_delete (c);
+ for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc))
+ bgp_nbr_connected_delete (nc);
+
/* Fast external-failover */
{
struct listnode *mnode;
@@ -188,7 +285,7 @@ bgp_interface_address_add (int command, struct zclient *zclient,
if (ifc == NULL)
return 0;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (bgp_debug_zebra(ifc->address))
{
char buf[128];
prefix2str(ifc->address, buf, sizeof(buf));
@@ -213,7 +310,7 @@ bgp_interface_address_delete (int command, struct zclient *zclient,
if (ifc == NULL)
return 0;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (bgp_debug_zebra(ifc->address))
{
char buf[128];
prefix2str(ifc->address, buf, sizeof(buf));
@@ -229,6 +326,58 @@ bgp_interface_address_delete (int command, struct zclient *zclient,
return 0;
}
+static int
+bgp_interface_nbr_address_add (int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct nbr_connected *ifc = NULL;
+
+ ifc = zebra_interface_nbr_address_read (command, zclient->ibuf);
+
+ if (ifc == NULL)
+ return 0;
+
+ if (bgp_debug_zebra(ifc->address))
+ {
+ char buf[128];
+ prefix2str(ifc->address, buf, sizeof(buf));
+ zlog_debug("Zebra rcvd: interface %s nbr address add %s",
+ ifc->ifp->name, buf);
+ }
+
+ if (if_is_operative (ifc->ifp))
+ bgp_nbr_connected_add (ifc);
+
+ return 0;
+}
+
+static int
+bgp_interface_nbr_address_delete (int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct nbr_connected *ifc = NULL;
+
+ ifc = zebra_interface_nbr_address_read (command, zclient->ibuf);
+
+ if (ifc == NULL)
+ return 0;
+
+ if (bgp_debug_zebra(ifc->address))
+ {
+ char buf[128];
+ prefix2str(ifc->address, buf, sizeof(buf));
+ zlog_debug("Zebra rcvd: interface %s nbr address delete %s",
+ ifc->ifp->name, buf);
+ }
+
+ if (if_is_operative (ifc->ifp))
+ bgp_nbr_connected_delete (ifc);
+
+ nbr_connected_free (ifc);
+
+ return 0;
+}
+
/* Zebra route add and delete treatment. */
static int
zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
@@ -239,6 +388,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
struct in_addr nexthop;
struct prefix_ipv4 p;
unsigned char plength = 0;
+ ifindex_t ifindex;
s = zclient->ibuf;
nexthop.s_addr = 0;
@@ -264,7 +414,11 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
{
api.ifindex_num = stream_getc (s);
- stream_getl (s); /* ifindex, unused */
+ ifindex = stream_getl (s); /* ifindex, unused */
+ }
+ else
+ {
+ ifindex = 0;
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
@@ -273,33 +427,40 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
else
api.metric = 0;
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
+ api.tag = stream_getw (s);
+ else
+ api.tag = 0;
+
if (command == ZEBRA_IPV4_ROUTE_ADD)
{
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (bgp_debug_zebra((struct prefix *)&p))
{
char buf[2][INET_ADDRSTRLEN];
- zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
+ zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u tag %d",
zebra_route_string(api.type),
inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
p.prefixlen,
inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
- api.metric);
+ api.metric,
+ api.tag);
}
- bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
- api.metric, api.type);
+ bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex,
+ api.metric, api.type, api.tag);
}
else
{
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (bgp_debug_zebra((struct prefix *)&p))
{
char buf[2][INET_ADDRSTRLEN];
zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d "
- "nexthop %s metric %u",
+ "nexthop %s metric %u tag %d",
zebra_route_string(api.type),
inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
p.prefixlen,
inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
- api.metric);
+ api.metric,
+ api.tag);
}
bgp_redistribute_delete((struct prefix *)&p, api.type);
}
@@ -317,6 +478,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
struct in6_addr nexthop;
struct prefix_ipv6 p;
unsigned char plength = 0;
+ ifindex_t ifindex;
s = zclient->ibuf;
memset (&nexthop, 0, sizeof (struct in6_addr));
@@ -342,7 +504,11 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
{
api.ifindex_num = stream_getc (s);
- stream_getl (s); /* ifindex, unused */
+ ifindex = stream_getl (s); /* ifindex, unused */
+ }
+ else
+ {
+ ifindex = 0;
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
@@ -353,37 +519,44 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
else
api.metric = 0;
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
+ api.tag = stream_getw (s);
+ else
+ api.tag = 0;
+
/* Simply ignore link-local address. */
if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
return 0;
if (command == ZEBRA_IPV6_ROUTE_ADD)
{
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (bgp_debug_zebra((struct prefix *)&p))
{
char buf[2][INET6_ADDRSTRLEN];
- zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
+ zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u tag %d",
zebra_route_string(api.type),
inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
p.prefixlen,
inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
- api.metric);
+ api.metric,
+ api.tag);
}
- bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
- api.metric, api.type);
+ bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex,
+ api.metric, api.type, api.tag);
}
else
{
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (bgp_debug_zebra((struct prefix *)&p))
{
char buf[2][INET6_ADDRSTRLEN];
zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
- "nexthop %s metric %u",
+ "nexthop %s metric %u tag %d",
zebra_route_string(api.type),
inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
p.prefixlen,
inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
- api.metric);
+ api.metric,
+ api.tag);
}
bgp_redistribute_delete ((struct prefix *) &p, api.type);
}
@@ -571,17 +744,22 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
if (local->sa.sa_family == AF_INET)
{
nexthop->v4 = local->sin.sin_addr;
- ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
+ if (peer->update_if)
+ ifp = if_lookup_by_name (peer->update_if);
+ else
+ ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr);
}
if (local->sa.sa_family == AF_INET6)
{
if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
{
- if (peer->ifname)
- ifp = if_lookup_by_name (peer->ifname);
+ if (peer->conf_if || peer->ifname)
+ ifp = if_lookup_by_index (if_nametoindex (peer->conf_if ? peer->conf_if : peer->ifname));
}
+ else if (peer->update_if)
+ ifp = if_lookup_by_name (peer->update_if);
else
- ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
+ ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr);
}
if (!ifp)
@@ -661,14 +839,73 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
return ret;
}
+static struct in6_addr *
+bgp_info_to_ipv6_nexthop (struct bgp_info *info)
+{
+ struct in6_addr *nexthop = NULL;
+
+ /* Only global address nexthop exists. */
+ if (info->attr->extra->mp_nexthop_len == 16)
+ nexthop = &info->attr->extra->mp_nexthop_global;
+
+ /* If both global and link-local address present. */
+ if (info->attr->extra->mp_nexthop_len == 32)
+ {
+ /* Workaround for Cisco's nexthop bug. */
+ if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
+ && info->peer->su_remote->sa.sa_family == AF_INET6)
+ nexthop = &info->peer->su_remote->sin6.sin6_addr;
+ else
+ nexthop = &info->attr->extra->mp_nexthop_local;
+ }
+
+ return nexthop;
+}
+
+static int
+bgp_table_map_apply (struct route_map *map, struct prefix *p,
+ struct bgp_info *info)
+{
+ if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH)
+ return 1;
+
+ if (bgp_debug_zebra(p))
+ {
+ if (p->family == AF_INET)
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra rmap deny: IPv4 route %s/%d nexthop %s",
+ inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET, &info->attr->nexthop, buf[1],
+ sizeof(buf[1])));
+ }
+ if (p->family == AF_INET6)
+ {
+ char buf[2][INET6_ADDRSTRLEN];
+ zlog_debug("Zebra rmap deny: IPv6 route %s/%d nexthop %s",
+ inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET6, bgp_info_to_ipv6_nexthop(info), buf[1],
+ sizeof(buf[1])));
+ }
+ }
+ return 0;
+}
+
void
-bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
+bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
+ afi_t afi, safi_t safi)
{
int flags;
u_char distance;
struct peer *peer;
struct bgp_info *mpinfo;
size_t oldsize, newsize;
+ u_int32_t nhcount, metric;
+ struct bgp_info local_info;
+ struct bgp_info *info_cp = &local_info;
+ u_short tag = 0;
if (zclient->sock < 0)
return;
@@ -676,9 +913,15 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT))
return;
+ if (bgp->main_zebra_update_hold)
+ return;
+
flags = 0;
peer = info->peer;
+ if ((info->attr->extra) && (info->attr->extra->tag != 0))
+ tag = info->attr->extra->tag;
+
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
{
SET_FLAG (flags, ZEBRA_FLAG_IBGP);
@@ -689,46 +932,108 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
- /* resize nexthop buffer size if necessary */
- if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
- (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1)))
- {
- newsize = (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1));
- newsize = stream_resize (bgp_nexthop_buf, newsize);
- if (newsize == oldsize)
- {
- zlog_err ("can't resize nexthop buffer");
- return;
- }
- }
-
- stream_reset (bgp_nexthop_buf);
+ nhcount = 1 + bgp_info_mpath_count (info);
if (p->family == AF_INET)
{
struct zapi_ipv4 api;
struct in_addr *nexthop;
+ char buf[2][INET_ADDRSTRLEN];
+ int valid_nh_count = 0;
+
+ /* resize nexthop buffer size if necessary */
+ if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
+ (sizeof (struct in_addr *) * nhcount))
+ {
+ newsize = (sizeof (struct in_addr *) * nhcount);
+ newsize = stream_resize (bgp_nexthop_buf, newsize);
+ if (newsize == oldsize)
+ {
+ zlog_err ("can't resize nexthop buffer");
+ return;
+ }
+ }
+ stream_reset (bgp_nexthop_buf);
+ nexthop = NULL;
+
+ /* Metric is currently based on the best-path only. */
+ metric = info->attr->med;
+
+ if (bgp->table_map[afi][safi].name)
+ {
+ BGP_INFO_ATTR_BUF_INIT();
+
+ /* Copy info and attributes, so the route-map apply doesn't modify the
+ BGP route info. */
+ BGP_INFO_ATTR_BUF_COPY(info, info_cp);
+ if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
+ {
+ metric = info_cp->attr->med;
+ nexthop = &info_cp->attr->nexthop;
+
+ if (info_cp->attr->extra)
+ tag = info_cp->attr->extra->tag;
+ }
+ BGP_INFO_ATTR_BUF_FREE(info_cp);
+ }
+ else
+ {
+ nexthop = &info->attr->nexthop;
+ }
+
+ if (nexthop)
+ {
+ stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
+ valid_nh_count++;
+ }
api.vrf_id = VRF_DEFAULT;
api.flags = flags;
nexthop = &info->attr->nexthop;
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
+
for (mpinfo = bgp_info_mpath_first (info); mpinfo;
- mpinfo = bgp_info_mpath_next (mpinfo))
- {
- nexthop = &mpinfo->attr->nexthop;
- stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
- }
+ mpinfo = bgp_info_mpath_next (mpinfo))
+ {
+ nexthop = NULL;
+
+ if (bgp->table_map[afi][safi].name)
+ {
+ /* Copy info and attributes, so the route-map apply doesn't modify the
+ BGP route info. */
+ BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
+ if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
+ nexthop = &info_cp->attr->nexthop;
+ BGP_INFO_ATTR_BUF_FREE(info_cp);
+ }
+ else
+ {
+ nexthop = &mpinfo->attr->nexthop;
+ }
+
+ if (nexthop == NULL)
+ continue;
+
+ stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
+ valid_nh_count++;
+ }
+ api.flags = flags;
api.type = ZEBRA_ROUTE_BGP;
api.message = 0;
api.safi = safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- api.nexthop_num = 1 + bgp_info_mpath_count (info);
+ api.nexthop_num = valid_nh_count;
api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
api.ifindex_num = 0;
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
- api.metric = info->attr->med;
+ api.metric = metric;
+
+ if (tag)
+ {
+ SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
+ api.tag = tag;
+ }
distance = bgp_distance_apply (p, info, bgp);
@@ -738,24 +1043,20 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
api.distance = distance;
}
- if (BGP_DEBUG(zebra, ZEBRA))
- {
- int i;
- char buf[2][INET_ADDRSTRLEN];
- zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
- " count %d",
- inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
- p->prefixlen,
- inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
- api.metric, api.nexthop_num);
- for (i = 1; i < api.nexthop_num; i++)
- zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
- i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
- sizeof(buf[1])));
- }
-
- zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
- (struct prefix_ipv4 *) p, &api);
+ if (bgp_debug_zebra(p))
+ {
+ int i;
+ zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d"
+ " count %d", (valid_nh_count ? "add":"delete"),
+ inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+ p->prefixlen, api.metric, api.tag, api.nexthop_num);
+ for (i = 0; i < api.nexthop_num; i++)
+ zlog_debug(" IPv4 [nexthop %d] %s", i+1,
+ inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1])));
+ }
+
+ zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE,
+ zclient, (struct prefix_ipv4 *) p, &api);
}
/* We have to think about a IPv6 link-local address curse. */
@@ -764,40 +1065,131 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
ifindex_t ifindex;
struct in6_addr *nexthop;
struct zapi_ipv6 api;
+ int valid_nh_count = 0;
+ char buf[2][INET6_ADDRSTRLEN];
+
+ /* resize nexthop buffer size if necessary */
+ if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
+ (sizeof (struct in6_addr *) * nhcount))
+ {
+ newsize = (sizeof (struct in6_addr *) * nhcount);
+ newsize = stream_resize (bgp_nexthop_buf, newsize);
+ if (newsize == oldsize)
+ {
+ zlog_err ("can't resize nexthop buffer");
+ return;
+ }
+ }
+ stream_reset (bgp_nexthop_buf);
+
+ /* resize ifindices buffer size if necessary */
+ if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
+ (sizeof (unsigned int) * nhcount))
+ {
+ newsize = (sizeof (unsigned int) * nhcount);
+ newsize = stream_resize (bgp_ifindices_buf, newsize);
+ if (newsize == oldsize)
+ {
+ zlog_err ("can't resize nexthop buffer");
+ return;
+ }
+ }
+ stream_reset (bgp_ifindices_buf);
ifindex = 0;
nexthop = NULL;
-
- assert (info->attr->extra);
-
- /* Only global address nexthop exists. */
- if (info->attr->extra->mp_nexthop_len == 16)
- nexthop = &info->attr->extra->mp_nexthop_global;
-
- /* If both global and link-local address present. */
- if (info->attr->extra->mp_nexthop_len == 32)
- {
- /* Workaround for Cisco's nexthop bug. */
- if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
- && peer->su_remote->sa.sa_family == AF_INET6)
- nexthop = &peer->su_remote->sin6.sin6_addr;
- else
- nexthop = &info->attr->extra->mp_nexthop_local;
- if (info->peer->nexthop.ifp)
- ifindex = info->peer->nexthop.ifp->ifindex;
- }
+ assert (info->attr->extra);
- if (nexthop == NULL)
- return;
+ /* Metric is currently based on the best-path only. */
+ metric = info->attr->med;
+
+ if (bgp->table_map[afi][safi].name)
+ {
+ BGP_INFO_ATTR_BUF_INIT();
+
+ /* Copy info and attributes, so the route-map apply doesn't modify the
+ BGP route info. */
+ BGP_INFO_ATTR_BUF_COPY(info, info_cp);
+ if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
+ {
+ metric = info_cp->attr->med;
+ nexthop = bgp_info_to_ipv6_nexthop(info_cp);
+
+ if (info_cp->attr->extra)
+ tag = info_cp->attr->extra->tag;
+ }
+ BGP_INFO_ATTR_BUF_FREE(info_cp);
+ }
+ else
+ {
+ nexthop = bgp_info_to_ipv6_nexthop(info);
+ }
+
+ if (nexthop)
+ {
+ if (IN6_IS_ADDR_LINKLOCAL (nexthop))
+ {
+ if (info->attr->extra->mp_nexthop_len == 32)
+ if (info->peer->nexthop.ifp)
+ ifindex = info->peer->nexthop.ifp->ifindex;
+
+ if (!ifindex)
+ {
+ if (info->peer->conf_if || info->peer->ifname)
+ ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname);
+ else if (info->peer->nexthop.ifp)
+ ifindex = info->peer->nexthop.ifp->ifindex;
+ }
+ }
+
+ stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
+ stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
+ valid_nh_count++;
+ }
- if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
- {
- if (info->peer->ifname)
- ifindex = ifname2ifindex (info->peer->ifname);
- else if (info->peer->nexthop.ifp)
- ifindex = info->peer->nexthop.ifp->ifindex;
- }
+ for (mpinfo = bgp_info_mpath_first (info); mpinfo;
+ mpinfo = bgp_info_mpath_next (mpinfo))
+ {
+ ifindex = 0;
+ nexthop = NULL;
+
+ if (bgp->table_map[afi][safi].name)
+ {
+ /* Copy info and attributes, so the route-map apply doesn't modify the
+ BGP route info. */
+ BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
+ if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
+ nexthop = bgp_info_to_ipv6_nexthop(info_cp);
+ BGP_INFO_ATTR_BUF_FREE(info_cp);
+ }
+ else
+ {
+ nexthop = bgp_info_to_ipv6_nexthop(mpinfo);
+ }
+
+ if (nexthop == NULL)
+ continue;
+
+ if (mpinfo->attr->extra->mp_nexthop_len == 32)
+ if (mpinfo->peer->nexthop.ifp)
+ ifindex = mpinfo->peer->nexthop.ifp->ifindex;
+
+ if (!ifindex)
+ {
+ if (mpinfo->peer->conf_if || mpinfo->peer->ifname)
+ ifindex = if_nametoindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname);
+ else if (mpinfo->peer->nexthop.ifp)
+ ifindex = mpinfo->peer->nexthop.ifp->ifindex;
+ }
+
+ if (ifindex == 0)
+ continue;
+
+ stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
+ stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
+ valid_nh_count++;
+ }
/* Make Zebra API structure. */
api.vrf_id = VRF_DEFAULT;
@@ -806,29 +1198,57 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
api.message = 0;
api.safi = safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- api.nexthop_num = 1;
- api.nexthop = &nexthop;
+ api.nexthop_num = valid_nh_count;
+ api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
- api.ifindex_num = 1;
- api.ifindex = &ifindex;
+ api.ifindex_num = valid_nh_count;
+ api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
- api.metric = info->attr->med;
+ api.metric = metric;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (tag)
{
- char buf[2][INET6_ADDRSTRLEN];
- zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u",
- inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
- p->prefixlen,
- inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
- api.metric);
+ SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
+ api.tag = tag;
}
- zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
- (struct prefix_ipv6 *) p, &api);
+ if (bgp_debug_zebra(p))
+ {
+ int i;
+ zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u tag %d",
+ valid_nh_count ? "add" : "delete",
+ inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+ p->prefixlen, api.metric, api.tag);
+ for (i = 0; i < api.nexthop_num; i++)
+ zlog_debug(" IPv6 [nexthop %d] %s (%d)", i+1,
+ inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])),
+ api.ifindex[i]);
+ }
+
+ zapi_ipv6_route (valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE,
+ zclient, (struct prefix_ipv6 *) p, &api);
}
}
+/* Announce all routes of a table to zebra */
+void
+bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ struct bgp_node *rn;
+ struct bgp_table *table;
+ struct bgp_info *ri;
+
+ table = bgp->rib[afi][safi];
+ if (!table) return;
+
+ for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+ for (ri = rn->info; ri; ri = ri->next)
+ if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
+ && ri->type == ZEBRA_ROUTE_BGP
+ && ri->sub_type == BGP_ROUTE_NORMAL)
+ bgp_zebra_announce (&rn->p, ri, bgp, afi, safi);
+}
+
void
bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
{
@@ -842,6 +1262,10 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
return;
peer = info->peer;
+
+ if (peer->bgp && peer->bgp->main_zebra_update_hold)
+ return;
+
flags = 0;
if (peer->sort == BGP_PEER_IBGP)
@@ -869,13 +1293,20 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if ((info->attr->extra) && (info->attr->extra->tag != 0))
+ {
+ SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+ api.tag = info->attr->extra->tag;
+ }
+
+ if (bgp_debug_zebra(p))
{
char buf[2][INET_ADDRSTRLEN];
- zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u",
+ zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d",
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
p->prefixlen,
- api.metric);
+ api.metric,
+ api.tag);
}
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient,
@@ -886,7 +1317,6 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
if (p->family == AF_INET6)
{
struct zapi_ipv6 api;
-
api.vrf_id = VRF_DEFAULT;
api.flags = flags;
api.type = ZEBRA_ROUTE_BGP;
@@ -897,13 +1327,20 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if ((info->attr->extra) && (info->attr->extra->tag != 0))
+ {
+ SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
+ api.tag = info->attr->extra->tag;
+ }
+
+ if (bgp_debug_zebra(p))
{
char buf[2][INET6_ADDRSTRLEN];
- zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u",
+ zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d",
inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
p->prefixlen,
- api.metric);
+ api.metric,
+ api.tag);
}
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
@@ -928,15 +1365,32 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
if (zclient->sock < 0)
return CMD_WARNING;
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
-
+
/* Send distribute add message to zebra. */
zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
return CMD_SUCCESS;
}
+int
+bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type)
+{
+ /* Return if zebra connection is not established. */
+ if (zclient->sock < 0)
+ return -1;
+
+ if (BGP_DEBUG (zebra, ZEBRA))
+ zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type));
+
+ /* Send distribute add message to zebra. */
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, VRF_DEFAULT);
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT);
+
+ return 0;
+}
+
/* Redistribute with route-map specification. */
int
bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type,
@@ -996,7 +1450,7 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
&& zclient->sock >= 0)
{
/* Send distribute delete message to zebra. */
- if (BGP_DEBUG(zebra, ZEBRA))
+ if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Zebra send: redistribute delete %s",
zebra_route_string(type));
zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type,
@@ -1009,35 +1463,6 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
return CMD_SUCCESS;
}
-/* Unset redistribution route-map configuration. */
-int
-bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
-{
- if (! bgp->rmap[afi][type].name)
- return 0;
-
- /* Unset route-map. */
- free (bgp->rmap[afi][type].name);
- bgp->rmap[afi][type].name = NULL;
- bgp->rmap[afi][type].map = NULL;
-
- return 1;
-}
-
-/* Unset redistribution metric configuration. */
-int
-bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
-{
- if (! bgp->redist_metric_flag[afi][type])
- return 0;
-
- /* Unset metric. */
- bgp->redist_metric_flag[afi][type] = 0;
- bgp->redist_metric[afi][type] = 0;
-
- return 1;
-}
-
void
bgp_zclient_reset (void)
{
@@ -1062,14 +1487,18 @@ bgp_zebra_init (struct thread_master *master)
zclient->interface_delete = bgp_interface_delete;
zclient->interface_address_add = bgp_interface_address_add;
zclient->interface_address_delete = bgp_interface_address_delete;
+ zclient->interface_nbr_address_add = bgp_interface_nbr_address_add;
+ zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete;
zclient->ipv4_route_add = zebra_read_ipv4;
zclient->ipv4_route_delete = zebra_read_ipv4;
zclient->interface_up = bgp_interface_up;
zclient->interface_down = bgp_interface_down;
zclient->ipv6_route_add = zebra_read_ipv6;
zclient->ipv6_route_delete = zebra_read_ipv6;
+ zclient->nexthop_update = bgp_read_nexthop_update;
bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
+ bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
}
void
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index e69a0bc5..0b76263c 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -22,8 +22,10 @@ Boston, MA 02111-1307, USA. */
#define _QUAGGA_BGP_ZEBRA_H
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
+#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int))
extern struct stream *bgp_nexthop_buf;
+extern struct stream *bgp_ifindices_buf;
extern void bgp_zebra_init (struct thread_master *master);
extern void bgp_zebra_destroy (void);
@@ -32,15 +34,16 @@ extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
safi_t, int *);
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
int *);
-extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *, safi_t);
+extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *,
+ afi_t, safi_t);
+extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t);
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t);
extern int bgp_redistribute_set (struct bgp *, afi_t, int);
+extern int bgp_redistribute_resend (struct bgp *, afi_t, int);
extern int bgp_redistribute_rmap_set (struct bgp *, afi_t, int, const char *);
extern int bgp_redistribute_metric_set (struct bgp *, afi_t, int, u_int32_t);
extern int bgp_redistribute_unset (struct bgp *, afi_t, int);
-extern int bgp_redistribute_routemap_unset (struct bgp *, afi_t, int);
-extern int bgp_redistribute_metric_unset (struct bgp *, afi_t, int);
extern struct interface *if_lookup_by_ipv4 (struct in_addr *);
extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 249d20f3..72ad1c19 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -61,6 +61,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_network.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h"
+#include "bgpd/bgp_nht.h"
#ifdef HAVE_SNMP
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */
@@ -76,6 +77,44 @@ struct bgp_master *bm;
/* BGP community-list. */
struct community_list_handler *bgp_clist;
+
+static inline void
+bgp_session_reset(struct peer *peer)
+{
+ if (peer->doppelganger && (peer->doppelganger->status != Deleted)
+ && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
+ peer_delete(peer->doppelganger);
+
+ BGP_EVENT_ADD (peer, BGP_Stop);
+}
+
+/*
+ * During session reset, we may delete the doppelganger peer, which would
+ * be the next node to the current node. If the session reset was invoked
+ * during walk of peer list, we would end up accessing the freed next
+ * node. This function moves the next node along.
+ */
+static inline void
+bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
+{
+ struct listnode *n;
+ struct peer *npeer;
+
+ n = (nnode) ? *nnode : NULL;
+ npeer = (n) ? listgetdata(n) : NULL;
+
+ if (peer->doppelganger && (peer->doppelganger->status != Deleted)
+ && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
+ {
+ if (peer->doppelganger == npeer)
+ /* nnode and *nnode are confirmed to be non-NULL here */
+ *nnode = (*nnode)->next;
+ peer_delete(peer->doppelganger);
+ }
+
+ BGP_EVENT_ADD (peer, BGP_Stop);
+}
+
/* BGP global flag manipulation. */
int
bgp_option_set (int flag)
@@ -311,9 +350,8 @@ bgp_confederation_id_set (struct bgp *bgp, as_t as)
bgp_notify_send (peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
-
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset_safe(peer, &nnode);
}
}
else
@@ -332,7 +370,7 @@ bgp_confederation_id_set (struct bgp *bgp, as_t as)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset_safe(peer, &nnode);
}
}
}
@@ -362,7 +400,7 @@ bgp_confederation_id_unset (struct bgp *bgp)
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset_safe(peer, &nnode);
}
}
return 0;
@@ -425,7 +463,7 @@ bgp_confederation_peers_add (struct bgp *bgp, as_t as)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset_safe(peer, &nnode);
}
}
}
@@ -481,7 +519,7 @@ bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset_safe(peer, &nnode);
}
}
}
@@ -530,7 +568,7 @@ peer_rsclient_active (struct peer *peer)
}
/* Peer comparison function for sorting. */
-static int
+int
peer_cmp (struct peer *p1, struct peer *p2)
{
return sockunion_cmp (&p1->su, &p2->su);
@@ -759,6 +797,10 @@ peer_free (struct peer *peer)
XFREE(MTYPE_TMP, peer->notify.data);
bgp_sync_delete (peer);
+
+ if (peer->conf_if)
+ XFREE (MTYPE_PEER_CONF_IF, peer->conf_if);
+
memset (peer, 0, sizeof (struct peer));
XFREE (MTYPE_BGP_PEER, peer);
@@ -801,7 +843,7 @@ peer_unlock_with_caller (const char *name, struct peer *peer)
return peer;
}
-
+
/* Allocate new peer object, implicitely locked. */
static struct peer *
peer_new (struct bgp *bgp)
@@ -825,11 +867,11 @@ peer_new (struct bgp *bgp)
peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
peer->status = Idle;
peer->ostatus = Idle;
- peer->weight = 0;
- peer->password = NULL;
peer->bgp = bgp;
peer = peer_lock (peer); /* initial reference */
bgp_lock (bgp);
+ peer->weight = 0;
+ peer->password = NULL;
/* Set default flags. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
@@ -847,9 +889,22 @@ peer_new (struct bgp *bgp)
/* Create buffers. */
peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
peer->obuf = stream_fifo_new ();
- peer->work = stream_new (BGP_MAX_PACKET_SIZE);
+
+ /* We use a larger buffer for peer->work in the event that:
+ * - We RX a BGP_UPDATE where the attributes alone are just
+ * under BGP_MAX_PACKET_SIZE
+ * - The user configures an outbound route-map that does many as-path
+ * prepends or adds many communities. At most they can have CMD_ARGC_MAX
+ * args in a route-map so there is a finite limit on how large they can
+ * make the attributes.
+ *
+ * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
+ * checking for every single attribute as we construct an UPDATE.
+ */
+ peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
+
bgp_sync_init (peer);
/* Get service port number. */
@@ -859,17 +914,149 @@ peer_new (struct bgp *bgp)
return peer;
}
+/*
+ * This function is invoked when a duplicate peer structure associated with
+ * a neighbor is being deleted. If this about-to-be-deleted structure is
+ * the one with all the config, then we have to copy over the info.
+ */
+void
+peer_xfer_config (struct peer *peer_dst, struct peer *peer_src)
+{
+ afi_t afi;
+ safi_t safi;
+
+ assert(peer_src);
+ assert(peer_dst);
+
+ /* The following function is used by both peer group config copy to
+ * individual peer and when we transfer config
+ */
+ if (peer_src->change_local_as)
+ peer_dst->change_local_as = peer_src->change_local_as;
+
+ /* peer flags apply */
+ peer_dst->flags = peer_src->flags;
+ peer_dst->cap = peer_src->cap;
+ peer_dst->config = peer_src->config;
+
+ peer_dst->local_as = peer_src->local_as;
+ peer_dst->ifindex = peer_src->ifindex;
+ peer_dst->port = peer_src->port;
+ peer_sort(peer_dst);
+ peer_dst->rmap_type = peer_src->rmap_type;
+
+ /* Timers */
+ peer_dst->holdtime = peer_src->holdtime;
+ peer_dst->keepalive = peer_src->keepalive;
+ peer_dst->connect = peer_src->connect;
+ peer_dst->v_holdtime = peer_src->v_holdtime;
+ peer_dst->v_keepalive = peer_src->v_keepalive;
+ peer_dst->routeadv = peer_src->routeadv;
+ peer_dst->v_routeadv = peer_src->v_routeadv;
+
+ /* password apply */
+ if (peer_src->password && !peer_dst->password)
+ peer_dst->password = XSTRDUP (MTYPE_PEER_PASSWORD, peer_src->password);
+
+ bgp_md5_set (peer_dst);
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ {
+ peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
+ peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
+ peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi];
+ }
+
+ /* update-source apply */
+ if (peer_src->update_source)
+ {
+ if (peer_dst->update_source)
+ sockunion_free (peer_dst->update_source);
+ if (peer_dst->update_if)
+ {
+ XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
+ peer_dst->update_if = NULL;
+ }
+ peer_dst->update_source = sockunion_dup (peer_src->update_source);
+ }
+ else if (peer_src->update_if)
+ {
+ if (peer_dst->update_if)
+ XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
+ if (peer_dst->update_source)
+ {
+ sockunion_free (peer_dst->update_source);
+ peer_dst->update_source = NULL;
+ }
+ peer_dst->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if);
+ }
+
+ if (peer_src->ifname)
+ {
+ if (peer_dst->ifname)
+ free(peer_dst->ifname);
+
+ peer_dst->ifname = strdup(peer_src->ifname);
+ }
+}
+
+/*
+ * Set or reset the peer address socketunion structure based on the
+ * learnt peer address. Currently via the source address of the
+ * ipv6 ND router-advertisement.
+ */
+void
+bgp_peer_conf_if_to_su_update (struct peer *peer)
+{
+ struct interface *ifp;
+ struct nbr_connected *ifc;
+
+ if (!peer->conf_if)
+ return;
+
+ if ((ifp = if_lookup_by_name(peer->conf_if)) &&
+ ifp->nbr_connected &&
+ (ifc = listnode_head(ifp->nbr_connected)))
+ {
+ peer->su.sa.sa_family = AF_INET6;
+ memcpy(&peer->su.sin6.sin6_addr, &ifc->address->u.prefix,
+ sizeof (struct in6_addr));
+#ifdef SIN6_LEN
+ peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6);
+#endif
+ }
+ else
+ {
+ /* This works as an indication of unresolved peer address
+ on a BGP interface*/
+ peer->su.sa.sa_family = AF_UNSPEC;
+ memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr));
+ }
+}
+
/* Create new BGP peer. */
-static struct peer *
-peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
- as_t remote_as, afi_t afi, safi_t safi)
+struct peer *
+peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
+ as_t local_as, as_t remote_as, afi_t afi, safi_t safi)
{
int active;
struct peer *peer;
char buf[SU_ADDRSTRLEN];
peer = peer_new (bgp);
- peer->su = *su;
+ if (conf_if)
+ {
+ peer->conf_if = XSTRDUP (MTYPE_PEER_CONF_IF, conf_if);
+ bgp_peer_conf_if_to_su_update(peer);
+ peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, conf_if);
+ }
+ else if (su)
+ {
+ peer->su = *su;
+ sockunion2str (su, buf, SU_ADDRSTRLEN);
+ peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
+ }
peer->local_as = local_as;
peer->as = remote_as;
peer->local_id = bgp->router_id;
@@ -894,9 +1081,7 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
/* Default TTL set. */
peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
- /* Make peer's address string. */
- sockunion2str (su, buf, SU_ADDRSTRLEN);
- peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
+ SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
/* Set up peer's events and timers. */
if (! active && peer_active (peer))
@@ -905,6 +1090,26 @@ peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
return peer;
}
+struct peer *
+peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi,
+ safi_t safi)
+{
+ struct peer *peer;
+
+ peer = peer_lookup_by_conf_if (bgp, conf_if);
+ if (!peer)
+ {
+ if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
+ && afi == AFI_IP && safi == SAFI_UNICAST)
+ peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, 0, 0);
+ else
+ peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, afi, safi);
+
+ }
+
+ return peer;
+}
+
/* Make accept BGP peer. Called from bgp_accept (). */
struct peer *
peer_create_accept (struct bgp *bgp)
@@ -912,7 +1117,7 @@ peer_create_accept (struct bgp *bgp)
struct peer *peer;
peer = peer_new (bgp);
-
+
peer = peer_lock (peer); /* bgp peer list reference */
listnode_add_sort (bgp->peer, peer);
@@ -920,7 +1125,7 @@ peer_create_accept (struct bgp *bgp)
}
/* Change peer's AS number. */
-static void
+void
peer_as_change (struct peer *peer, as_t as)
{
bgp_peer_sort_t type;
@@ -936,7 +1141,7 @@ peer_as_change (struct peer *peer, as_t as)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
type = peer_sort (peer);
peer->as = as;
@@ -1000,13 +1205,16 @@ peer_as_change (struct peer *peer, as_t as)
/* If peer does not exist, create new one. If peer already exists,
set AS number to the peer. */
int
-peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
- afi_t afi, safi_t safi)
+peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t *as,
+ afi_t afi, safi_t safi)
{
struct peer *peer;
as_t local_as;
- peer = peer_lookup (bgp, su);
+ if (conf_if)
+ peer = peer_lookup_by_conf_if (bgp, conf_if);
+ else
+ peer = peer_lookup (bgp, su);
if (peer)
{
@@ -1043,6 +1251,8 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
}
else
{
+ if (conf_if)
+ return BGP_ERR_NO_INTERFACE_CONFIG;
/* If the peer is not part of our confederation, and its not an
iBGP peer then spoof the source AS */
@@ -1058,9 +1268,9 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
&& afi == AFI_IP && safi == SAFI_UNICAST)
- peer_create (su, bgp, local_as, *as, 0, 0);
+ peer = peer_create (su, conf_if, bgp, local_as, *as, 0, 0);
else
- peer_create (su, bgp, local_as, *as, afi, safi);
+ peer = peer_create (su, conf_if, bgp, local_as, *as, afi, safi);
}
return 0;
@@ -1195,13 +1405,13 @@ peer_nsf_stop (struct peer *peer)
if (peer->t_gr_restart)
{
BGP_TIMER_OFF (peer->t_gr_restart);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s graceful restart timer stopped", peer->host);
}
if (peer->t_gr_stale)
{
BGP_TIMER_OFF (peer->t_gr_stale);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
}
bgp_clear_route_all (peer);
@@ -1229,12 +1439,14 @@ peer_delete (struct peer *peer)
struct listnode *pn;
assert (peer->status != Deleted);
-
+
bgp = peer->bgp;
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
peer_nsf_stop (peer);
+ SET_FLAG(peer->flags, PEER_FLAG_DELETE);
+
/* If this peer belongs to peer group, clear up the
relationship. */
if (peer->group)
@@ -1253,6 +1465,13 @@ peer_delete (struct peer *peer)
*/
peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
bgp_stop (peer);
+ UNSET_FLAG(peer->flags, PEER_FLAG_DELETE);
+
+ if (peer->doppelganger)
+ peer->doppelganger->doppelganger = NULL;
+ peer->doppelganger = NULL;
+
+ UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
bgp_fsm_change_status (peer, Deleted);
/* Password configuration */
@@ -1266,7 +1485,7 @@ peer_delete (struct peer *peer)
}
bgp_timer_set (peer); /* stops all timers for Deleted */
-
+
/* Delete from all peer list. */
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
&& (pn = listnode_lookup (bgp->peer, peer)))
@@ -1281,12 +1500,15 @@ peer_delete (struct peer *peer)
peer_unlock (peer); /* rsclient list reference */
list_delete_node (bgp->rsclient, pn);
- /* Clear our own rsclient ribs. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_RSERVER_CLIENT))
- bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ {
+ /* Clear our own rsclient ribs. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
+ }
}
/* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
@@ -1765,13 +1987,21 @@ peer_group_delete (struct peer_group *group)
{
struct bgp *bgp;
struct peer *peer;
+ struct peer *other;
struct listnode *node, *nnode;
bgp = group->bgp;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
{
+ other = peer->doppelganger;
+ peer->group = NULL;
peer_delete (peer);
+ if (other && other->status != Deleted)
+ {
+ other->group = NULL;
+ peer_delete(other);
+ }
}
list_delete (group->peer);
@@ -1792,7 +2022,7 @@ peer_group_delete (struct peer_group *group)
int
peer_group_remote_as_delete (struct peer_group *group)
{
- struct peer *peer;
+ struct peer *peer, *other;
struct listnode *node, *nnode;
if (! group->conf->as)
@@ -1800,7 +2030,16 @@ peer_group_remote_as_delete (struct peer_group *group)
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
{
+ other = peer->doppelganger;
+
+ peer->group = NULL;
peer_delete (peer);
+
+ if (other && other->status != Deleted)
+ {
+ other->group = NULL;
+ peer_delete(other);
+ }
}
list_delete_all_node (group->peer);
@@ -1811,10 +2050,9 @@ peer_group_remote_as_delete (struct peer_group *group)
/* Bind specified peer to peer group. */
int
-peer_group_bind (struct bgp *bgp, union sockunion *su,
+peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
{
- struct peer *peer;
int first_member = 0;
/* Check peer group's address family. */
@@ -1822,7 +2060,8 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
/* Lookup the peer. */
- peer = peer_lookup (bgp, su);
+ if (!peer)
+ peer = peer_lookup (bgp, su);
/* Create a new peer. */
if (! peer)
@@ -1830,13 +2069,14 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
if (! group->conf->as)
return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
- peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
+ peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, afi, safi);
peer->group = group;
peer->af_group[afi][safi] = 1;
peer = peer_lock (peer); /* group->peer list reference */
listnode_add (group->peer, peer);
peer_group2peer_config_copy (group, peer, afi, safi);
+ SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
return 0;
}
@@ -1943,6 +2183,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
}
peer_group2peer_config_copy (group, peer, afi, safi);
+ SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
{
@@ -1951,7 +2192,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
return 0;
}
@@ -1960,6 +2201,8 @@ int
peer_group_unbind (struct bgp *bgp, struct peer *peer,
struct peer_group *group, afi_t afi, safi_t safi)
{
+ struct peer *other;
+
if (! peer->af_group[afi][safi])
return 0;
@@ -1979,9 +2222,20 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
peer_unlock (peer); /* peer group list reference */
listnode_delete (group->peer, peer);
peer->group = NULL;
+ other = peer->doppelganger;
if (group->conf->as)
{
peer_delete (peer);
+ if (other && other->status != Deleted)
+ {
+ if (other->group)
+ {
+ peer_unlock(other);
+ listnode_delete(group->peer, other);
+ }
+ other->group = NULL;
+ peer_delete(other);
+ }
return 0;
}
peer_global_config_reset (peer);
@@ -1994,7 +2248,7 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
return 0;
}
@@ -2045,6 +2299,7 @@ bgp_create (as_t *as, const char *name)
bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
}
+ bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
@@ -2057,6 +2312,10 @@ bgp_create (as_t *as, const char *name)
if (name)
bgp->name = strdup (name);
+ bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
+ bgp->adv_quanta = BGP_ADV_FIFO_QUANTA;
+ bgp->wd_quanta = BGP_WD_FIFO_QUANTA;
+
THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
bgp, bgp->restart_time);
@@ -2152,6 +2411,9 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
bgp_router_id_set(bgp, &router_id_zebra);
*bgp_val = bgp;
+ bgp->t_rmap_update = NULL;
+ bgp->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
+
/* Create BGP server socket, if first instance. */
if (list_isempty(bm->bgp)
&& !bgp_option_check (BGP_OPT_NO_LISTEN))
@@ -2180,6 +2442,20 @@ bgp_delete (struct bgp *bgp)
THREAD_OFF (bgp->t_startup);
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
+ {
+ if (peer->status == Established ||
+ peer->status == OpenSent ||
+ peer->status == OpenConfirm)
+ {
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_PEER_UNCONFIG);
+ }
+ }
+
+ if (bgp->t_rmap_update)
+ BGP_TIMER_OFF(bgp->t_rmap_update);
+
/* Delete static route. */
bgp_static_delete (bgp);
@@ -2189,17 +2465,6 @@ bgp_delete (struct bgp *bgp)
if (i != ZEBRA_ROUTE_BGP)
bgp_redistribute_unset (bgp, afi, i);
- for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
- {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
- {
- /* Send notify to remote peer. */
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
- }
-
- peer_delete (peer);
- }
-
for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
{
for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
@@ -2213,6 +2478,17 @@ bgp_delete (struct bgp *bgp)
peer_group_delete (group);
}
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
+ {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ {
+ /* Send notify to remote peer. */
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+ }
+
+ peer_delete (peer);
+ }
+
assert (listcount (bgp->rsclient) == 0);
if (bgp->peer_self) {
@@ -2284,25 +2560,28 @@ bgp_free (struct bgp *bgp)
}
struct peer *
-peer_lookup (struct bgp *bgp, union sockunion *su)
+peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if)
{
struct peer *peer;
struct listnode *node, *nnode;
+ if (!conf_if)
+ return NULL;
+
if (bgp != NULL)
{
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- if (sockunion_same (&peer->su, su)
+ if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
&& ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
return peer;
}
else if (bm->bgp != NULL)
{
struct listnode *bgpnode, *nbgpnode;
-
+
for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- if (sockunion_same (&peer->su, su)
+ if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
&& ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
return peer;
}
@@ -2310,44 +2589,27 @@ peer_lookup (struct bgp *bgp, union sockunion *su)
}
struct peer *
-peer_lookup_with_open (union sockunion *su, as_t remote_as,
- struct in_addr *remote_id, int *as)
+peer_lookup (struct bgp *bgp, union sockunion *su)
{
struct peer *peer;
- struct listnode *node;
- struct listnode *bgpnode;
- struct bgp *bgp;
-
- if (! bm->bgp)
- return NULL;
+ struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
+ if (bgp != NULL)
{
- for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
- {
- if (sockunion_same (&peer->su, su)
- && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- if (peer->as == remote_as
- && peer->remote_id.s_addr == remote_id->s_addr)
- return peer;
- if (peer->as == remote_as)
- *as = 1;
- }
- }
-
- for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
- {
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if (sockunion_same (&peer->su, su)
+ && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
+ return peer;
+ }
+ else if (bm->bgp != NULL)
+ {
+ struct listnode *bgpnode, *nbgpnode;
+
+ for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
if (sockunion_same (&peer->su, su)
- && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
- {
- if (peer->as == remote_as
- && peer->remote_id.s_addr == 0)
- return peer;
- if (peer->as == remote_as)
- *as = 1;
- }
- }
+ && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
+ return peer;
}
return NULL;
}
@@ -2356,6 +2618,8 @@ peer_lookup_with_open (union sockunion *su, as_t remote_as,
int
peer_active (struct peer *peer)
{
+ if (BGP_PEER_SU_UNSPEC(peer))
+ return 0;
if (peer->afc[AFI_IP][SAFI_UNICAST]
|| peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN]
@@ -2404,16 +2668,31 @@ peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
return;
if (type == peer_change_reset)
- bgp_notify_send (peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ {
+ /* If we're resetting session, we've to delete both peer struct */
+ if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
+ && (!CHECK_FLAG(peer->doppelganger->flags,
+ PEER_FLAG_CONFIG_NODE)))
+ peer_delete(peer->doppelganger);
+
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ }
else if (type == peer_change_reset_in)
{
if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
|| CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
else
- bgp_notify_send (peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ {
+ if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
+ && (!CHECK_FLAG(peer->doppelganger->flags,
+ PEER_FLAG_CONFIG_NODE)))
+ peer_delete(peer->doppelganger);
+
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ }
}
else if (type == peer_change_reset_out)
bgp_announce_route (peer, afi, safi);
@@ -2458,11 +2737,14 @@ static const struct peer_flag_action peer_af_flag_action_list[] =
{ PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
{ PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
{ PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
+ { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
+ { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
{ PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
{ PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
{ PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
{ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
{ PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
+ { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
{ 0, 0, 0 }
};
@@ -2530,19 +2812,19 @@ peer_flag_modify_action (struct peer *peer, u_int32_t flag)
if (peer->t_pmax_restart)
{
BGP_TIMER_OFF (peer->t_pmax_restart);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Maximum-prefix restart timer canceled",
peer->host);
}
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
- peer_nsf_stop (peer);
+ if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
+ peer_nsf_stop (peer);
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send (peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
else
{
@@ -2563,7 +2845,7 @@ peer_flag_modify_action (struct peer *peer, u_int32_t flag)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
/* Change specified peer flag. */
@@ -2706,6 +2988,11 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
&& peer_sort (peer) == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS;
+ /* as-override is not allowed for IBGP peers */
+ if (flag & PEER_FLAG_AS_OVERRIDE
+ && peer_sort (peer) == BGP_PEER_IBGP)
+ return BGP_ERR_AS_OVERRIDE;
+
/* When unset the peer-group member's flag we have to check
peer-group configuration. */
if (! set && peer->af_group[afi][safi])
@@ -2812,7 +3099,7 @@ peer_ebgp_multihop_set (struct peer *peer, int ttl)
struct listnode *node, *nnode;
struct peer *peer1;
- if (peer->sort == BGP_PEER_IBGP)
+ if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
return 0;
/* see comment in peer_ttl_security_hops_set() */
@@ -2960,7 +3247,7 @@ peer_update_source_if_set (struct peer *peer, const char *ifname)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
return 0;
}
@@ -2992,7 +3279,7 @@ peer_update_source_if_set (struct peer *peer, const char *ifname)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
return 0;
}
@@ -3016,6 +3303,7 @@ peer_update_source_addr_set (struct peer *peer, union sockunion *su)
{
XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
peer->update_if = NULL;
+
}
peer->update_source = sockunion_dup (su);
@@ -3029,7 +3317,7 @@ peer_update_source_addr_set (struct peer *peer, union sockunion *su)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
return 0;
}
@@ -3060,7 +3348,7 @@ peer_update_source_addr_set (struct peer *peer, union sockunion *su)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
return 0;
}
@@ -3111,7 +3399,7 @@ peer_update_source_unset (struct peer *peer)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
return 0;
}
@@ -3141,7 +3429,7 @@ peer_update_source_unset (struct peer *peer)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
return 0;
}
@@ -3642,8 +3930,7 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
-
+ bgp_session_reset(peer);
return 0;
}
@@ -3718,7 +4005,7 @@ peer_local_as_unset (struct peer *peer)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
return 0;
}
@@ -3748,7 +4035,7 @@ peer_password_set (struct peer *peer, const char *password)
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
}
@@ -3766,7 +4053,7 @@ peer_password_set (struct peer *peer, const char *password)
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
if (bgp_md5_set (peer) < 0)
ret = BGP_ERR_TCPSIG_FAILED;
@@ -3794,7 +4081,7 @@ peer_password_unset (struct peer *peer)
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
if (peer->password)
XFREE (MTYPE_PEER_PASSWORD, peer->password);
@@ -3817,7 +4104,7 @@ peer_password_unset (struct peer *peer)
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
XFREE (MTYPE_PEER_PASSWORD, peer->password);
peer->password = NULL;
@@ -4250,7 +4537,7 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
}
static void
-peer_aslist_update (void)
+peer_aslist_update (const char *aslist_name)
{
afi_t afi;
safi_t safi;
@@ -4300,8 +4587,42 @@ peer_aslist_update (void)
}
}
}
+static void
+peer_aslist_add (char *aslist_name)
+{
+ peer_aslist_update (aslist_name);
+ route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED);
+}
+
+static void
+peer_aslist_del (const char *aslist_name)
+{
+ peer_aslist_update (aslist_name);
+ route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_DELETED);
+}
+
/* Set route-map to the peer. */
+static void
+peer_reprocess_routes (struct peer *peer, int direct,
+ afi_t afi, safi_t safi)
+{
+ if (peer->status != Established)
+ return;
+
+ if (direct != RMAP_OUT)
+ {
+ if (CHECK_FLAG (peer->af_flags[afi][safi],
+ PEER_FLAG_SOFT_RECONFIG))
+ bgp_soft_reconfig_in (peer, afi, safi);
+ else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
+ || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+ bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+ }
+ else
+ bgp_announce_route(peer, afi, safi);
+}
+
int
peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
const char *name)
@@ -4325,12 +4646,15 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
if (filter->map[direct].name)
free (filter->map[direct].name);
-
+
filter->map[direct].name = strdup (name);
filter->map[direct].map = route_map_lookup_by_name (name);
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
- return 0;
+ {
+ peer_reprocess_routes(peer, direct, afi, safi);
+ return 0;
+ }
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
@@ -4344,6 +4668,7 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
free (filter->map[direct].name);
filter->map[direct].name = strdup (name);
filter->map[direct].map = route_map_lookup_by_name (name);
+ peer_reprocess_routes (peer, direct, afi, safi);
}
return 0;
}
@@ -4391,7 +4716,10 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
filter->map[direct].map = NULL;
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
- return 0;
+ {
+ peer_reprocess_routes(peer, direct, afi, safi);
+ return 0;
+ }
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
@@ -4405,6 +4733,7 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
free (filter->map[direct].name);
filter->map[direct].name = NULL;
filter->map[direct].map = NULL;
+ peer_reprocess_routes(peer, direct, afi, safi);
}
return 0;
}
@@ -4433,7 +4762,10 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
filter->usmap.map = route_map_lookup_by_name (name);
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
- return 0;
+ {
+ bgp_announce_route (peer, afi, safi);
+ return 0;
+ }
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
@@ -4447,6 +4779,7 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
free (filter->usmap.name);
filter->usmap.name = strdup (name);
filter->usmap.map = route_map_lookup_by_name (name);
+ bgp_announce_route (peer, afi, safi);
}
return 0;
}
@@ -4473,7 +4806,10 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
filter->usmap.map = NULL;
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
- return 0;
+ {
+ bgp_announce_route(peer, afi, safi);
+ return 0;
+ }
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
@@ -4487,6 +4823,7 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
free (filter->usmap.name);
filter->usmap.name = NULL;
filter->usmap.map = NULL;
+ bgp_announce_route(peer, afi, safi);
}
return 0;
}
@@ -4511,24 +4848,33 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
else
UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
- return 0;
-
- group = peer->group;
- for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+ if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
- if (! peer->af_group[afi][safi])
- continue;
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+ {
+ if (! peer->af_group[afi][safi])
+ continue;
- SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
- peer->pmax[afi][safi] = max;
- peer->pmax_threshold[afi][safi] = threshold;
- peer->pmax_restart[afi][safi] = restart;
- if (warning)
- SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
- else
- UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+ SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+ peer->pmax[afi][safi] = max;
+ peer->pmax_threshold[afi][safi] = threshold;
+ peer->pmax_restart[afi][safi] = restart;
+ if (warning)
+ SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+ else
+ 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;
}
@@ -4650,7 +4996,11 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
if (peer->fd >= 0)
- sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
+ sockopt_minttl (peer->su.sa.sa_family, peer->fd,
+ MAXTTL + 1 - gtsm_hops);
+ if (peer->status != Established && peer->doppelganger)
+ sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
+ MAXTTL + 1 - gtsm_hops);
}
else
{
@@ -4672,9 +5022,9 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
}
else if (peer->status < Established)
{
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Min-ttl changed", peer->host);
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset(peer);
}
}
}
@@ -4702,6 +5052,9 @@ peer_ttl_security_hops_unset (struct peer *peer)
{
if (peer->fd >= 0)
sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
+
+ if (peer->status != Established && peer->doppelganger)
+ sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, 0);
}
else
{
@@ -4712,14 +5065,24 @@ peer_ttl_security_hops_unset (struct peer *peer)
if (peer->fd >= 0)
sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
+
+ if (peer->status != Established && peer->doppelganger)
+ sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, 0);
}
}
return peer_ebgp_multihop_unset (opeer);
}
+/*
+ * If peer clear is invoked in a loop for all peers on the BGP instance,
+ * it may end up freeing the doppelganger, and if this was the next node
+ * to the current node, we would end up accessing the freed next node.
+ * Pass along additional parameter which can be updated if next node
+ * is freed; only required when walking the peer list on BGP instance.
+ */
int
-peer_clear (struct peer *peer)
+peer_clear (struct peer *peer, struct listnode **nnode)
{
if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
{
@@ -4729,7 +5092,7 @@ peer_clear (struct peer *peer)
if (peer->t_pmax_restart)
{
BGP_TIMER_OFF (peer->t_pmax_restart);
- if (BGP_DEBUG (events, EVENTS))
+ if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Maximum-prefix restart timer canceled",
peer->host);
}
@@ -4742,7 +5105,7 @@ peer_clear (struct peer *peer)
bgp_notify_send (peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_ADMIN_RESET);
else
- BGP_EVENT_ADD (peer, BGP_Stop);
+ bgp_session_reset_safe(peer, nnode);
}
return 0;
}
@@ -4954,7 +5317,11 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
char buf[SU_ADDRSTRLEN];
char *addr;
- addr = peer->host;
+ if (peer->conf_if)
+ addr = peer->conf_if;
+ else
+ addr = peer->host;
+
if (peer_group_active (peer))
g_peer = peer->group->conf;
@@ -4963,6 +5330,9 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
************************************/
if (afi == AFI_IP && safi == SAFI_UNICAST)
{
+ if (peer->conf_if)
+ vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE);
+
/* remote-as. */
if (! peer_group_active (peer))
{
@@ -5173,11 +5543,27 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
" all" : "", VTY_NEWLINE);
- /* Remove private AS. */
- if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
- && ! peer->af_group[afi][safi])
- vty_out (vty, " neighbor %s remove-private-AS%s",
- addr, VTY_NEWLINE);
+ /* remove-private-AS */
+ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi])
+ {
+ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) &&
+ peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE);
+
+ else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ vty_out (vty, " neighbor %s remove-private-AS replace-AS%s", addr, VTY_NEWLINE);
+
+ else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
+ vty_out (vty, " neighbor %s remove-private-AS all%s", addr, VTY_NEWLINE);
+
+ else
+ vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE);
+ }
+
+ /* as-override */
+ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) &&
+ !peer->af_group[afi][safi])
+ vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE);
/* send-community print. */
if (! peer->af_group[afi][safi])
@@ -5357,7 +5743,7 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
{
if (peer->afc[afi][safi])
{
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
{
bgp_config_write_family_header (vty, afi, safi, &write);
bgp_config_write_peer (vty, bgp, peer, afi, safi);
@@ -5366,6 +5752,7 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
}
bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
+ bgp_config_write_table_map (vty, bgp, afi, safi, &write);
if (write)
vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
@@ -5478,6 +5865,27 @@ bgp_config_write (struct vty *vty)
if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
+ /* BGP update-delay. */
+ bgp_config_write_update_delay (vty, bgp);
+
+ if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
+ {
+ vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
+ if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
+ vty_out (vty, " %d", bgp->maxmed_onstartup_value);
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+ if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
+ {
+ vty_out (vty, " bgp max-med administrative");
+ if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
+ vty_out (vty, " %d", bgp->maxmed_admin_value);
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+
+ /* write quanta */
+ bgp_config_write_wpkt_quanta (vty, bgp);
+
/* BGP graceful-restart. */
if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
@@ -5493,6 +5901,10 @@ bgp_config_write (struct vty *vty)
if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
}
+ if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
+ vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
+ VTY_NEWLINE);
+ }
if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
@@ -5510,9 +5922,6 @@ bgp_config_write (struct vty *vty)
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
- /* BGP scan interval. */
- bgp_config_write_scan_time (vty);
-
/* BGP flag dampening. */
if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
BGP_CONFIG_DAMPENING))
@@ -5530,6 +5939,10 @@ bgp_config_write (struct vty *vty)
vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
bgp->default_holdtime, VTY_NEWLINE);
+ if (bgp->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
+ vty_out (vty, " bgp route-map delay-timer %d%s", bgp->rmap_update_timer,
+ VTY_NEWLINE);
+
/* peer-group */
for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
{
@@ -5539,12 +5952,13 @@ bgp_config_write (struct vty *vty)
/* Normal neighbor configuration. */
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
- if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
}
/* maximum-paths */
bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
+ bgp_config_write_table_map (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
/* Distance configuration. */
bgp_config_write_distance (vty, bgp);
@@ -5598,12 +6012,16 @@ bgp_master_init (void)
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. */
bgp_zebra_init (bm->master);
+ /* BGP VTY commands installation. */
+ bgp_vty_init ();
+
/* BGP inits. */
bgp_attr_init ();
bgp_debug_init ();
@@ -5611,7 +6029,7 @@ bgp_init (void)
bgp_route_init ();
bgp_route_map_init ();
bgp_address_init ();
- bgp_scan_init ();
+ bgp_scan_vty_init();
bgp_mplsvpn_init ();
bgp_encap_init ();
@@ -5622,8 +6040,8 @@ bgp_init (void)
/* Filter list initialize. */
bgp_filter_init ();
- as_list_add_hook (peer_aslist_update);
- as_list_delete_hook (peer_aslist_update);
+ as_list_add_hook (peer_aslist_add);
+ as_list_delete_hook (peer_aslist_del);
/* Prefix list initialize.*/
prefix_list_init ();
@@ -5646,12 +6064,25 @@ bgp_terminate (void)
struct listnode *node, *nnode;
struct listnode *mnode, *mnnode;
+ /* Close the listener sockets first as this prevents peers from attempting
+ * to reconnect on receiving the peer unconfig message. In the presence
+ * of a large number of peers this will ensure that no peer is left with
+ * a dangling connection
+ */
+ /* reverse bgp_master_init */
+ bgp_close();
+ if (bm->listen_sockets)
+ list_free(bm->listen_sockets);
+ bm->listen_sockets = NULL;
+
for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- if (peer->status == Established)
+ if (peer->status == Established ||
+ peer->status == OpenSent ||
+ peer->status == OpenConfirm)
bgp_notify_send (peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
-
+
bgp_cleanup_routes ();
if (bm->process_main_queue)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 7665d9d0..25838edb 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -23,6 +23,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* For union sockunion. */
#include "sockunion.h"
+#include "routemap.h"
/* Typedef BGP specific types. */
typedef u_int32_t as_t;
@@ -62,6 +63,13 @@ struct bgp_master
#define BGP_OPT_NO_LISTEN (1 << 3)
};
+/* BGP route-map structure. */
+struct bgp_rmap
+{
+ char *name;
+ struct route_map *map;
+};
+
/* BGP instance structure. */
struct bgp
{
@@ -104,10 +112,45 @@ struct bgp
as_t *confed_peers;
int confed_peers_cnt;
- struct thread *t_startup;
+ struct thread *t_startup; /* start-up timer on only once at the beginning */
+
+ u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */
+#define BGP_MAXMED_ONSTARTUP_UNCONFIGURED 0 /* 0 means off, its the default */
+ u_int32_t maxmed_onstartup_value; /* Max-med value when active on start-up */
+ struct thread *t_maxmed_onstartup; /* non-null when max-med onstartup is on */
+ u_char maxmed_onstartup_over; /* Flag to make it effective only once */
+
+ u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */
+#define BGP_MAXMED_ADMIN_UNCONFIGURED 0 /* Off by default */
+ u_int32_t maxmed_admin_value; /* Max-med value when administrative in on */
+#define BGP_MAXMED_VALUE_DEFAULT 4294967294 /* Maximum by default */
+
+ u_char maxmed_active; /* 1/0 if max-med is active or not */
+ u_int32_t maxmed_value; /* Max-med value when its active */
+
+ /* BGP update delay on startup */
+ struct thread *t_update_delay;
+ struct thread *t_establish_wait;
+ u_char update_delay_over;
+ u_char main_zebra_update_hold;
+ u_char main_peers_update_hold;
+ u_char rsclient_peers_update_hold;
+ u_int16_t v_update_delay;
+ u_int16_t v_establish_wait;
+ char update_delay_begin_time[64];
+ char update_delay_end_time[64];
+ char update_delay_zebra_resume_time[64];
+ char update_delay_peers_resume_time[64];
+ u_int32_t established;
+ u_int32_t restarted_peers;
+ u_int32_t implicit_eors;
+ u_int32_t explicit_eors;
+#define BGP_UPDATE_DELAY_DEF 0
+#define BGP_UPDATE_DELAY_MIN 0
+#define BGP_UPDATE_DELAY_MAX 3600
/* BGP flags. */
- u_int16_t flags;
+ u_int32_t flags;
#define BGP_FLAG_ALWAYS_COMPARE_MED (1 << 0)
#define BGP_FLAG_DETERMINISTIC_MED (1 << 1)
#define BGP_FLAG_MED_MISSING_AS_WORST (1 << 2)
@@ -124,6 +167,7 @@ struct bgp
#define BGP_FLAG_ASPATH_CONFED (1 << 13)
#define BGP_FLAG_ASPATH_MULTIPATH_RELAX (1 << 14)
#define BGP_FLAG_DELETING (1 << 15)
+#define BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY (1 << 16)
/* BGP Per AF flags */
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
@@ -138,6 +182,9 @@ struct bgp
/* BGP routing information base. */
struct bgp_table *rib[AFI_MAX][SAFI_MAX];
+ /* BGP table route-map. */
+ struct bgp_rmap table_map[AFI_MAX][SAFI_MAX];
+
/* BGP redistribute configuration. */
u_char redist[AFI_MAX][ZEBRA_ROUTE_MAX];
@@ -146,11 +193,12 @@ struct bgp
u_int32_t redist_metric[AFI_MAX][ZEBRA_ROUTE_MAX];
/* BGP redistribute route-map. */
- struct
- {
- char *name;
- struct route_map *map;
- } rmap[AFI_MAX][ZEBRA_ROUTE_MAX];
+ struct bgp_rmap rmap[AFI_MAX][ZEBRA_ROUTE_MAX];
+
+ /* timer to dampen route map changes */
+ struct thread *t_rmap_update; /* Handle route map updates */
+ u_int32_t rmap_update_timer; /* Route map update timer */
+#define RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */
/* BGP distance configuration. */
u_char distance_ebgp;
@@ -172,9 +220,18 @@ struct bgp
struct bgp_maxpaths_cfg {
u_int16_t maxpaths_ebgp;
u_int16_t maxpaths_ibgp;
+ u_int16_t ibgp_flags;
+#define BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN (1 << 0)
} maxpaths[AFI_MAX][SAFI_MAX];
+
+ u_int32_t wpkt_quanta; /* per peer packet quanta to write */
+ u_int32_t adv_quanta; /* adv FIFO size that triggers write */
+ u_int32_t wd_quanta; /* withdraw FIFO size that triggers write */
};
+#define BGP_ROUTE_ADV_HOLD(bgp) \
+ (bgp->main_peers_update_hold || bgp->rsclient_peers_update_hold)
+
/* BGP peer-group support. */
struct peer_group
{
@@ -272,6 +329,12 @@ typedef enum
BGP_PEER_CONFED,
} bgp_peer_sort_t;
+/* BGP message header and packet size. */
+#define BGP_MARKER_SIZE 16
+#define BGP_HEADER_SIZE 19
+#define BGP_MAX_PACKET_SIZE 4096
+#define BGP_MAX_PACKET_SIZE_OVERFLOW 1024
+
/* BGP neighbor structure. */
struct peer
{
@@ -320,6 +383,9 @@ struct peer
*/
struct stream *scratch;
+ /* the doppelganger peer structure, due to dual TCP conn setup */
+ struct peer *doppelganger;
+
/* Status of the peer. */
int status;
int ostatus;
@@ -336,15 +402,16 @@ struct peer
unsigned short port; /* Destination port for peer */
char *host; /* Printable address of the peer. */
union sockunion su; /* Sockunion address of the peer. */
+#define BGP_PEER_SU_UNSPEC(peer) (peer->su.sa.sa_family == AF_UNSPEC)
time_t uptime; /* Last Up/Down time */
time_t readtime; /* Last read time */
time_t resettime; /* Last reset time */
ifindex_t ifindex; /* ifindex of the BGP connection. */
+ char *conf_if; /* neighbor interface config name. */
char *ifname; /* bind interface name. */
char *update_if;
union sockunion *update_source;
- struct zlog *log;
union sockunion *su_local; /* Sockunion of local address. */
union sockunion *su_remote; /* Sockunion of remote address. */
@@ -393,6 +460,8 @@ struct peer
#define PEER_FLAG_DISABLE_CONNECTED_CHECK (1 << 6) /* disable-connected-check */
#define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 7) /* local-as no-prepend */
#define PEER_FLAG_LOCAL_AS_REPLACE_AS (1 << 8) /* local-as no-prepend replace-as */
+#define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */
+#define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */
/* NSF mode (graceful restart) */
u_char nsf[AFI_MAX][SAFI_MAX];
@@ -417,6 +486,9 @@ struct peer
#define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */
#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */
#define PEER_FLAG_NEXTHOP_SELF_ALL (1 << 17) /* next-hop-self all */
+#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1 << 18) /* remove-private-as all */
+#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */
+#define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */
/* MD5 password */
char *password;
@@ -481,6 +553,8 @@ struct peer
struct thread *t_gr_restart;
struct thread *t_gr_stale;
+ int radv_adjusted; /* flag if MRAI has been adjusted or not */
+
/* workqueues */
struct work_queue *clear_node_queue;
@@ -503,9 +577,13 @@ struct peer
u_int32_t established; /* Established */
u_int32_t dropped; /* Dropped */
+ /* Update delay related fields */
+ u_char update_delay_over; /* When this is set, BGP is no more waiting for EOR */
+
/* Syncronization list and time. */
struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX];
time_t synctime;
+ time_t last_write; /* timestamp when the last UPDATE msg was written */
/* Send prefix count. */
unsigned long scount[AFI_MAX][SAFI_MAX];
@@ -525,6 +603,12 @@ struct peer
/* ORF Prefix-list */
struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX];
+ /* Text description of last attribute rcvd */
+ char rcvd_attr_str[BUFSIZ];
+
+ /* Track if we printed the attribute in debugs */
+ int rcvd_attr_printed;
+
/* Prefix count. */
unsigned long pcount[AFI_MAX][SAFI_MAX];
@@ -561,6 +645,8 @@ struct peer
#define PEER_DOWN_PASSIVE_CHANGE 20 /* neighbor passive command */
#define PEER_DOWN_MULTIHOP_CHANGE 21 /* neighbor multihop command */
#define PEER_DOWN_NSF_CLOSE_SESSION 22 /* NSF tcp session close */
+unsigned long last_reset_cause_size;
+u_char last_reset_cause[BGP_MAX_PACKET_SIZE];
/* The kind of route-map Flags.*/
u_char rmap_type;
@@ -600,11 +686,6 @@ struct bgp_nlri
/* Default BGP port number. */
#define BGP_PORT_DEFAULT 179
-/* BGP message header and packet size. */
-#define BGP_MARKER_SIZE 16
-#define BGP_HEADER_SIZE 19
-#define BGP_MAX_PACKET_SIZE 4096
-
/* BGP minimum message size. */
#define BGP_MSG_OPEN_MIN_SIZE (BGP_HEADER_SIZE + 10)
#define BGP_MSG_UPDATE_MIN_SIZE (BGP_HEADER_SIZE + 4)
@@ -742,7 +823,7 @@ struct bgp_nlri
#define BGP_EVENTS_MAX 15
/* BGP timers default value. */
-#define BGP_INIT_START_TIMER 5
+#define BGP_INIT_START_TIMER 1
#define BGP_DEFAULT_HOLDTIME 180
#define BGP_DEFAULT_KEEPALIVE 60
#define BGP_DEFAULT_EBGP_ROUTEADV 30
@@ -826,8 +907,10 @@ enum bgp_clear_type
#define BGP_ERR_TCPSIG_FAILED -29
#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -30
#define BGP_ERR_NO_IBGP_WITH_TTLHACK -31
-#define BGP_ERR_MAX -32
+#define BGP_ERR_NO_INTERFACE_CONFIG -32
#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -33
+#define BGP_ERR_AS_OVERRIDE -34
+#define BGP_ERR_MAX -35
extern struct bgp_master *bm;
@@ -842,6 +925,10 @@ extern struct bgp *bgp_get_default (void);
extern struct bgp *bgp_lookup (as_t, const char *);
extern struct bgp *bgp_lookup_by_name (const char *);
extern struct peer *peer_lookup (struct bgp *, union sockunion *);
+extern struct peer *peer_lookup_by_conf_if (struct bgp *, const char *);
+extern struct peer *peer_conf_interface_get(struct bgp *, const char *, afi_t,
+ safi_t);
+extern void bgp_peer_conf_if_to_su_update (struct peer *);
extern struct peer_group *peer_group_lookup (struct bgp *, const char *);
extern struct peer_group *peer_group_get (struct bgp *, const char *);
extern struct peer *peer_lookup_with_open (union sockunion *, as_t, struct in_addr *,
@@ -860,7 +947,10 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *);
extern bgp_peer_sort_t peer_sort (struct peer *peer);
extern int peer_active (struct peer *);
extern int peer_active_nego (struct peer *);
+extern struct peer *peer_create(union sockunion *, const char *, struct bgp *,
+ as_t, as_t, afi_t, safi_t);
extern struct peer *peer_create_accept (struct bgp *);
+extern void peer_xfer_config (struct peer *dst, struct peer *src);
extern char *peer_uptime (time_t, char *, size_t);
extern int bgp_config_write (struct vty *);
extern void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *);
@@ -902,9 +992,12 @@ extern int bgp_timers_unset (struct bgp *);
extern int bgp_default_local_preference_set (struct bgp *, u_int32_t);
extern int bgp_default_local_preference_unset (struct bgp *);
+extern int bgp_update_delay_active (struct bgp *);
+extern int bgp_update_delay_configured (struct bgp *);
extern int peer_rsclient_active (struct peer *);
-
-extern int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
+extern void peer_as_change (struct peer *, as_t);
+extern int peer_remote_as (struct bgp *, union sockunion *,const char *, as_t *,
+ afi_t, safi_t);
extern int peer_group_remote_as (struct bgp *, const char *, as_t *);
extern int peer_delete (struct peer *peer);
extern int peer_group_delete (struct peer_group *);
@@ -913,8 +1006,8 @@ extern int peer_group_remote_as_delete (struct peer_group *);
extern int peer_activate (struct peer *, afi_t, safi_t);
extern int peer_deactivate (struct peer *, afi_t, safi_t);
-extern int peer_group_bind (struct bgp *, union sockunion *, struct peer_group *,
- afi_t, safi_t, as_t *);
+extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *,
+ struct peer_group *, afi_t, safi_t, as_t *);
extern int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *,
afi_t, safi_t);
@@ -984,10 +1077,16 @@ extern int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t);
extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int, u_int16_t);
extern int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
-extern int peer_clear (struct peer *);
+extern int peer_clear (struct peer *, struct listnode **);
extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type);
extern int peer_ttl_security_hops_set (struct peer *, int);
extern int peer_ttl_security_hops_unset (struct peer *);
+extern int bgp_route_map_update_timer (struct thread *thread);
+extern void bgp_route_map_terminate(void);
+
+extern void bgp_scan_finish (void);
+
+extern int peer_cmp (struct peer *p1, struct peer *p2);
#endif /* _QUAGGA_BGPD_H */