#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_mpath.h"
/* Extern from bgp_dump.c */
-extern char *bgp_origin_str[];
-extern char *bgp_origin_long_str[];
+extern const char *bgp_origin_str[];
+extern const char *bgp_origin_long_str[];
\f
static struct bgp_node *
bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p,
{
struct bgp_node *rn;
struct bgp_node *prn = NULL;
-
+
+ assert (table);
+ if (!table)
+ return NULL;
+
if (safi == SAFI_MPLS_VPN)
{
prn = bgp_node_get (table, (struct prefix *) prd);
if (prn->info == NULL)
- prn->info = bgp_table_init ();
+ prn->info = bgp_table_init (afi, safi);
else
bgp_unlock_node (prn);
table = prn->info;
return rn;
}
\f
-/* Allocate new bgp info structure. */
-static struct bgp_info *
-bgp_info_new ()
+/* Allocate bgp_info_extra */
+static struct bgp_info_extra *
+bgp_info_extra_new (void)
{
- struct bgp_info *new;
+ struct bgp_info_extra *new;
+ new = XCALLOC (MTYPE_BGP_ROUTE_EXTRA, sizeof (struct bgp_info_extra));
+ return new;
+}
+
+static void
+bgp_info_extra_free (struct bgp_info_extra **extra)
+{
+ if (extra && *extra)
+ {
+ if ((*extra)->damp_info)
+ bgp_damp_info_free ((*extra)->damp_info, 0);
+
+ (*extra)->damp_info = NULL;
+
+ XFREE (MTYPE_BGP_ROUTE_EXTRA, *extra);
+
+ *extra = NULL;
+ }
+}
- new = XMALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
- memset (new, 0, sizeof (struct bgp_info));
+/* Get bgp_info extra information for the given bgp_info, lazy allocated
+ * if required.
+ */
+struct bgp_info_extra *
+bgp_info_extra_get (struct bgp_info *ri)
+{
+ if (!ri->extra)
+ ri->extra = bgp_info_extra_new();
+ return ri->extra;
+}
- return new;
+/* 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. */
bgp_info_free (struct bgp_info *binfo)
{
if (binfo->attr)
- bgp_attr_unintern (binfo->attr);
-
- if (binfo->damp_info)
- bgp_damp_info_free (binfo->damp_info, 0);
+ bgp_attr_unintern (&binfo->attr);
+
+ bgp_info_extra_free (&binfo->extra);
+ bgp_info_mpath_free (&binfo->mpath);
peer_unlock (binfo->peer); /* bgp_info peer reference */
else
rn->info = ri->next;
+ bgp_info_mpath_dequeue (ri);
bgp_info_unlock (ri);
bgp_unlock_node (rn);
}
void
bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri)
{
- /* leave info in place for now in place for now,
- * bgp_process will reap it later. */
- SET_FLAG (ri->flags, BGP_INFO_REMOVED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_REMOVED);
+ /* set of previous already took care of pcount */
UNSET_FLAG (ri->flags, BGP_INFO_VALID);
}
+/* undo the effects of a previous call to bgp_info_delete; typically
+ called when a route is deleted and then quickly re-added before the
+ deletion has been processed */
+static void
+bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri)
+{
+ bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED);
+ /* unset of previous already took care of pcount */
+ SET_FLAG (ri->flags, BGP_INFO_VALID);
+}
+
+/* Adjust pcount as required */
+static void
+bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
+{
+ assert (rn && rn->table);
+ assert (ri && ri->peer && ri->peer->bgp);
+
+ /* Ignore 'pcount' for RS-client tables */
+ if (rn->table->type != BGP_TABLE_MAIN
+ || ri->peer == ri->peer->bgp->peer_self)
+ return;
+
+ if (BGP_INFO_HOLDDOWN (ri)
+ && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+ {
+
+ UNSET_FLAG (ri->flags, BGP_INFO_COUNTED);
+
+ /* slight hack, but more robust against errors. */
+ if (ri->peer->pcount[rn->table->afi][rn->table->safi])
+ ri->peer->pcount[rn->table->afi][rn->table->safi]--;
+ else
+ {
+ zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s",
+ __func__, ri->peer->host);
+ zlog_backtrace (LOG_WARNING);
+ zlog_warn ("%s: Please report to Quagga bugzilla", __func__);
+ }
+ }
+ else if (!BGP_INFO_HOLDDOWN (ri)
+ && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+ {
+ SET_FLAG (ri->flags, BGP_INFO_COUNTED);
+ ri->peer->pcount[rn->table->afi][rn->table->safi]++;
+ }
+}
+
+
+/* Set/unset bgp_info flags, adjusting any other state as needed.
+ * This is here primarily to keep prefix-count in check.
+ */
+void
+bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
+{
+ SET_FLAG (ri->flags, flag);
+
+ /* early bath if we know it's not a flag that changes useability state */
+ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+ return;
+
+ bgp_pcount_adjust (rn, ri);
+}
+
+void
+bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
+{
+ UNSET_FLAG (ri->flags, flag);
+
+ /* early bath if we know it's not a flag that changes useability state */
+ if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
+ return;
+
+ bgp_pcount_adjust (rn, ri);
+}
+
/* Get MED value. If MED value is missing and "bgp bestpath
missing-as-worst" is specified, treat it as the worst value. */
static u_int32_t
/* Compare two bgp route entity. br is preferable then return 1. */
static int
-bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
+bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
+ int *paths_eq)
{
u_int32_t new_pref;
u_int32_t exist_pref;
u_int32_t new_med;
u_int32_t exist_med;
+ u_int32_t new_weight = 0;
+ u_int32_t exist_weight = 0;
struct in_addr new_id;
struct in_addr exist_id;
int new_cluster;
int internal_as_route = 0;
int confed_as_route = 0;
int ret;
+ uint32_t newm, existm;
+
+ *paths_eq = 0;
/* 0. Null check. */
if (new == NULL)
return 1;
/* 1. Weight check. */
- if (new->attr->weight > exist->attr->weight)
+ if (new->attr->extra)
+ new_weight = new->attr->extra->weight;
+ if (exist->attr->extra)
+ exist_weight = exist->attr->extra->weight;
+ if (new_weight > exist_weight)
return 1;
- if (new->attr->weight < exist->attr->weight)
+ if (new_weight < exist_weight)
return 0;
/* 2. Local preference check. */
/* 4. AS path length check. */
if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
{
+ int exist_hops = aspath_count_hops (exist->attr->aspath);
+ int exist_confeds = aspath_count_confeds (exist->attr->aspath);
+
if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
{
- if ((new->attr->aspath->count +
- new->attr->aspath->confed_count)
- < (exist->attr->aspath->count +
- exist->attr->aspath->confed_count))
+ int aspath_hops;
+
+ aspath_hops = aspath_count_hops (new->attr->aspath);
+ aspath_hops += aspath_count_confeds (new->attr->aspath);
+
+ if ( aspath_hops < (exist_hops + exist_confeds))
return 1;
- if ((new->attr->aspath->count +
- new->attr->aspath->confed_count)
- > (exist->attr->aspath->count +
- exist->attr->aspath->confed_count))
+ if ( aspath_hops > (exist_hops + exist_confeds))
return 0;
}
else
{
- if (new->attr->aspath->count < exist->attr->aspath->count)
+ int newhops = aspath_count_hops (new->attr->aspath);
+
+ if (newhops < exist_hops)
return 1;
- if (new->attr->aspath->count > exist->attr->aspath->count)
+ if (newhops > exist_hops)
return 0;
}
}
return 0;
/* 6. MED check. */
- internal_as_route = (new->attr->aspath->length == 0
- && exist->attr->aspath->length == 0);
- confed_as_route = (new->attr->aspath->length > 0
- && exist->attr->aspath->length > 0
- && new->attr->aspath->count == 0
- && exist->attr->aspath->count == 0);
+ internal_as_route = (aspath_count_hops (new->attr->aspath) == 0
+ && aspath_count_hops (exist->attr->aspath) == 0);
+ confed_as_route = (aspath_count_confeds (new->attr->aspath) > 0
+ && aspath_count_confeds (exist->attr->aspath) > 0
+ && aspath_count_hops (new->attr->aspath) == 0
+ && aspath_count_hops (exist->attr->aspath) == 0);
if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
|| (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
return 0;
/* 8. IGP metric check. */
- if (new->igpmetric < exist->igpmetric)
- return 1;
- if (new->igpmetric > exist->igpmetric)
- return 0;
+ newm = (new->extra ? new->extra->igpmetric : 0);
+ existm = (exist->extra ? exist->extra->igpmetric : 0);
+ if (newm < existm)
+ ret = 1;
+ if (newm > existm)
+ ret = 0;
/* 9. Maximum path check. */
+ if (newm == existm)
+ {
+ if ((peer_sort (new->peer) == BGP_PEER_IBGP))
+ {
+ if (aspath_cmp (new->attr->aspath, exist->attr->aspath))
+ *paths_eq = 1;
+ }
+ else if (new->peer->as == exist->peer->as)
+ *paths_eq = 1;
+ }
+ else
+ {
+ /*
+ * TODO: If unequal cost ibgp multipath is enabled we can
+ * mark the paths as equal here instead of returning
+ */
+ return ret;
+ }
/* 10. If both paths are external, prefer the path that was received
first (the oldest one). This step minimizes route-flap, since a
/* 11. Rourter-ID comparision. */
if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- new_id.s_addr = new->attr->originator_id.s_addr;
+ new_id.s_addr = new->attr->extra->originator_id.s_addr;
else
new_id.s_addr = new->peer->remote_id.s_addr;
if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- exist_id.s_addr = exist->attr->originator_id.s_addr;
+ exist_id.s_addr = exist->attr->extra->originator_id.s_addr;
else
exist_id.s_addr = exist->peer->remote_id.s_addr;
/* 12. Cluster length comparision. */
if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- new_cluster = new->attr->cluster->length;
+ new_cluster = new->attr->extra->cluster->length;
else
new_cluster = 0;
if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- exist_cluster = exist->attr->cluster->length;
+ exist_cluster = exist->attr->extra->cluster->length;
else
exist_cluster = 0;
filter = &peer->filter[afi][safi];
- if (DISTRIBUTE_IN_NAME (filter))
+#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!", \
+ peer->host, #f, F ## _IN_NAME(filter));
+
+ if (DISTRIBUTE_IN_NAME (filter)) {
+ FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
+
if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY)
return FILTER_DENY;
+ }
- if (PREFIX_LIST_IN_NAME (filter))
+ if (PREFIX_LIST_IN_NAME (filter)) {
+ FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
+
if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY)
return FILTER_DENY;
+ }
- if (FILTER_LIST_IN_NAME (filter))
+ if (FILTER_LIST_IN_NAME (filter)) {
+ FILTER_EXIST_WARN(FILTER_LIST, as, filter);
+
if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY)
return FILTER_DENY;
-
+ }
+
return FILTER_PERMIT;
+#undef FILTER_EXIST_WARN
}
static enum filter_type
filter = &peer->filter[afi][safi];
- if (DISTRIBUTE_OUT_NAME (filter))
+#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!", \
+ peer->host, #f, F ## _OUT_NAME(filter));
+
+ if (DISTRIBUTE_OUT_NAME (filter)) {
+ FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
+
if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY)
return FILTER_DENY;
+ }
- if (PREFIX_LIST_OUT_NAME (filter))
+ if (PREFIX_LIST_OUT_NAME (filter)) {
+ FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
+
if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY)
return FILTER_DENY;
+ }
- if (FILTER_LIST_OUT_NAME (filter))
+ if (FILTER_LIST_OUT_NAME (filter)) {
+ FILTER_EXIST_WARN(FILTER_LIST, as, filter);
+
if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY)
return FILTER_DENY;
+ }
return FILTER_PERMIT;
+#undef FILTER_EXIST_WARN
}
/* If community attribute includes no_export then return 1. */
{
struct in_addr cluster_id;
- if (attr->cluster)
+ if (attr->extra && attr->extra->cluster)
{
if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
cluster_id = peer->bgp->cluster_id;
else
cluster_id = peer->bgp->router_id;
- if (cluster_loop_check (attr->cluster, cluster_id))
+ if (cluster_loop_check (attr->extra->cluster, cluster_id))
return 1;
}
return 0;
filter = &peer->filter[afi][safi];
/* Apply default weight value. */
- attr->weight = peer->weight;
+ if (peer->weight)
+ (bgp_attr_extra_get (attr))->weight = peer->weight;
/* Route map apply. */
if (ROUTE_MAP_IN_NAME (filter))
filter = &rsclient->filter[afi][safi];
/* Apply default weight value. */
- attr->weight = peer->weight;
+ if (peer->weight)
+ (bgp_attr_extra_get (attr))->weight = peer->weight;
/* Route map apply. */
if (ROUTE_MAP_IMPORT_NAME (filter))
int ret;
char buf[SU_ADDRSTRLEN];
struct bgp_filter *filter;
- struct bgp_info info;
struct peer *from;
struct bgp *bgp;
- struct attr dummy_attr;
int transparent;
int reflect;
+ struct attr *riattr;
from = ri->peer;
filter = &peer->filter[afi][safi];
bgp = peer->bgp;
+ riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
-#ifdef DISABLE_BGP_ANNOUNCE
- return 0;
-#endif
+ if (DISABLE_BGP_ANNOUNCE)
+ return 0;
/* Do not send announces to RS-clients from the 'normal' bgp_table. */
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
/* If peer's id and route's nexthop are same. draft-ietf-idr-bgp4-23 5.1.3 */
if (p->family == AF_INET
- && IPV4_ADDR_SAME(&peer->remote_id, &ri->attr->nexthop))
+ && IPV4_ADDR_SAME(&peer->remote_id, &riattr->nexthop))
return 0;
#ifdef HAVE_IPV6
if (p->family == AF_INET6
- && IPV6_ADDR_SAME(&peer->remote_id, &ri->attr->nexthop))
+ && IPV6_ADDR_SAME(&peer->remote_id, &riattr->nexthop))
return 0;
#endif
/* Aggregate-address suppress check. */
- if (ri->suppress)
+ if (ri->extra && ri->extra->suppress)
if (! UNSUPPRESS_MAP_NAME (filter))
return 0;
transparent = 0;
/* If community is not disabled check the no-export and local. */
- if (! transparent && bgp_community_filter (peer, ri->attr))
+ if (! transparent && bgp_community_filter (peer, riattr))
return 0;
/* If the attribute has originator-id and it is same as remote
peer's id. */
- if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
+ if (riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
{
- if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->originator_id))
+ if (IPV4_ADDR_SAME (&peer->remote_id, &riattr->extra->originator_id))
{
if (BGP_DEBUG (filter, FILTER))
zlog (peer->log, LOG_DEBUG,
}
/* Output filter check. */
- if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY)
+ if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY)
{
if (BGP_DEBUG (filter, FILTER))
zlog (peer->log, LOG_DEBUG,
#ifdef BGP_SEND_ASPATH_CHECK
/* AS path loop check. */
- if (aspath_loop_check (ri->attr->aspath, peer->as))
+ 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 %d is AS path.",
+ "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
peer->host, peer->as);
return 0;
}
/* If we're a CONFED we need to loop check the CONFED ID too */
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
{
- if (aspath_loop_check(ri->attr->aspath, bgp->confed_id))
+ 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 %d is AS path.",
+ "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
peer->host,
bgp->confed_id);
return 0;
return 0;
}
}
-
+
/* For modify attribute, copy it to temporary structure. */
- *attr = *ri->attr;
-
+ bgp_attr_dup (attr, riattr);
+
/* If local-preference is not set. */
if ((peer_sort (peer) == BGP_PEER_IBGP
|| peer_sort (peer) == BGP_PEER_CONFED)
&& ((p->family == AF_INET && attr->nexthop.s_addr)
#ifdef HAVE_IPV6
|| (p->family == AF_INET6 &&
- ! IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global))
+ ! IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
#endif /* HAVE_IPV6 */
)))
{
|| (p->family == AF_INET && attr->nexthop.s_addr == 0)
#ifdef HAVE_IPV6
|| (p->family == AF_INET6 &&
- IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global))
+ IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
#endif /* HAVE_IPV6 */
|| (peer_sort (peer) == BGP_PEER_EBGP
&& bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0))
if (p->family == AF_INET)
{
if (safi == SAFI_MPLS_VPN)
- memcpy (&attr->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
+ memcpy (&attr->extra->mp_nexthop_global_in, &peer->nexthop.v4,
+ IPV4_MAX_BYTELEN);
else
memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
}
if (p->family == AF_INET6)
{
/* IPv6 global nexthop must be included. */
- memcpy (&attr->mp_nexthop_global, &peer->nexthop.v6_global,
+ memcpy (&attr->extra->mp_nexthop_global, &peer->nexthop.v6_global,
IPV6_MAX_BYTELEN);
- attr->mp_nexthop_len = 16;
+ attr->extra->mp_nexthop_len = 16;
}
#endif /* HAVE_IPV6 */
}
if ( CHECK_FLAG (peer->af_flags[afi][safi],
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) )
{
- if ( IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local) )
- attr->mp_nexthop_len=32;
+ if ( IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_local) )
+ attr->extra->mp_nexthop_len=32;
else
- attr->mp_nexthop_len=16;
+ attr->extra->mp_nexthop_len=16;
}
/* Default nexthop_local treatment for non-RS-Clients */
else
{
/* Link-local address should not be transit to different peer. */
- attr->mp_nexthop_len = 16;
+ attr->extra->mp_nexthop_len = 16;
/* Set link-local address for shared network peer. */
if (peer->shared_network
&& ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
{
- memcpy (&attr->mp_nexthop_local, &peer->nexthop.v6_local,
+ memcpy (&attr->extra->mp_nexthop_local, &peer->nexthop.v6_local,
IPV6_MAX_BYTELEN);
- attr->mp_nexthop_len = 32;
+ attr->extra->mp_nexthop_len = 32;
}
/* If bgpd act as BGP-4+ route-reflector, do not send link-local
address.*/
if (reflect)
- attr->mp_nexthop_len = 16;
+ attr->extra->mp_nexthop_len = 16;
/* If BGP-4+ link-local nexthop is not link-local nexthop. */
if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local))
- attr->mp_nexthop_len = 16;
+ attr->extra->mp_nexthop_len = 16;
}
}
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME (filter)
- || ri->suppress)
+ || (ri->extra && ri->extra->suppress) )
{
+ struct bgp_info info;
+ struct attr dummy_attr = { 0 };
+
info.peer = peer;
info.attr = attr;
if (peer_sort (from) == BGP_PEER_IBGP
&& peer_sort (peer) == BGP_PEER_IBGP)
{
- dummy_attr = *attr;
+ bgp_attr_dup (&dummy_attr, attr);
info.attr = &dummy_attr;
}
SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT);
- if (ri->suppress)
+ if (ri->extra && ri->extra->suppress)
ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info);
else
ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info);
peer->rmap_type = 0;
-
+
+ if (dummy_attr.extra)
+ bgp_attr_extra_free (&dummy_attr);
+
if (ret == RMAP_DENYMATCH)
{
bgp_attr_flush (attr);
struct bgp_filter *filter;
struct bgp_info info;
struct peer *from;
- struct bgp *bgp;
+ struct attr *riattr;
from = ri->peer;
filter = &rsclient->filter[afi][safi];
- bgp = rsclient->bgp;
+ riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
-#ifdef DISABLE_BGP_ANNOUNCE
- return 0;
-#endif
+ if (DISABLE_BGP_ANNOUNCE)
+ return 0;
/* Do not send back route to sender. */
if (from == rsclient)
return 0;
/* Aggregate-address suppress check. */
- if (ri->suppress)
+ if (ri->extra && ri->extra->suppress)
if (! UNSUPPRESS_MAP_NAME (filter))
return 0;
/* If the attribute has originator-id and it is same as remote
peer's id. */
- if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
+ if (riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
{
- if (IPV4_ADDR_SAME (&rsclient->remote_id, &ri->attr->originator_id))
+ if (IPV4_ADDR_SAME (&rsclient->remote_id,
+ &riattr->extra->originator_id))
{
if (BGP_DEBUG (filter, FILTER))
zlog (rsclient->log, LOG_DEBUG,
}
/* Output filter check. */
- if (bgp_output_filter (rsclient, p, ri->attr, afi, safi) == FILTER_DENY)
+ if (bgp_output_filter (rsclient, p, riattr, afi, safi) == FILTER_DENY)
{
if (BGP_DEBUG (filter, FILTER))
zlog (rsclient->log, LOG_DEBUG,
#ifdef BGP_SEND_ASPATH_CHECK
/* AS path loop check. */
- if (aspath_loop_check (ri->attr->aspath, rsclient->as))
+ 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 %d is AS path.",
+ "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
rsclient->host, rsclient->as);
return 0;
}
#endif /* BGP_SEND_ASPATH_CHECK */
/* For modify attribute, copy it to temporary structure. */
- *attr = *ri->attr;
+ bgp_attr_dup (attr, riattr);
/* next-hop-set */
if ((p->family == AF_INET && attr->nexthop.s_addr == 0)
#ifdef HAVE_IPV6
|| (p->family == AF_INET6 &&
- IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global))
+ IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
#endif /* HAVE_IPV6 */
)
{
if (p->family == AF_INET)
{
if (safi == SAFI_MPLS_VPN)
- memcpy (&attr->mp_nexthop_global_in, &rsclient->nexthop.v4,
+ memcpy (&attr->extra->mp_nexthop_global_in, &rsclient->nexthop.v4,
IPV4_MAX_BYTELEN);
else
memcpy (&attr->nexthop, &rsclient->nexthop.v4, IPV4_MAX_BYTELEN);
if (p->family == AF_INET6)
{
/* IPv6 global nexthop must be included. */
- memcpy (&attr->mp_nexthop_global, &rsclient->nexthop.v6_global,
-
+ memcpy (&attr->extra->mp_nexthop_global, &rsclient->nexthop.v6_global,
IPV6_MAX_BYTELEN);
- attr->mp_nexthop_len = 16;
+ attr->extra->mp_nexthop_len = 16;
}
#endif /* HAVE_IPV6 */
}
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
{
+ struct attr_extra *attre = attr->extra;
+
+ assert (attr->extra);
+
/* Left nexthop_local unchanged if so configured. */
if ( CHECK_FLAG (rsclient->af_flags[afi][safi],
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) )
{
- if ( IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local) )
- attr->mp_nexthop_len=32;
+ if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) )
+ attre->mp_nexthop_len=32;
else
- attr->mp_nexthop_len=16;
+ attre->mp_nexthop_len=16;
}
/* Default nexthop_local treatment for RS-Clients */
if (rsclient->shared_network && from->shared_network &&
(rsclient->ifindex == from->ifindex))
{
- if ( IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local) )
- attr->mp_nexthop_len=32;
+ if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) )
+ attre->mp_nexthop_len=32;
else
- attr->mp_nexthop_len=16;
+ attre->mp_nexthop_len=16;
}
/* Set link-local address for shared network peer. */
else if (rsclient->shared_network
&& IN6_IS_ADDR_LINKLOCAL (&rsclient->nexthop.v6_local))
{
- memcpy (&attr->mp_nexthop_local, &rsclient->nexthop.v6_local,
+ memcpy (&attre->mp_nexthop_local, &rsclient->nexthop.v6_local,
IPV6_MAX_BYTELEN);
- attr->mp_nexthop_len = 32;
+ attre->mp_nexthop_len = 32;
}
else
- attr->mp_nexthop_len = 16;
+ attre->mp_nexthop_len = 16;
}
}
attr->aspath = aspath_empty_get ();
/* Route map & unsuppress-map apply. */
- if (ROUTE_MAP_OUT_NAME (filter) || ri->suppress)
+ if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) )
{
info.peer = rsclient;
info.attr = attr;
SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_OUT);
- if (ri->suppress)
+ if (ri->extra && ri->extra->suppress)
ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info);
else
ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info);
};
static void
-bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, struct bgp_info_pair *result)
+bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
+ struct bgp_maxpaths_cfg *mpath_cfg,
+ struct bgp_info_pair *result)
{
struct bgp_info *new_select;
struct bgp_info *old_select;
struct bgp_info *ri1;
struct bgp_info *ri2;
struct bgp_info *nextri = NULL;
-
+ int paths_eq, do_mpath;
+ struct list mp_list;
+
+ bgp_mp_list_init (&mp_list);
+ do_mpath = (mpath_cfg->maxpaths_ebgp != BGP_DEFAULT_MAXPATHS ||
+ mpath_cfg->maxpaths_ibgp != BGP_DEFAULT_MAXPATHS);
+
/* bgp deterministic-med */
new_select = NULL;
if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
continue;
new_select = ri1;
+ if (do_mpath)
+ bgp_mp_list_add (&mp_list, ri1);
+ old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL;
if (ri1->next)
for (ri2 = ri1->next; ri2; ri2 = ri2->next)
{
|| aspath_cmp_left_confed (ri1->attr->aspath,
ri2->attr->aspath))
{
- if (bgp_info_cmp (bgp, ri2, new_select))
+ if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED))
+ old_select = ri2;
+ if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq))
{
- UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
new_select = ri2;
+ if (do_mpath && !paths_eq)
+ {
+ bgp_mp_list_clear (&mp_list);
+ bgp_mp_list_add (&mp_list, ri2);
+ }
}
- SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK);
+ if (do_mpath && paths_eq)
+ bgp_mp_list_add (&mp_list, ri2);
+
+ bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK);
}
}
- SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK);
- SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
+
+ bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
+ bgp_mp_list_clear (&mp_list);
}
/* Check old selected route and new selected route. */
if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
&& (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))
{
- UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
continue;
}
- UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
- UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED);
+
+ if (bgp_info_cmp (bgp, ri, new_select, &paths_eq))
+ {
+ if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+ bgp_mp_dmed_deselect (new_select);
+
+ new_select = ri;
+
+ if (do_mpath && !paths_eq)
+ {
+ bgp_mp_list_clear (&mp_list);
+ bgp_mp_list_add (&mp_list, ri);
+ }
+ }
+ else if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+ bgp_mp_dmed_deselect (ri);
- if (bgp_info_cmp (bgp, ri, new_select))
- new_select = ri;
+ if (do_mpath && paths_eq)
+ bgp_mp_list_add (&mp_list, ri);
}
- result->old = old_select;
- result->new = new_select;
- return;
+ if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+ bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
+
+ bgp_info_mpath_aggregate_update (new_select, old_select);
+ bgp_mp_list_clear (&mp_list);
+
+ result->old = old_select;
+ result->new = new_select;
+
+ return;
}
static int
bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected,
- struct bgp_node *rn, struct attr *attr, afi_t afi, safi_t safi)
- {
+ struct bgp_node *rn, afi_t afi, safi_t safi)
+{
struct prefix *p;
+ struct attr attr = { 0 };
p = &rn->p;
- /* Announce route to Established peer. */
- if (peer->status != Established)
+ /* Announce route to Established peer. */
+ if (peer->status != Established)
return 0;
- /* Address family configuration check. */
- if (! peer->afc_nego[afi][safi])
+ /* Address family configuration check. */
+ if (! peer->afc_nego[afi][safi])
return 0;
- /* First update is deferred until ORF or ROUTE-REFRESH is received */
+ /* First update is deferred until ORF or ROUTE-REFRESH is received */
if (CHECK_FLAG (peer->af_sflags[afi][safi],
PEER_STATUS_ORF_WAIT_REFRESH))
return 0;
case BGP_TABLE_MAIN:
/* Announcement to peer->conf. If the route is filtered,
withdraw it. */
- if (selected && bgp_announce_check (selected, peer, p, attr, afi, safi))
- bgp_adj_out_set (rn, peer, p, attr, afi, safi, selected);
+ if (selected && bgp_announce_check (selected, peer, p, &attr, afi, safi))
+ bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected);
else
bgp_adj_out_unset (rn, peer, p, afi, safi);
break;
case BGP_TABLE_RSCLIENT:
/* Announcement to peer->conf. If the route is filtered,
withdraw it. */
- if (selected && bgp_announce_check_rsclient
- (selected, peer, p, attr, afi, safi))
- bgp_adj_out_set (rn, peer, p, attr, afi, safi, selected);
- else
- bgp_adj_out_unset (rn, peer, p, afi, safi);
+ if (selected &&
+ bgp_announce_check_rsclient (selected, peer, p, &attr, afi, safi))
+ bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected);
+ else
+ bgp_adj_out_unset (rn, peer, p, afi, safi);
break;
}
+
+ bgp_attr_extra_free (&attr);
+
return 0;
}
};
static wq_item_status
-bgp_process_rsclient (struct bgp_process_queue *pq)
+bgp_process_rsclient (struct work_queue *wq, void *data)
{
+ struct bgp_process_queue *pq = data;
struct bgp *bgp = pq->bgp;
struct bgp_node *rn = pq->rn;
afi_t afi = pq->afi;
struct bgp_info *new_select;
struct bgp_info *old_select;
struct bgp_info_pair old_and_new;
- struct attr attr;
struct listnode *node, *nnode;
struct peer *rsclient = rn->table->owner;
- /* we shouldn't run if the clear_route_node queue is still running
- * or scheduled to run, or we can race with session coming up
- * and adding routes back before we've cleared them
- */
- if (bm->clear_node_queue && bm->clear_node_queue->thread)
- return WQ_QUEUE_BLOCKED;
-
/* Best path selection. */
- bgp_best_selection (bgp, rn, &old_and_new);
+ bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
new_select = old_and_new.new;
old_select = old_and_new.old;
if (CHECK_FLAG (rsclient->sflags, PEER_STATUS_GROUP))
{
- for (ALL_LIST_ELEMENTS (rsclient->group->peer, node, nnode, rsclient))
- {
- /* Nothing to do. */
- if (old_select && old_select == new_select)
- if (!CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
- continue;
-
- if (old_select)
- UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
- if (new_select)
- {
- SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
- UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
- }
-
- bgp_process_announce_selected (rsclient, new_select, rn, &attr,
- afi, safi);
- }
+ if (rsclient->group)
+ for (ALL_LIST_ELEMENTS (rsclient->group->peer, node, nnode, rsclient))
+ {
+ /* Nothing to do. */
+ if (old_select && old_select == new_select)
+ if (!CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
+ continue;
+
+ if (old_select)
+ bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
+ if (new_select)
+ {
+ bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+ UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+ }
+
+ bgp_process_announce_selected (rsclient, new_select, rn,
+ afi, safi);
+ }
}
else
{
- bgp_process_announce_selected (rsclient, new_select, rn,
- &attr, afi, safi);
+ if (old_select)
+ bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
+ if (new_select)
+ {
+ bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+ UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+ }
+ bgp_process_announce_selected (rsclient, new_select, rn, afi, safi);
}
if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED))
}
static wq_item_status
-bgp_process_main (struct bgp_process_queue *pq)
+bgp_process_main (struct work_queue *wq, void *data)
{
+ struct bgp_process_queue *pq = data;
struct bgp *bgp = pq->bgp;
struct bgp_node *rn = pq->rn;
afi_t afi = pq->afi;
struct bgp_info_pair old_and_new;
struct listnode *node, *nnode;
struct peer *peer;
- struct attr attr;
- /* we shouldn't run if the clear_route_node queue is still running
- * or scheduled to run, or we can race with session coming up
- * and adding routes back before we've cleared them
- */
- if (bm->clear_node_queue && bm->clear_node_queue->thread)
- return WQ_QUEUE_BLOCKED;
-
/* Best path selection. */
- bgp_best_selection (bgp, rn, &old_and_new);
+ bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
old_select = old_and_new.old;
new_select = old_and_new.new;
{
if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
{
- if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))
- bgp_zebra_announce (p, old_select, bgp);
+ 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);
+ UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
return WQ_SUCCESS;
}
}
if (old_select)
- UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
if (new_select)
{
- SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
- UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
+ bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+ UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
}
/* Check each BGP peer. */
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
- bgp_process_announce_selected (peer, new_select, rn, &attr, afi, safi);
+ bgp_process_announce_selected (peer, new_select, rn, afi, safi);
}
/* FIB update. */
- if (safi == SAFI_UNICAST && ! bgp->name &&
- ! bgp_option_check (BGP_OPT_NO_FIB))
+ if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && (! bgp->name &&
+ ! bgp_option_check (BGP_OPT_NO_FIB)))
{
if (new_select
&& new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_announce (p, new_select, bgp);
+ bgp_zebra_announce (p, new_select, bgp, safi);
else
{
/* Withdraw the route from the kernel. */
if (old_select
&& old_select->type == ZEBRA_ROUTE_BGP
&& old_select->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_withdraw (p, old_select);
+ bgp_zebra_withdraw (p, old_select, safi);
}
}
}
static void
-bgp_processq_del (struct bgp_process_queue *pq)
+bgp_processq_del (struct work_queue *wq, void *data)
{
+ struct bgp_process_queue *pq = data;
+ struct bgp_table *table = pq->rn->table;
+
+ bgp_unlock (pq->bgp);
bgp_unlock_node (pq->rn);
+ bgp_table_unlock (table);
XFREE (MTYPE_BGP_PROCESS_QUEUE, pq);
}
}
bm->process_main_queue->spec.workfunc = &bgp_process_main;
- bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
- bm->process_rsclient_queue->spec.del_item_data
- = bm->process_main_queue->spec.del_item_data;
- bm->process_main_queue->spec.max_retries
- = bm->process_main_queue->spec.max_retries = 0;
- bm->process_rsclient_queue->spec.hold
- = bm->process_main_queue->spec.hold = 500;
- bm->process_rsclient_queue->spec.delay
- = bm->process_main_queue->spec.delay = 10;
+ bm->process_main_queue->spec.max_retries = 0;
+ bm->process_main_queue->spec.hold = 50;
+
+ memcpy (bm->process_rsclient_queue, bm->process_main_queue,
+ sizeof (struct work_queue *));
+ bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
}
void
sizeof (struct bgp_process_queue));
if (!pqnode)
return;
-
- pqnode->rn = bgp_lock_node (rn); /* unlocked by bgp_processq_del */
+
+ /* all unlocked in bgp_processq_del */
+ bgp_table_lock (rn->table);
+ pqnode->rn = bgp_lock_node (rn);
pqnode->bgp = bgp;
+ bgp_lock (bgp);
pqnode->afi = afi;
pqnode->safi = safi;
u_int8_t ndata[7];
if (safi == SAFI_MPLS_VPN)
- safi = BGP_SAFI_VPNV4;
+ safi = SAFI_MPLS_LABELED_VPN;
ndata[0] = (afi >> 8);
ndata[1] = afi;
bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
afi_t afi, safi_t safi)
{
- if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
- && rn->table->type == BGP_TABLE_MAIN)
- {
- /* Ignore 'pcount' for RS-client tables */
- if ( rn->table->type == BGP_TABLE_MAIN)
- {
- peer->pcount[afi][safi]--;
- bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
- }
- }
+ bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
+
+ if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+ bgp_info_delete (rn, ri); /* keep historical info */
+
bgp_process (peer->bgp, rn, afi, safi);
- bgp_info_delete (rn, ri);
}
static void
bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
afi_t afi, safi_t safi)
{
- int valid;
int status = BGP_DAMP_NONE;
- if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
- && rn->table->type == BGP_TABLE_MAIN)
- {
- /* Ignore 'pcount' for RS-client tables */
- if ( rn->table->type == BGP_TABLE_MAIN)
- {
- peer->pcount[afi][safi]--;
- bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
- }
- }
-
/* apply dampening, if result is suppressed, we'll be retaining
* the bgp_info in the RIB for historical reference.
*/
&& peer_sort (peer) == BGP_PEER_EBGP)
if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0))
== BGP_DAMP_SUPPRESSED)
- return;
-
- bgp_process (peer->bgp, rn, afi, safi);
-
- if (status != BGP_DAMP_USED)
- bgp_info_delete (rn, ri);
+ {
+ bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
+ return;
+ }
+
+ bgp_rib_remove (rn, ri, peer, afi, safi);
}
static void
{
struct bgp_node *rn;
struct bgp *bgp;
- struct attr new_attr;
+ struct attr new_attr = { 0 };
struct attr *attr_new;
struct attr *attr_new2;
struct bgp_info *ri;
/* Route reflector originator ID check. */
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)
- && IPV4_ADDR_SAME (&rsclient->remote_id, &attr->originator_id))
+ && IPV4_ADDR_SAME (&rsclient->remote_id, &attr->extra->originator_id))
{
reason = "originator is us;";
goto filtered;
}
-
- new_attr = *attr;
+
+ bgp_attr_dup (&new_attr, attr);
/* Apply export policy. */
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) &&
}
attr_new2 = bgp_attr_intern (&new_attr);
-
+
/* Apply import policy. */
if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
{
- bgp_attr_unintern (attr_new2);
+ bgp_attr_unintern (&attr_new2);
reason = "import-policy;";
goto filtered;
}
attr_new = bgp_attr_intern (&new_attr);
- bgp_attr_unintern (attr_new2);
+ bgp_attr_unintern (&attr_new2);
/* IPv4 unicast next hop check. */
- if (afi == AFI_IP && safi == SAFI_UNICAST)
+ if ((afi == AFI_IP) && ((safi == SAFI_UNICAST) || safi == SAFI_MULTICAST))
{
- /* Next hop must not be 0.0.0.0 nor Class E address. */
+ /* Next hop must not be 0.0.0.0 nor Class D/E address. */
if (new_attr.nexthop.s_addr == 0
- || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
+ || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
{
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
reason = "martian next-hop;";
goto filtered;
}
}
-
+
+ /* new_attr isn't passed to any functions after here */
+ bgp_attr_extra_free (&new_attr);
+
/* If the update is implicit withdraw. */
if (ri)
{
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Same attribute comes in. */
- if (attrhash_cmp (ri->attr, attr_new))
+ if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
+ && attrhash_cmp (ri->attr, attr_new))
{
- UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
if (BGP_DEBUG (update, UPDATE_IN))
zlog (peer->log, LOG_DEBUG,
inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
p->prefixlen, rsclient->host);
- bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
+ bgp_unlock_node (rn);
+ bgp_attr_unintern (&attr_new);
- return;
+ return;
}
+ /* Withdraw/Announce before we fully processed the withdraw */
+ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+ 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",
p->prefixlen, rsclient->host);
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Update to new attribute. */
- bgp_attr_unintern (ri->attr);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
- memcpy (ri->tag, tag, 3);
+ memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
- SET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
/* Process change. */
bgp_process (bgp, rn, afi, safi);
new->sub_type = sub_type;
new->peer = peer;
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
- memcpy (new->tag, tag, 3);
+ memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
- SET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, new, BGP_INFO_VALID);
/* Register new BGP information. */
bgp_info_add (rn, new);
/* Process change. */
bgp_process (bgp, rn, afi, safi);
-
+
+ bgp_attr_extra_free (&new_attr);
+
return;
filtered:
bgp_rib_remove (rn, ri, peer, afi, safi);
bgp_unlock_node (rn);
-
+
+ if (new_attr.extra)
+ bgp_attr_extra_free (&new_attr);
+
return;
}
bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
struct peer *peer, struct prefix *p, int type, int sub_type,
struct prefix_rd *prd, u_char *tag)
- {
+{
struct bgp_node *rn;
struct bgp_info *ri;
char buf[SU_ADDRSTRLEN];
if (rsclient == peer)
- return;
+ return;
rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, prd);
p->prefixlen);
/* Unlock bgp_node_get() lock. */
- bgp_unlock_node (rn);
- }
+ bgp_unlock_node (rn);
+}
static int
bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
int aspath_loop_count = 0;
struct bgp_node *rn;
struct bgp *bgp;
- struct attr new_attr;
+ struct attr new_attr = { 0 };
struct attr *attr_new;
struct bgp_info *ri;
struct bgp_info *new;
bgp = peer->bgp;
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
-
+
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
/* Route reflector originator ID check. */
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)
- && IPV4_ADDR_SAME (&bgp->router_id, &attr->originator_id))
+ && IPV4_ADDR_SAME (&bgp->router_id, &attr->extra->originator_id))
{
reason = "originator is us;";
goto filtered;
}
/* Apply incoming route-map. */
- new_attr = *attr;
+ bgp_attr_dup (&new_attr, attr);
if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY)
{
/* If the peer is EBGP and nexthop is not on connected route,
discard it. */
if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1
- && ! bgp_nexthop_check_ebgp (afi, &new_attr)
+ && ! bgp_nexthop_onlink (afi, &new_attr)
&& ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
{
reason = "non-connected next-hop;";
goto filtered;
}
- /* Next hop must not be 0.0.0.0 nor Class E address. Next hop
+ /* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop
must not be my own address. */
if (bgp_nexthop_self (afi, &new_attr)
|| new_attr.nexthop.s_addr == 0
- || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
+ || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
{
reason = "martian next-hop;";
goto filtered;
/* If the update is implicit withdraw. */
if (ri)
{
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Same attribute comes in. */
- if (attrhash_cmp (ri->attr, attr_new))
+ if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
+ && attrhash_cmp (ri->attr, attr_new))
{
- UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer_sort (peer) == BGP_PEER_EBGP
inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
p->prefixlen);
- peer->pcount[afi][safi]++;
- ret = bgp_damp_update (ri, rn, afi, safi);
- if (ret != BGP_DAMP_SUPPRESSED)
- {
- bgp_aggregate_increment (bgp, p, ri, afi, safi);
- bgp_process (bgp, rn, afi, safi);
- }
+ if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED)
+ {
+ bgp_aggregate_increment (bgp, p, ri, afi, safi);
+ bgp_process (bgp, rn, afi, safi);
+ }
}
- else
+ else /* Duplicate - odd */
{
if (BGP_DEBUG (update, UPDATE_IN))
zlog (peer->log, LOG_DEBUG,
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
{
- UNSET_FLAG (ri->flags, BGP_INFO_STALE);
- peer->pcount[afi][safi]++;
+ bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
+ bgp_process (bgp, rn, afi, safi);
}
}
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
+ bgp_attr_extra_free (&new_attr);
+
return 0;
}
+ /* 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);
+ bgp_info_restore (rn, ri);
+ }
+
/* Received Logging. */
if (BGP_DEBUG (update, UPDATE_IN))
zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
/* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
- {
- UNSET_FLAG (ri->flags, BGP_INFO_STALE);
- peer->pcount[afi][safi]++;
- }
+ bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
-
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
+
+ /* implicit withdraw, decrement aggregate and pcount here.
+ * only if update is accepted, they'll increment below.
+ */
+ bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+
/* Update bgp route dampening information. */
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer_sort (peer) == BGP_PEER_EBGP)
information. */
if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
bgp_damp_withdraw (ri, rn, afi, safi, 1);
- else
- peer->pcount[afi][safi]++;
}
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-
/* Update to new attribute. */
- bgp_attr_unintern (ri->attr);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
- memcpy (ri->tag, tag, 3);
+ memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
/* Update bgp route dampening information. */
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
if (ret == BGP_DAMP_SUPPRESSED)
{
bgp_unlock_node (rn);
+ bgp_attr_extra_free (&new_attr);
return 0;
}
}
if ((afi == AFI_IP || afi == AFI_IP6)
&& safi == SAFI_UNICAST
&& (peer_sort (peer) == BGP_PEER_IBGP
+ || peer_sort (peer) == BGP_PEER_CONFED
|| (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
{
if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL))
- SET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
else
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
}
else
- SET_FLAG (ri->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
/* Process change. */
bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
+ bgp_attr_extra_free (&new_attr);
+
return 0;
}
p->prefixlen);
}
- /* Increment prefix counter */
- peer->pcount[afi][safi]++;
-
/* 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 = time (NULL);
+ new->uptime = bgp_clock ();
/* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN)
- memcpy (new->tag, tag, 3);
+ memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
/* Nexthop reachability check. */
if ((afi == AFI_IP || afi == AFI_IP6)
&& safi == SAFI_UNICAST
&& (peer_sort (peer) == BGP_PEER_IBGP
+ || peer_sort (peer) == BGP_PEER_CONFED
|| (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
{
if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL))
- SET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, new, BGP_INFO_VALID);
else
- UNSET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
}
else
- SET_FLAG (new->flags, BGP_INFO_VALID);
+ bgp_info_set_flag (rn, new, BGP_INFO_VALID);
- /* Aggregate address increment. */
+ /* Increment prefix */
bgp_aggregate_increment (bgp, p, new, afi, safi);
/* Register new BGP information. */
/* route_node_get lock */
bgp_unlock_node (rn);
+ bgp_attr_extra_free (&new_attr);
+
/* If maximum prefix count is configured and current prefix
count exeed it. */
if (bgp_maximum_prefix_overflow (peer, afi, safi, 0))
bgp_rib_remove (rn, ri, peer, afi, safi);
bgp_unlock_node (rn);
-
+
+ bgp_attr_extra_free (&new_attr);
+
return 0;
}
bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
{
struct bgp *bgp;
- struct attr attr;
- struct aspath *aspath;
+ struct attr attr = { 0 };
+ struct aspath *aspath = { 0 };
struct prefix p;
struct bgp_info binfo;
struct peer *from;
int ret = RMAP_DENYMATCH;
-
+
+ if (!(afi == AFI_IP || afi == AFI_IP6))
+ return;
+
bgp = peer->bgp;
from = bgp->peer_self;
-
+
bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
aspath = attr.aspath;
attr.local_pref = bgp->default_local_pref;
#ifdef HAVE_IPV6
else if (afi == AFI_IP6)
{
+ struct attr_extra *ae;
+ attr.extra = NULL;
+
+ ae = bgp_attr_extra_get (&attr);
+ attr.extra = ae;
+
str2prefix ("::/0", &p);
/* IPv6 global nexthop must be included. */
- memcpy (&attr.mp_nexthop_global, &peer->nexthop.v6_global,
+ memcpy (&ae->mp_nexthop_global, &peer->nexthop.v6_global,
IPV6_MAX_BYTELEN);
- attr.mp_nexthop_len = 16;
+ ae->mp_nexthop_len = 16;
/* If the peer is on shared nextwork and we have link-local
nexthop set it. */
if (peer->shared_network
&& !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
{
- memcpy (&attr.mp_nexthop_local, &peer->nexthop.v6_local,
+ memcpy (&ae->mp_nexthop_local, &peer->nexthop.v6_local,
IPV6_MAX_BYTELEN);
- attr.mp_nexthop_len = 32;
+ ae->mp_nexthop_len = 32;
}
}
#endif /* HAVE_IPV6 */
- else
- return;
if (peer->default_rmap[afi][safi].name)
{
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE);
bgp_default_update_send (peer, &attr, afi, safi, from);
}
-
- aspath_unintern (aspath);
+
+ bgp_attr_extra_free (&attr);
+ aspath_unintern (&aspath);
}
\f
static void
{
struct bgp_node *rn;
struct bgp_info *ri;
- struct attr attr;
-
+ struct attr attr = { 0 };
+
if (! table)
table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi];
bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri);
else
bgp_adj_out_unset (rn, peer, &rn->p, afi, safi);
+
+ bgp_attr_extra_free (&attr);
}
}
bgp_soft_reconfig_table (peer, afi, safi, table);
}
\f
+
struct bgp_clear_node_queue
{
struct bgp_node *rn;
- struct peer *peer;
- afi_t afi;
- safi_t safi;
+ enum bgp_clear_route_type purpose;
};
static wq_item_status
-bgp_clear_route_node (struct bgp_clear_node_queue *cq)
+bgp_clear_route_node (struct work_queue *wq, void *data)
{
- struct bgp_adj_in *ain;
- struct bgp_adj_out *aout;
+ struct bgp_clear_node_queue *cnq = data;
+ struct bgp_node *rn = cnq->rn;
+ struct peer *peer = wq->spec.data;
struct bgp_info *ri;
+ afi_t afi = rn->table->afi;
+ safi_t safi = rn->table->safi;
- assert (cq->rn && cq->peer);
+ assert (rn && peer);
- for (ri = cq->rn->info; ri; ri = ri->next)
- if (ri->peer == cq->peer)
+ for (ri = rn->info; ri; ri = ri->next)
+ if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
{
/* graceful restart STALE flag set. */
- if (CHECK_FLAG (cq->peer->sflags, PEER_STATUS_NSF_WAIT)
- && cq->peer->nsf[cq->afi][cq->safi]
+ if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)
+ && peer->nsf[afi][safi]
&& ! CHECK_FLAG (ri->flags, BGP_INFO_STALE)
- && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
- && ! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
- {
- SET_FLAG (ri->flags, BGP_INFO_STALE);
- cq->peer->pcount[cq->afi][cq->safi]--;
- }
+ && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ bgp_info_set_flag (rn, ri, BGP_INFO_STALE);
else
- bgp_rib_remove (cq->rn, ri, cq->peer, cq->afi, cq->safi);
- break;
- }
- for (ain = cq->rn->adj_in; ain; ain = ain->next)
- if (ain->peer == cq->peer)
- {
- bgp_adj_in_remove (cq->rn, ain);
- bgp_unlock_node (cq->rn);
- break;
- }
- for (aout = cq->rn->adj_out; aout; aout = aout->next)
- if (aout->peer == cq->peer)
- {
- bgp_adj_out_remove (cq->rn, aout, cq->peer, cq->afi, cq->safi);
- bgp_unlock_node (cq->rn);
+ bgp_rib_remove (rn, ri, peer, afi, safi);
break;
}
return WQ_SUCCESS;
}
static void
-bgp_clear_node_queue_del (struct bgp_clear_node_queue *cq)
+bgp_clear_node_queue_del (struct work_queue *wq, void *data)
{
- bgp_unlock_node (cq->rn);
- peer_unlock (cq->peer); /* bgp_clear_node_queue_del */
- XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cq);
+ struct bgp_clear_node_queue *cnq = data;
+ struct bgp_node *rn = cnq->rn;
+ struct bgp_table *table = rn->table;
+
+ bgp_unlock_node (rn);
+ bgp_table_unlock (table);
+ XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
}
static void
bgp_clear_node_complete (struct work_queue *wq)
{
- /* unplug the 2 processing queues */
- if (bm->process_main_queue)
- work_queue_unplug (bm->process_main_queue);
- if (bm->process_rsclient_queue)
- work_queue_unplug (bm->process_rsclient_queue);
+ struct peer *peer = wq->spec.data;
+
+ /* Tickle FSM to start moving again */
+ BGP_EVENT_ADD (peer, Clearing_Completed);
+
+ peer_unlock (peer); /* bgp_clear_route */
}
static void
-bgp_clear_node_queue_init (void)
+bgp_clear_node_queue_init (struct peer *peer)
{
- if ( (bm->clear_node_queue
- = work_queue_new (bm->master, "clear_route_node")) == NULL)
+ char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
+
+ snprintf (wname, sizeof(wname), "clear %s", peer->host);
+#undef CLEAR_QUEUE_NAME_LEN
+
+ if ( (peer->clear_node_queue = work_queue_new (bm->master, wname)) == NULL)
{
zlog_err ("%s: Failed to allocate work queue", __func__);
exit (1);
}
- bm->clear_node_queue->spec.hold = 10;
- bm->clear_node_queue->spec.delay = 0; /* no gathering to be gained */
- bm->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
- bm->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
- bm->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
- bm->clear_node_queue->spec.max_retries = 0;
+ peer->clear_node_queue->spec.hold = 10;
+ peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
+ peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
+ peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
+ peer->clear_node_queue->spec.max_retries = 0;
+
+ /* we only 'lock' this peer reference when the queue is actually active */
+ peer->clear_node_queue->spec.data = peer;
}
static void
bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_table *table, struct peer *rsclient)
+ struct bgp_table *table, struct peer *rsclient,
+ enum bgp_clear_route_type purpose)
{
- struct bgp_clear_node_queue *cqnode;
struct bgp_node *rn;
+
if (! table)
table = (rsclient) ? rsclient->rib[afi][safi] : peer->bgp->rib[afi][safi];
-
+
/* If still no table => afi/safi isn't configured at all or smth. */
if (! table)
return;
-
- if (bm->clear_node_queue == NULL)
- bgp_clear_node_queue_init ();
-
- /* plug the two bgp_process queues to avoid any chance of racing
- * with a session coming back up and adding routes before we've
- * cleared them all. We'll unplug them with completion callback.
- */
- if (bm->process_main_queue)
- work_queue_plug (bm->process_main_queue);
- if (bm->process_rsclient_queue)
- work_queue_plug (bm->process_rsclient_queue);
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
{
- if (rn->info == NULL)
- continue;
+ struct bgp_info *ri;
+ struct bgp_adj_in *ain;
+ struct bgp_adj_out *aout;
- if ( (cqnode = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE,
- sizeof (struct bgp_clear_node_queue))) == NULL)
+ if (rn->info == NULL)
continue;
-
- cqnode->rn = bgp_lock_node (rn); /* unlocked: bgp_clear_node_queue_del */
- cqnode->afi = afi;
- cqnode->safi = safi;
- cqnode->peer = peer_lock (peer); /* bgp_clear_node_queue_del */
- work_queue_add (bm->clear_node_queue, cqnode);
+
+ /* XXX:TODO: This is suboptimal, every non-empty route_node is
+ * queued for every clearing peer, regardless of whether it is
+ * relevant to the peer at hand.
+ *
+ * Overview: There are 3 different indices which need to be
+ * scrubbed, potentially, when a peer is removed:
+ *
+ * 1 peer's routes visible via the RIB (ie accepted routes)
+ * 2 peer's routes visible by the (optional) peer's adj-in index
+ * 3 other routes visible by the peer's adj-out index
+ *
+ * 3 there is no hurry in scrubbing, once the struct peer is
+ * removed from bgp->peer, we could just GC such deleted peer's
+ * adj-outs at our leisure.
+ *
+ * 1 and 2 must be 'scrubbed' in some way, at least made
+ * invisible via RIB index before peer session is allowed to be
+ * brought back up. So one needs to know when such a 'search' is
+ * complete.
+ *
+ * Ideally:
+ *
+ * - there'd be a single global queue or a single RIB walker
+ * - rather than tracking which route_nodes still need to be
+ * examined on a peer basis, we'd track which peers still
+ * aren't cleared
+ *
+ * Given that our per-peer prefix-counts now should be reliable,
+ * this may actually be achievable. It doesn't seem to be a huge
+ * problem at this time,
+ */
+ for (ri = rn->info; ri; ri = ri->next)
+ if (ri->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+ {
+ struct bgp_clear_node_queue *cnq;
+
+ /* both unlocked in bgp_clear_node_queue_del */
+ bgp_table_lock (rn->table);
+ bgp_lock_node (rn);
+ cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE,
+ sizeof (struct bgp_clear_node_queue));
+ cnq->rn = rn;
+ cnq->purpose = purpose;
+ work_queue_add (peer->clear_node_queue, cnq);
+ break;
+ }
+
+ for (ain = rn->adj_in; ain; ain = ain->next)
+ if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+ {
+ bgp_adj_in_remove (rn, ain);
+ bgp_unlock_node (rn);
+ break;
+ }
+ for (aout = rn->adj_out; aout; aout = aout->next)
+ if (aout->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+ {
+ bgp_adj_out_remove (rn, aout, peer, afi, safi);
+ bgp_unlock_node (rn);
+ break;
+ }
}
return;
}
void
-bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
+bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi,
+ enum bgp_clear_route_type purpose)
{
struct bgp_node *rn;
struct bgp_table *table;
struct peer *rsclient;
struct listnode *node, *nnode;
- if (safi != SAFI_MPLS_VPN)
- bgp_clear_route_table (peer, afi, safi, NULL, NULL);
- else
- for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
- rn = bgp_route_next (rn))
- if ((table = rn->info) != NULL)
- bgp_clear_route_table (peer, afi, safi, table, NULL);
+ if (peer->clear_node_queue == NULL)
+ bgp_clear_node_queue_init (peer);
+
+ /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
+ * Idle until it receives a Clearing_Completed event. This protects
+ * against peers which flap faster than we can we clear, which could
+ * lead to:
+ *
+ * a) race with routes from the new session being installed before
+ * clear_route_node visits the node (to delete the route of that
+ * peer)
+ * b) resource exhaustion, clear_route_node likely leads to an entry
+ * on the process_main queue. Fast-flapping could cause that queue
+ * to grow and grow.
+ */
+ if (!peer->clear_node_queue->thread)
+ peer_lock (peer); /* bgp_clear_node_complete */
- for (ALL_LIST_ELEMENTS (peer->bgp->rsclient, node, nnode, rsclient))
+ switch (purpose)
{
- if (CHECK_FLAG(rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_clear_route_table (peer, afi, safi, NULL, rsclient);
+ case BGP_CLEAR_ROUTE_NORMAL:
+ if (safi != SAFI_MPLS_VPN)
+ bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose);
+ else
+ for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
+ rn = bgp_route_next (rn))
+ if ((table = rn->info) != NULL)
+ bgp_clear_route_table (peer, afi, safi, table, NULL, purpose);
+
+ for (ALL_LIST_ELEMENTS (peer->bgp->rsclient, node, nnode, rsclient))
+ if (CHECK_FLAG(rsclient->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ bgp_clear_route_table (peer, afi, safi, NULL, rsclient, purpose);
+ break;
+
+ case BGP_CLEAR_ROUTE_MY_RSCLIENT:
+ bgp_clear_route_table (peer, afi, safi, NULL, peer, purpose);
+ break;
+
+ default:
+ assert (0);
+ break;
}
+
+ /* If no routes were cleared, nothing was added to workqueue, the
+ * completion function won't be run by workqueue code - call it here.
+ * XXX: Actually, this assumption doesn't hold, see
+ * bgp_clear_route_table(), we queue all non-empty nodes.
+ *
+ * Additionally, there is a presumption in FSM that clearing is only
+ * really needed if peer state is Established - peers in
+ * pre-Established states shouldn't have any route-update state
+ * associated with them (in or out).
+ *
+ * We still can get here in pre-Established though, through
+ * peer_delete -> bgp_fsm_change_status, so this is a useful sanity
+ * check to ensure the assumption above holds.
+ *
+ * At some future point, this check could be move to the top of the
+ * function, and do a quick early-return when state is
+ * pre-Established, avoiding above list and table scans. Once we're
+ * sure it is safe..
+ */
+ if (!peer->clear_node_queue->thread)
+ bgp_clear_node_complete (peer->clear_node_queue);
}
void
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- bgp_clear_route (peer, afi, safi);
+ bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
}
void
\f
/* Delete all kernel routes. */
void
-bgp_cleanup_routes ()
+bgp_cleanup_routes (void)
{
struct bgp *bgp;
struct listnode *node, *nnode;
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
&& ri->type == ZEBRA_ROUTE_BGP
&& ri->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_withdraw (&rn->p, ri);
+ bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
table = bgp->rib[AFI_IP6][SAFI_UNICAST];
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
&& ri->type == ZEBRA_ROUTE_BGP
&& ri->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_withdraw (&rn->p, ri);
+ bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
}
}
void
-bgp_reset ()
+bgp_reset (void)
{
vty_reset ();
bgp_zclient_reset ();
}
\f
static struct bgp_static *
-bgp_static_new ()
+bgp_static_new (void)
{
- struct bgp_static *new;
- new = XMALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static));
- memset (new, 0, sizeof (struct bgp_static));
- return new;
+ return XCALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static));
}
static void
/* Withdraw static BGP route from routing table. */
if (ri)
{
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
static void
bgp_static_update_rsclient (struct peer *rsclient, 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;
struct bgp_info *new;
struct bgp_info info;
- struct attr new_attr;
struct attr *attr_new;
- struct attr attr;
+ struct attr attr = {0 };
+ struct attr new_attr = { .extra = 0 };
struct bgp *bgp;
int ret;
char buf[SU_ADDRSTRLEN];
bgp = rsclient->bgp;
+ assert (bgp_static);
+ if (!bgp_static)
+ return;
+
rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, NULL);
bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
- if (bgp_static)
- {
- attr.nexthop = bgp_static->igpnexthop;
- attr.med = bgp_static->igpmetric;
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
- }
-
- new_attr = attr;
+ attr.nexthop = bgp_static->igpnexthop;
+ attr.med = bgp_static->igpmetric;
+ attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+ if (bgp_static->atomic)
+ attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+
/* Apply network route-map for export to this rsclient. */
if (bgp_static->rmap.name)
{
+ struct attr attr_tmp = attr;
info.peer = rsclient;
- info.attr = &new_attr;
-
+ info.attr = &attr_tmp;
+
SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_EXPORT);
SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_NETWORK);
if (ret == RMAP_DENYMATCH)
{
/* Free uninterned attribute. */
- bgp_attr_flush (&new_attr);
+ bgp_attr_flush (&attr_tmp);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
-
+ bgp_attr_extra_free (&attr);
+
return;
}
- attr_new = bgp_attr_intern (&new_attr);
+ attr_new = bgp_attr_intern (&attr_tmp);
}
else
attr_new = bgp_attr_intern (&attr);
-
- new_attr = *attr_new;
-
+
+ bgp_attr_dup(&new_attr, attr_new);
+
SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
- if (bgp_import_modifier (rsclient, bgp->peer_self, p, &new_attr, afi, safi) == RMAP_DENY)
-{
+ if (bgp_import_modifier (rsclient, bgp->peer_self, p, &new_attr, afi, safi)
+ == 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,
bgp->peer_self->rmap_type = 0;
- bgp_attr_unintern (attr_new);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&attr_new);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
return;
- }
+ }
bgp->peer_self->rmap_type = 0;
- bgp_attr_unintern (attr_new);
+ bgp_attr_unintern (&attr_new);
attr_new = bgp_attr_intern (&new_attr);
+ bgp_attr_extra_free (&new_attr);
for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
if (ri)
{
- if (attrhash_cmp (ri->attr, attr_new))
+ if (attrhash_cmp (ri->attr, attr_new) &&
+ !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&attr_new);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
return;
}
else
{
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
- bgp_attr_unintern (ri->attr);
+ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+ bgp_info_restore(rn, ri);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Process change. */
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
return;
+ }
}
-}
-\f
+
/* Make new BGP info. */
new = bgp_info_new ();
new->type = ZEBRA_ROUTE_BGP;
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Register new BGP information. */
bgp_info_add (rn, new);
bgp_process (bgp, rn, afi, safi);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
}
static void
struct bgp_info *ri;
struct bgp_info *new;
struct bgp_info info;
- struct attr attr;
- struct attr attr_tmp;
+ struct attr attr = { 0 };
struct attr *attr_new;
int ret;
+ assert (bgp_static);
+ if (!bgp_static)
+ return;
+
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL);
bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
- if (bgp_static)
- {
- attr.nexthop = bgp_static->igpnexthop;
- attr.med = bgp_static->igpmetric;
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
- }
+
+ attr.nexthop = bgp_static->igpnexthop;
+ attr.med = bgp_static->igpmetric;
+ attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+ if (bgp_static->atomic)
+ attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
/* Apply route-map. */
if (bgp_static->rmap.name)
{
- attr_tmp = attr;
+ struct attr attr_tmp = attr;
info.peer = bgp->peer_self;
info.attr = &attr_tmp;
bgp_attr_flush (&attr_tmp);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
bgp_static_withdraw (bgp, p, afi, safi);
return;
}
if (ri)
{
- if (attrhash_cmp (ri->attr, attr_new))
+ if (attrhash_cmp (ri->attr, attr_new) &&
+ !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
- bgp_attr_unintern (attr_new);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&attr_new);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
return;
}
else
{
/* The attribute is changed. */
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- bgp_attr_unintern (ri->attr);
+ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
+ bgp_info_restore(rn, ri);
+ else
+ bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+ bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
- ri->uptime = time (NULL);
+ ri->uptime = bgp_clock ();
/* Process change. */
bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
return;
}
}
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = attr_new;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
/* Aggregate address increment. */
bgp_aggregate_increment (bgp, p, new, afi, safi);
bgp_process (bgp, rn, afi, safi);
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
}
void
for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
{
- bgp_static_update_rsclient (rsclient, p, bgp_static, afi, safi);
+ if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
+ bgp_static_update_rsclient (rsclient, p, bgp_static, afi, safi);
}
}
static void
-bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
- u_char safi, struct prefix_rd *prd, u_char *tag)
+bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
+ safi_t safi, struct prefix_rd *prd, u_char *tag)
{
struct bgp_node *rn;
struct bgp_info *new;
-
+
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
/* Make new BGP info. */
new->peer = bgp->peer_self;
new->attr = bgp_attr_default_intern (BGP_ORIGIN_IGP);
SET_FLAG (new->flags, BGP_INFO_VALID);
- new->uptime = time (NULL);
- memcpy (new->tag, tag, 3);
+ new->uptime = bgp_clock ();
+ new->extra = bgp_info_extra_new();
+ memcpy (new->extra->tag, tag, 3);
/* Aggregate address increment. */
bgp_aggregate_increment (bgp, p, new, afi, safi);
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
}
static void
-bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
- u_char safi, struct prefix_rd *prd, u_char *tag)
+bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
+ safi_t safi, struct prefix_rd *prd, u_char *tag)
{
struct bgp_node *rn;
struct bgp_info *ri;
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
route should be installed as valid. */
static int
bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
- u_int16_t afi, u_char safi, const char *rmap, int backdoor)
+ afi_t afi, safi_t safi, const char *rmap, int backdoor)
{
int ret;
struct prefix p;
struct bgp_static *bgp_static;
struct bgp_node *rn;
- int need_update = 0;
+ u_char need_update = 0;
/* Convert IP prefix string to struct prefix. */
ret = str2prefix (ip_str, &p);
bgp_static = rn->info;
/* Check previous routes are installed into BGP. */
- if (! bgp_static->backdoor && bgp_static->valid)
- need_update = 1;
-
+ if (bgp_static->valid && bgp_static->backdoor != backdoor)
+ need_update = 1;
+
bgp_static->backdoor = backdoor;
+
if (rmap)
{
if (bgp_static->rmap.name)
bgp_static->valid = 0;
bgp_static->igpmetric = 0;
bgp_static->igpnexthop.s_addr = 0;
+
if (rmap)
{
if (bgp_static->rmap.name)
/* Configure static BGP network. */
static int
bgp_static_unset (struct vty *vty, struct bgp *bgp, const char *ip_str,
- u_int16_t afi, u_char safi)
+ afi_t afi, safi_t safi)
{
int ret;
struct prefix p;
}
bgp_static = rn->info;
-
+
/* Update BGP RIB. */
if (! bgp_static->backdoor)
bgp_static_withdraw (bgp, &p, afi, safi);
prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
(struct prefix *)&prd);
if (prn->info == NULL)
- prn->info = bgp_table_init ();
+ prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
else
bgp_unlock_node (prn);
table = prn->info;
prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
(struct prefix *)&prd);
if (prn->info == NULL)
- prn->info = bgp_table_init ();
+ prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
else
bgp_unlock_node (prn);
table = prn->info;
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
"Specify a BGP backdoor route\n")
{
- return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST,
+ NULL, 1);
}
DEFUN (bgp_network_mask,
{
int ret;
char prefix_str[BUFSIZ];
-
+
ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
if (! ret)
{
{
int ret;
char prefix_str[BUFSIZ];
-
+
ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
if (! ret)
{
{
int ret;
char prefix_str[BUFSIZ];
-
+
ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
if (! ret)
{
return CMD_WARNING;
}
- return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST,
+ NULL, 1);
}
DEFUN (bgp_network_mask_natural,
return CMD_WARNING;
}
- return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);
+ return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST,
+ NULL, 1);
}
DEFUN (no_bgp_network,
"Specify a network to announce via BGP\n"
"IPv6 prefix <network>/<length>\n")
{
- return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+ return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty),
+ NULL, 0);
}
DEFUN (ipv6_bgp_network_route_map,
"Specify a network to announce via BGP\n"
"IPv6 prefix <network>/<length>\n")
{
- return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST);
+ return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty));
}
ALIAS (no_ipv6_bgp_network,
"Specify a network to announce via BGP\n"
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
#endif /* HAVE_IPV6 */
+
+/* stubs for removed AS-Pathlimit commands, kept for config compatibility */
+ALIAS_DEPRECATED (bgp_network,
+ bgp_network_ttl_cmd,
+ "network A.B.C.D/M pathlimit <0-255>",
+ "Specify a network to announce via BGP\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_backdoor,
+ bgp_network_backdoor_ttl_cmd,
+ "network A.B.C.D/M backdoor pathlimit <0-255>",
+ "Specify a network to announce via BGP\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Specify a BGP backdoor route\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask,
+ bgp_network_mask_ttl_cmd,
+ "network A.B.C.D mask A.B.C.D pathlimit <0-255>",
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "Network mask\n"
+ "Network mask\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask_backdoor,
+ bgp_network_mask_backdoor_ttl_cmd,
+ "network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>",
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "Network mask\n"
+ "Network mask\n"
+ "Specify a BGP backdoor route\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask_natural,
+ bgp_network_mask_natural_ttl_cmd,
+ "network A.B.C.D pathlimit <0-255>",
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (bgp_network_mask_natural_backdoor,
+ bgp_network_mask_natural_backdoor_ttl_cmd,
+ "network A.B.C.D backdoor pathlimit (1-255>",
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "Specify a BGP backdoor route\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network,
+ no_bgp_network_ttl_cmd,
+ "no network A.B.C.D/M pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network,
+ no_bgp_network_backdoor_ttl_cmd,
+ "no network A.B.C.D/M backdoor pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+ "Specify a BGP backdoor route\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network,
+ no_bgp_network_mask_ttl_cmd,
+ "no network A.B.C.D mask A.B.C.D pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "Network mask\n"
+ "Network mask\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network_mask,
+ no_bgp_network_mask_backdoor_ttl_cmd,
+ "no network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "Network mask\n"
+ "Network mask\n"
+ "Specify a BGP backdoor route\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network_mask_natural,
+ no_bgp_network_mask_natural_ttl_cmd,
+ "no network A.B.C.D pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_bgp_network_mask_natural,
+ no_bgp_network_mask_natural_backdoor_ttl_cmd,
+ "no network A.B.C.D backdoor pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "Network number\n"
+ "Specify a BGP backdoor route\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+#ifdef HAVE_IPV6
+ALIAS_DEPRECATED (ipv6_bgp_network,
+ ipv6_bgp_network_ttl_cmd,
+ "network X:X::X:X/M pathlimit <0-255>",
+ "Specify a network to announce via BGP\n"
+ "IPv6 prefix <network>/<length>\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+ALIAS_DEPRECATED (no_ipv6_bgp_network,
+ no_ipv6_bgp_network_ttl_cmd,
+ "no network X:X::X:X/M pathlimit <0-255>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "IPv6 prefix <network>/<length>\n"
+ "AS-Path hopcount limit attribute\n"
+ "AS-Pathlimit TTL, in number of AS-Path hops\n")
+#endif /* HAVE_IPV6 */
\f
/* Aggreagete address:
};
static struct bgp_aggregate *
-bgp_aggregate_new ()
+bgp_aggregate_new (void)
{
- struct bgp_aggregate *new;
- new = XMALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
- memset (new, 0, sizeof (struct bgp_aggregate));
- return new;
+ return XCALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
}
static void
{
if (aggregate->summary_only)
{
- ri->suppress++;
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ (bgp_info_extra_get (ri))->suppress++;
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
aggregate->count++;
if (aggregate->summary_only)
- rinew->suppress++;
+ (bgp_info_extra_get (rinew))->suppress++;
if (aggregate->as_set)
{
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
bgp_info_add (rn, new);
bgp_unlock_node (rn);
route announcement. */
if (aggregate->summary_only)
{
- ri->suppress++;
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ (bgp_info_extra_get (ri))->suppress++;
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
/* as-set aggregate route generate origin, as path,
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
bgp_info_add (rn, new);
bgp_unlock_node (rn);
if (ri->sub_type != BGP_ROUTE_AGGREGATE)
{
- if (aggregate->summary_only)
+ if (aggregate->summary_only && ri->extra)
{
- ri->suppress--;
+ ri->extra->suppress--;
- if (ri->suppress == 0)
+ if (ri->extra->suppress == 0)
{
- SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
match++;
}
}
}
}
- /* If this node is suppressed, process the change. */
+ /* If this node was suppressed, process the change. */
if (match)
bgp_process (bgp, rn, afi, safi);
}
/* Withdraw static BGP route from routing table. */
if (ri)
{
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, safi);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, safi);
}
/* Unlock bgp_node_lookup. */
#define AGGREGATE_AS_SET 1
static int
-bgp_aggregate_set (struct vty *vty, const char *prefix_str,
- afi_t afi, safi_t safi,
- u_char summary_only, u_char as_set)
+bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
+ afi_t afi, safi_t safi)
{
int ret;
struct prefix p;
bgp = vty->index;
/* Old configuration check. */
- rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
-
- if (rn->info)
+ rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
+ if (! rn)
{
- vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
- bgp_unlock_node (rn);
+ vty_out (vty, "%% There is no aggregate-address configuration.%s",
+ VTY_NEWLINE);
return CMD_WARNING;
}
- /* Make aggregate address structure. */
- aggregate = bgp_aggregate_new ();
- aggregate->summary_only = summary_only;
- aggregate->as_set = as_set;
- aggregate->safi = safi;
- rn->info = aggregate;
+ aggregate = rn->info;
+ if (aggregate->safi & SAFI_UNICAST)
+ bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
+ if (aggregate->safi & SAFI_MULTICAST)
+ bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
- /* Aggregate address insert into BGP routing table. */
- if (safi & SAFI_UNICAST)
- bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
- if (safi & SAFI_MULTICAST)
- bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+ /* Unlock aggregate address configuration. */
+ rn->info = NULL;
+ bgp_aggregate_free (aggregate);
+ bgp_unlock_node (rn);
+ bgp_unlock_node (rn);
return CMD_SUCCESS;
}
static int
-bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
- afi_t afi, safi_t safi)
+bgp_aggregate_set (struct vty *vty, const char *prefix_str,
+ afi_t afi, safi_t safi,
+ u_char summary_only, u_char as_set)
{
int ret;
struct prefix p;
bgp = vty->index;
/* Old configuration check. */
- rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
- if (! rn)
+ rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
+
+ if (rn->info)
{
- vty_out (vty, "%% There is no aggregate-address configuration.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
+ vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
+ /* try to remove the old entry */
+ ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
+ if (ret)
+ {
+ vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE);
+ bgp_unlock_node (rn);
+ return CMD_WARNING;
+ }
}
- aggregate = rn->info;
- if (aggregate->safi & SAFI_UNICAST)
- bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
- if (aggregate->safi & SAFI_MULTICAST)
- bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+ /* Make aggregate address structure. */
+ aggregate = bgp_aggregate_new ();
+ aggregate->summary_only = summary_only;
+ aggregate->as_set = as_set;
+ aggregate->safi = safi;
+ rn->info = aggregate;
- /* Unlock aggregate address configuration. */
- rn->info = NULL;
- bgp_aggregate_free (aggregate);
- bgp_unlock_node (rn);
- bgp_unlock_node (rn);
+ /* Aggregate address insert into BGP routing table. */
+ if (safi & SAFI_UNICAST)
+ bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
+ if (safi & SAFI_MULTICAST)
+ bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
return CMD_SUCCESS;
}
\f
/* Redistribute route treatment. */
void
-bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
+bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
+ const struct in6_addr *nexthop6,
u_int32_t metric, u_char type)
{
struct bgp *bgp;
struct bgp_info *bi;
struct bgp_info info;
struct bgp_node *bn;
- struct attr attr;
- struct attr attr_new;
+ struct attr attr = { 0 };
+ struct attr attr_new = { 0 };
struct attr *new_attr;
afi_t afi;
int ret;
if (nexthop)
attr.nexthop = *nexthop;
+#ifdef HAVE_IPV6
+ if (nexthop6)
+ {
+ struct attr_extra *extra = bgp_attr_extra_get(&attr);
+ extra->mp_nexthop_global = *nexthop6;
+ extra->mp_nexthop_len = 16;
+ }
+#endif
+
attr.med = metric;
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
if (bgp->redist[afi][type])
{
/* Copy attribute for modification. */
- attr_new = attr;
+ bgp_attr_dup (&attr_new, &attr);
if (bgp->redist_metric_flag[afi][type])
attr_new.med = bgp->redist_metric[afi][type];
{
/* Free uninterned attribute. */
bgp_attr_flush (&attr_new);
-
+ bgp_attr_extra_free (&attr_new);
+
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
bgp_redistribute_delete (p, type);
return;
}
}
- bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL);
+ bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST],
+ afi, SAFI_UNICAST, p, NULL);
+
new_attr = bgp_attr_intern (&attr_new);
-
+ bgp_attr_extra_free (&attr_new);
+
for (bi = bn->info; bi; bi = bi->next)
if (bi->peer == bgp->peer_self
&& bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
if (bi)
{
- if (attrhash_cmp (bi->attr, new_attr))
+ if (attrhash_cmp (bi->attr, new_attr) &&
+ !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
{
- bgp_attr_unintern (new_attr);
- aspath_unintern (attr.aspath);
+ bgp_attr_unintern (&new_attr);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
bgp_unlock_node (bn);
return;
}
else
{
/* The attribute is changed. */
- SET_FLAG (bi->flags, BGP_INFO_ATTR_CHANGED);
+ bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
- bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
- bgp_attr_unintern (bi->attr);
+ if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
+ bgp_info_restore(bn, bi);
+ else
+ bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
+ bgp_attr_unintern (&bi->attr);
bi->attr = new_attr;
- bi->uptime = time (NULL);
+ bi->uptime = bgp_clock ();
/* Process change. */
bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
bgp_process (bgp, bn, afi, SAFI_UNICAST);
bgp_unlock_node (bn);
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
return;
}
}
new->peer = bgp->peer_self;
SET_FLAG (new->flags, BGP_INFO_VALID);
new->attr = new_attr;
- new->uptime = time (NULL);
+ new->uptime = bgp_clock ();
bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
bgp_info_add (bn, new);
}
/* Unintern original. */
- aspath_unintern (attr.aspath);
+ aspath_unintern (&attr.aspath);
+ bgp_attr_extra_free (&attr);
}
void
if (ri)
{
bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, SAFI_UNICAST);
}
bgp_unlock_node (rn);
}
if (ri)
{
bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST);
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
bgp_info_delete (rn, ri);
+ bgp_process (bgp, rn, afi, SAFI_UNICAST);
}
}
}
vty_out (vty, "R");
else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
vty_out (vty, "S");
- else if (binfo->suppress)
+ else if (binfo->extra && binfo->extra->suppress)
vty_out (vty, "s");
else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, "*");
if (p->family == AF_INET)
{
if (safi == SAFI_MPLS_VPN)
- vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in));
+ vty_out (vty, "%-16s",
+ inet_ntoa (attr->extra->mp_nexthop_global_in));
else
vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
}
char buf[BUFSIZ];
len = vty_out (vty, "%s",
- inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ));
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
+ buf, BUFSIZ));
len = 16 - len;
if (len < 1)
vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
#endif /* HAVE_IPV6 */
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
- vty_out (vty, "%10d", attr->med);
+ vty_out (vty, "%10u", attr->med);
else
vty_out (vty, " ");
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- vty_out (vty, "%7d", attr->local_pref);
+ vty_out (vty, "%7u", attr->local_pref);
else
vty_out (vty, " ");
- vty_out (vty, "%7u ",attr->weight);
+ vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
- /* Print aspath */
- if (attr->aspath)
- aspath_print_vty (vty, attr->aspath);
+ /* Print aspath */
+ if (attr->aspath)
+ aspath_print_vty (vty, "%s", attr->aspath, " ");
- /* Print origin */
- if (strlen (attr->aspath->str) == 0)
+ /* Print origin */
vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- else
- vty_out (vty, " %s", bgp_origin_str[attr->origin]);
- }
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
if (p->family == AF_INET)
{
if (safi == SAFI_MPLS_VPN)
- vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in));
+ vty_out (vty, "%-16s",
+ inet_ntoa (attr->extra->mp_nexthop_global_in));
else
vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
}
{
int len;
char buf[BUFSIZ];
+
+ assert (attr->extra);
len = vty_out (vty, "%s",
- inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ));
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
+ buf, BUFSIZ));
len = 16 - len;
if (len < 1)
vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
#endif /* HAVE_IPV6 */
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
- vty_out (vty, "%10d", attr->med);
+ vty_out (vty, "%10u", attr->med);
else
vty_out (vty, " ");
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- vty_out (vty, "%7d", attr->local_pref);
+ vty_out (vty, "%7u", attr->local_pref);
else
vty_out (vty, " ");
+
+ vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
+
+ /* Print aspath */
+ if (attr->aspath)
+ aspath_print_vty (vty, "%s", attr->aspath, " ");
- vty_out (vty, "%7d ",attr->weight);
-
- /* Print aspath */
- if (attr->aspath)
- aspath_print_vty (vty, attr->aspath);
-
- /* Print origin */
- if (strlen (attr->aspath->str) == 0)
+ /* Print origin */
vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- else
- vty_out (vty, " %s", bgp_origin_str[attr->origin]);
- }
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
{
struct attr *attr;
u_int32_t label = 0;
-
+
+ if (!binfo->extra)
+ return;
+
/* short status lead text */
route_vty_short_status_out (vty, binfo);
if (p->family == AF_INET)
{
if (safi == SAFI_MPLS_VPN)
- vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in));
+ vty_out (vty, "%-16s",
+ inet_ntoa (attr->extra->mp_nexthop_global_in));
else
vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
}
#ifdef HAVE_IPV6
else if (p->family == AF_INET6)
{
+ assert (attr->extra);
char buf[BUFSIZ];
char buf1[BUFSIZ];
- if (attr->mp_nexthop_len == 16)
+ if (attr->extra->mp_nexthop_len == 16)
vty_out (vty, "%s",
- inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ));
- else if (attr->mp_nexthop_len == 32)
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
+ buf, BUFSIZ));
+ else if (attr->extra->mp_nexthop_len == 32)
vty_out (vty, "%s(%s)",
- inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ),
- inet_ntop (AF_INET6, &attr->mp_nexthop_local, buf1, BUFSIZ));
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
+ buf, BUFSIZ),
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
+ buf1, BUFSIZ));
}
#endif /* HAVE_IPV6 */
}
- label = decode_label (binfo->tag);
+ label = decode_label (binfo->extra->tag);
vty_out (vty, "notag/%d", label);
{
struct attr *attr;
int len;
+ char timebuf[BGP_UPTIME_LEN];
/* short status lead text */
route_vty_short_status_out (vty, binfo);
else
vty_out (vty, "%*s", len, " ");
- vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo));
+ vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN));
/* Print attribute */
attr = binfo->attr;
{
/* Print aspath */
if (attr->aspath)
- aspath_print_vty (vty, attr->aspath);
+ aspath_print_vty (vty, "%s", attr->aspath, " ");
/* Print origin */
- if (strlen (attr->aspath->str) == 0)
- vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- else
- vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+ vty_out (vty, "%s", bgp_origin_str[attr->origin]);
}
vty_out (vty, "%s", VTY_NEWLINE);
}
-#define BGP_UPTIME_LEN 25
-
/* flap route */
static void
flap_route_vty_out (struct vty *vty, struct prefix *p,
struct bgp_damp_info *bdi;
char timebuf[BGP_UPTIME_LEN];
int len;
-
- bdi = binfo->damp_info;
+
+ if (!binfo->extra)
+ return;
+
+ bdi = binfo->extra->damp_info;
/* short status lead text */
route_vty_short_status_out (vty, binfo);
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
&& ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
- vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo));
+ vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN));
else
vty_out (vty, "%*s ", 8, " ");
{
/* Print aspath */
if (attr->aspath)
- aspath_print_vty (vty, attr->aspath);
+ aspath_print_vty (vty, "%s", attr->aspath, " ");
/* Print origin */
- if (strlen (attr->aspath->str) == 0)
- vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- else
- vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+ vty_out (vty, "%s", bgp_origin_str[attr->origin]);
}
vty_out (vty, "%s", VTY_NEWLINE);
}
char buf1[BUFSIZ];
struct attr *attr;
int sockunion_vty_out (struct vty *, union sockunion *);
+#ifdef HAVE_CLOCK_MONOTONIC
+ time_t tbuf;
+#endif
attr = binfo->attr;
if (attr->aspath)
{
vty_out (vty, " ");
- if (attr->aspath->length == 0)
+ if (aspath_count_hops (attr->aspath) == 0)
vty_out (vty, "Local");
else
- aspath_print_vty (vty, attr->aspath);
+ aspath_print_vty (vty, "%s", attr->aspath, "");
}
if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
vty_out (vty, ", (stale)");
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
- vty_out (vty, ", (aggregated by %d %s)", attr->aggregator_as,
- inet_ntoa (attr->aggregator_addr));
+ vty_out (vty, ", (aggregated by %u %s)",
+ attr->extra->aggregator_as,
+ inet_ntoa (attr->extra->aggregator_addr));
if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
vty_out (vty, ", (Received from a RR-client)");
if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
if (p->family == AF_INET)
{
vty_out (vty, " %s", safi == SAFI_MPLS_VPN ?
- inet_ntoa (attr->mp_nexthop_global_in) :
+ inet_ntoa (attr->extra->mp_nexthop_global_in) :
inet_ntoa (attr->nexthop));
}
#ifdef HAVE_IPV6
else
{
+ assert (attr->extra);
vty_out (vty, " %s",
- inet_ntop (AF_INET6, &attr->mp_nexthop_global,
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
buf, INET6_ADDRSTRLEN));
}
#endif /* HAVE_IPV6 */
{
if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
vty_out (vty, " (inaccessible)");
- else if (binfo->igpmetric)
- vty_out (vty, " (metric %d)", binfo->igpmetric);
+ else if (binfo->extra && binfo->extra->igpmetric)
+ vty_out (vty, " (metric %d)", binfo->extra->igpmetric);
vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- vty_out (vty, " (%s)", inet_ntoa (attr->originator_id));
+ vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
else
vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
}
#ifdef HAVE_IPV6
/* display nexthop local */
- if (attr->mp_nexthop_len == 32)
+ if (attr->extra && attr->extra->mp_nexthop_len == 32)
{
vty_out (vty, " (%s)%s",
- inet_ntop (AF_INET6, &attr->mp_nexthop_local,
+ inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
buf, INET6_ADDRSTRLEN),
VTY_NEWLINE);
}
vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]);
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
- vty_out (vty, ", metric %d", attr->med);
+ vty_out (vty, ", metric %u", attr->med);
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
- vty_out (vty, ", localpref %d", attr->local_pref);
+ vty_out (vty, ", localpref %u", attr->local_pref);
else
- vty_out (vty, ", localpref %d", bgp->default_local_pref);
+ vty_out (vty, ", localpref %u", bgp->default_local_pref);
- if (attr->weight != 0)
- vty_out (vty, ", weight %d", attr->weight);
+ if (attr->extra && attr->extra->weight != 0)
+ vty_out (vty, ", weight %u", attr->extra->weight);
if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, ", valid");
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
vty_out (vty, ", atomic-aggregate");
+ if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) ||
+ (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) &&
+ bgp_info_mpath_count (binfo)))
+ vty_out (vty, ", multipath");
+
if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
vty_out (vty, ", best");
/* Line 5 display Extended-community */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
- vty_out (vty, " Extended Community: %s%s", attr->ecommunity->str,
- VTY_NEWLINE);
+ vty_out (vty, " Extended Community: %s%s",
+ attr->extra->ecommunity->str, VTY_NEWLINE);
/* Line 6 display Originator, Cluster-id */
if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) ||
(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)))
{
+ assert (attr->extra);
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- vty_out (vty, " Originator: %s", inet_ntoa (attr->originator_id));
+ vty_out (vty, " Originator: %s",
+ inet_ntoa (attr->extra->originator_id));
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
{
int i;
vty_out (vty, ", Cluster list: ");
- for (i = 0; i < attr->cluster->length / 4; i++)
- vty_out (vty, "%s ", inet_ntoa (attr->cluster->list[i]));
+ for (i = 0; i < attr->extra->cluster->length / 4; i++)
+ vty_out (vty, "%s ",
+ inet_ntoa (attr->extra->cluster->list[i]));
}
vty_out (vty, "%s", VTY_NEWLINE);
}
-
- if (binfo->damp_info)
+
+ if (binfo->extra && binfo->extra->damp_info)
bgp_damp_info_vty (vty, binfo);
/* Line 7 display Uptime */
- vty_out (vty, " Last update: %s", ctime (&binfo->uptime));
+#ifdef HAVE_CLOCK_MONOTONIC
+ tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
+ vty_out (vty, " Last update: %s", ctime(&tbuf));
+#else
+ vty_out (vty, " Last update: %s", ctime(&binfo->uptime));
+#endif /* HAVE_CLOCK_MONOTONIC */
}
vty_out (vty, "%s", VTY_NEWLINE);
}
|| type == bgp_show_type_dampend_paths
|| type == bgp_show_type_damp_neighbor)
{
- if (! ri->damp_info)
+ if (!(ri->extra && ri->extra->damp_info))
continue;
}
if (type == bgp_show_type_regexp
{
struct route_map *rmap = output_arg;
struct bgp_info binfo;
- struct attr dummy_attr;
+ struct attr dummy_attr = { 0 };
int ret;
- dummy_attr = *ri->attr;
+ bgp_attr_dup (&dummy_attr, ri->attr);
binfo.peer = ri->peer;
binfo.attr = &dummy_attr;
ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo);
-
+
+ bgp_attr_extra_free (&dummy_attr);
+
if (ret == RMAP_DENYMATCH)
continue;
}
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
{
best = count;
- if (ri->suppress)
+ if (ri->extra && ri->extra->suppress)
suppress = 1;
if (ri->attr->community != NULL)
{
if ((rm = bgp_node_match (table, &match)) != NULL)
{
if (prefix_check && rm->p.prefixlen != match.prefixlen)
- continue;
+ {
+ bgp_unlock_node (rm);
+ continue;
+ }
for (ri = rm->info; ri; ri = ri->next)
{
display++;
route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN);
}
+
+ bgp_unlock_node (rm);
}
}
}
route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
}
}
+
+ bgp_unlock_node (rn);
}
}
return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
}
+ALIAS (show_ip_bgp_ipv4,
+ show_bgp_ipv4_safi_cmd,
+ "show bgp ipv4 (unicast|multicast)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n")
+
DEFUN (show_ip_bgp_route,
show_ip_bgp_route_cmd,
"show ip bgp A.B.C.D",
return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
}
+ALIAS (show_ip_bgp_ipv4_route,
+ show_bgp_ipv4_safi_route_cmd,
+ "show bgp ipv4 (unicast|multicast) A.B.C.D",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Network in the BGP routing table to display\n")
+
DEFUN (show_ip_bgp_vpnv4_all_route,
show_ip_bgp_vpnv4_all_route_cmd,
"show ip bgp vpnv4 all A.B.C.D",
return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
}
+ALIAS (show_ip_bgp_ipv4_prefix,
+ show_bgp_ipv4_safi_prefix_cmd,
+ "show bgp ipv4 (unicast|multicast) A.B.C.D/M",
+ 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")
+
DEFUN (show_ip_bgp_vpnv4_all_prefix,
show_ip_bgp_vpnv4_all_prefix_cmd,
"show ip bgp vpnv4 all A.B.C.D/M",
BGP_STR
"Address family\n")
+DEFUN (show_bgp_ipv6_safi,
+ show_bgp_ipv6_safi_cmd,
+ "show bgp ipv6 (unicast|multicast)",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n")
+{
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal,
+ NULL);
+
+ return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL);
+}
+
/* old command */
DEFUN (show_ipv6_bgp,
show_ipv6_bgp_cmd,
"Address family\n"
"Network in the BGP routing table to display\n")
+DEFUN (show_bgp_ipv6_safi_route,
+ show_bgp_ipv6_safi_route_cmd,
+ "show bgp ipv6 (unicast|multicast) X:X::X:X",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "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_UNICAST, NULL, 0);
+}
+
/* old command */
DEFUN (show_ipv6_bgp_route,
show_ipv6_bgp_route_cmd,
"Address family\n"
"IPv6 prefix <network>/<length>\n")
+DEFUN (show_bgp_ipv6_safi_prefix,
+ show_bgp_ipv6_safi_prefix_cmd,
+ "show bgp ipv6 (unicast|multicast) X:X::X:X/M",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "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_UNICAST, NULL, 1);
+}
+
/* old command */
DEFUN (show_ipv6_bgp_prefix,
show_ipv6_bgp_prefix_cmd,
#endif /* HAVE_IPV6 */
\f
static int
-bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
- u_int16_t afi, u_char safi)
+bgp_show_community (struct vty *vty, const char *view_name, int argc,
+ const char **argv, int exact, afi_t afi, safi_t safi)
{
struct community *com;
struct buffer *b;
+ struct bgp *bgp;
int i;
char *str;
int first = 0;
+ /* 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;
+ }
+ }
+
b = buffer_new (1024);
for (i = 0; i < argc; i++)
{
return CMD_WARNING;
}
- return bgp_show (vty, NULL, afi, safi,
+ return bgp_show (vty, bgp, afi, safi,
(exact ? bgp_show_type_community_exact :
bgp_show_type_community), com);
}
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n")
{
- return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_community,
"Do not export to next AS (well-known community)\n")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
- return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_ipv4_community,
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n")
+DEFUN (show_bgp_view_afi_safi_community_all,
+ show_bgp_view_afi_safi_community_all_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Display routes containing communities\n")
+{
+ int afi;
+ int safi;
+ struct bgp *bgp;
+
+ /* BGP structure lookup. */
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+#ifdef HAVE_IPV6
+ afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+ safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#else
+ afi = AFI_IP;
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#endif
+ return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL);
+}
+
+DEFUN (show_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address family modifier\n"
+ "Address family modifier\n"
+ "Display routes matching the communities\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n")
+{
+ int afi;
+ int safi;
+
+#ifdef HAVE_IPV6
+ afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+ safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_community (vty, argv[0], argc-3, &argv[3], 0, afi, safi);
+#else
+ afi = AFI_IP;
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ return bgp_show_community (vty, argv[0], argc-2, &argv[2], 0, afi, safi);
+#endif
+}
+
+ALIAS (show_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community2_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address family modifier\n"
+ "Address family modifier\n"
+ "Display routes matching the communities\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community3_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address family modifier\n"
+ "Address family modifier\n"
+ "Display routes matching the communities\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_view_afi_safi_community,
+ show_bgp_view_afi_safi_community4_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address family modifier\n"
+ "Address family modifier\n"
+ "Display routes matching the communities\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "community number\n"
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n")
+
DEFUN (show_ip_bgp_community_exact,
show_ip_bgp_community_exact_cmd,
"show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
"Do not export to next AS (well-known community)\n"
"Exact match of the communities")
{
- return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_community_exact,
"Exact match of the communities")
{
if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
- return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_ipv4_community_exact,
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n")
{
- return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
}
ALIAS (show_bgp_community,
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n")
{
- return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
}
/* old command */
"Do not export to next AS (well-known community)\n"
"Exact match of the communities")
{
- return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
}
ALIAS (show_bgp_community_exact,
"Do not export to next AS (well-known community)\n"
"Exact match of the communities")
{
- return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
}
/* old command */
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n")
{
- return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
}
/* old command */
"Do not export to next AS (well-known community)\n"
"Exact match of the communities")
{
- return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
}
/* old command */
\f
static int
bgp_show_community_list (struct vty *vty, const char *com, int exact,
- u_int16_t afi, u_char safi)
+ afi_t afi, safi_t safi)
{
struct community_list *list;
"Address family\n"
"Display routes matching the community-list\n"
"community-list number\n"
- "community-list name\n");
+ "community-list name\n")
/* old command */
DEFUN (show_ipv6_bgp_community_list,
return peer;
}
+\f
+enum bgp_stats
+{
+ BGP_STATS_MAXBITLEN = 0,
+ BGP_STATS_RIB,
+ BGP_STATS_PREFIXES,
+ BGP_STATS_TOTPLEN,
+ BGP_STATS_UNAGGREGATEABLE,
+ BGP_STATS_MAX_AGGREGATEABLE,
+ BGP_STATS_AGGREGATES,
+ BGP_STATS_SPACE,
+ BGP_STATS_ASPATH_COUNT,
+ BGP_STATS_ASPATH_MAXHOPS,
+ BGP_STATS_ASPATH_TOTHOPS,
+ BGP_STATS_ASPATH_MAXSIZE,
+ BGP_STATS_ASPATH_TOTSIZE,
+ BGP_STATS_ASN_HIGHEST,
+ BGP_STATS_MAX,
+};
-static void
-show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
- int in)
+static const char *table_stats_strs[] =
+{
+ [BGP_STATS_PREFIXES] = "Total Prefixes",
+ [BGP_STATS_TOTPLEN] = "Average prefix length",
+ [BGP_STATS_RIB] = "Total Advertisements",
+ [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
+ [BGP_STATS_MAX_AGGREGATEABLE] = "Maximum aggregateable prefixes",
+ [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
+ [BGP_STATS_SPACE] = "Address space advertised",
+ [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
+ [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
+ [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
+ [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
+ [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
+ [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
+ [BGP_STATS_MAX] = NULL,
+};
+
+struct bgp_table_stats
{
struct bgp_table *table;
- struct bgp_adj_in *ain;
- struct bgp_adj_out *adj;
- unsigned long output_count;
- struct bgp_node *rn;
- int header1 = 1;
- struct bgp *bgp;
- int header2 = 1;
-
- bgp = peer->bgp;
+ unsigned long long counts[BGP_STATS_MAX];
+};
- if (! bgp)
- return;
+#if 0
+#define TALLY_SIGFIG 100000
+static unsigned long
+ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
+{
+ unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
+ unsigned long res = (newtot * TALLY_SIGFIG) / count;
+ unsigned long ret = newtot / count;
+
+ if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
+ return ret + 1;
+ else
+ return ret;
+}
+#endif
- table = bgp->rib[afi][safi];
+static int
+bgp_table_stats_walker (struct thread *t)
+{
+ struct bgp_node *rn;
+ struct bgp_node *top;
+ struct bgp_table_stats *ts = THREAD_ARG (t);
+ unsigned int space = 0;
+
+ if (!(top = bgp_table_top (ts->table)))
+ return 0;
- output_count = 0;
-
- if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
- PEER_STATUS_DEFAULT_ORIGINATE))
+ switch (top->p.family)
{
- vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
- vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+ case AF_INET:
+ space = IPV4_MAX_BITLEN;
+ break;
+ case AF_INET6:
+ space = IPV6_MAX_BITLEN;
+ break;
+ }
+
+ ts->counts[BGP_STATS_MAXBITLEN] = space;
+
+ for (rn = top; rn; rn = bgp_route_next (rn))
+ {
+ struct bgp_info *ri;
+ struct bgp_node *prn = rn->parent;
+ unsigned int rinum = 0;
+
+ if (rn == top)
+ continue;
+
+ if (!rn->info)
+ continue;
+
+ ts->counts[BGP_STATS_PREFIXES]++;
+ ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
+
+#if 0
+ ts->counts[BGP_STATS_AVGPLEN]
+ = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
+ ts->counts[BGP_STATS_AVGPLEN],
+ rn->p.prefixlen);
+#endif
+
+ /* check if the prefix is included by any other announcements */
+ while (prn && !prn->info)
+ prn = prn->parent;
+
+ if (prn == NULL || prn == top)
+ {
+ ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
+ /* announced address space */
+ if (space)
+ ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen);
+ }
+ else if (prn->info)
+ ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
+
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ rinum++;
+ ts->counts[BGP_STATS_RIB]++;
+
+ if (ri->attr &&
+ (CHECK_FLAG (ri->attr->flag,
+ ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))))
+ ts->counts[BGP_STATS_AGGREGATES]++;
+
+ /* as-path stats */
+ if (ri->attr && ri->attr->aspath)
+ {
+ unsigned int hops = aspath_count_hops (ri->attr->aspath);
+ unsigned int size = aspath_size (ri->attr->aspath);
+ as_t highest = aspath_highest (ri->attr->aspath);
+
+ ts->counts[BGP_STATS_ASPATH_COUNT]++;
+
+ if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
+ ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
+
+ if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
+ ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
+
+ ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
+ ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
+#if 0
+ ts->counts[BGP_STATS_ASPATH_AVGHOPS]
+ = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
+ ts->counts[BGP_STATS_ASPATH_AVGHOPS],
+ hops);
+ ts->counts[BGP_STATS_ASPATH_AVGSIZE]
+ = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
+ ts->counts[BGP_STATS_ASPATH_AVGSIZE],
+ size);
+#endif
+ if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
+ ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ struct bgp_table_stats ts;
+ unsigned int i;
+
+ if (!bgp->rib[afi][safi])
+ {
+ vty_out (vty, "%% No RIB exist for the AFI/SAFI%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ memset (&ts, 0, sizeof (ts));
+ ts.table = bgp->rib[afi][safi];
+ thread_execute (bm->master, bgp_table_stats_walker, &ts, 0);
+
+ vty_out (vty, "BGP %s RIB statistics%s%s",
+ afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE);
+
+ for (i = 0; i < BGP_STATS_MAX; i++)
+ {
+ if (!table_stats_strs[i])
+ continue;
+
+ switch (i)
+ {
+#if 0
+ case BGP_STATS_ASPATH_AVGHOPS:
+ case BGP_STATS_ASPATH_AVGSIZE:
+ case BGP_STATS_AVGPLEN:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12.2f",
+ (float)ts.counts[i] / (float)TALLY_SIGFIG);
+ break;
+#endif
+ case BGP_STATS_ASPATH_TOTHOPS:
+ case BGP_STATS_ASPATH_TOTSIZE:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12.2f",
+ ts.counts[i] ?
+ (float)ts.counts[i] /
+ (float)ts.counts[BGP_STATS_ASPATH_COUNT]
+ : 0);
+ break;
+ case BGP_STATS_TOTPLEN:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12.2f",
+ ts.counts[i] ?
+ (float)ts.counts[i] /
+ (float)ts.counts[BGP_STATS_PREFIXES]
+ : 0);
+ break;
+ case BGP_STATS_SPACE:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12llu%s", ts.counts[i], VTY_NEWLINE);
+ if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
+ break;
+ vty_out (vty, "%30s: ", "%% announced ");
+ vty_out (vty, "%12.2f%s",
+ 100 * (float)ts.counts[BGP_STATS_SPACE] /
+ (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]),
+ VTY_NEWLINE);
+ vty_out (vty, "%30s: ", "/8 equivalent ");
+ vty_out (vty, "%12.2f%s",
+ (float)ts.counts[BGP_STATS_SPACE] /
+ (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)),
+ VTY_NEWLINE);
+ if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
+ break;
+ vty_out (vty, "%30s: ", "/24 equivalent ");
+ vty_out (vty, "%12.2f",
+ (float)ts.counts[BGP_STATS_SPACE] /
+ (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24)));
+ break;
+ default:
+ vty_out (vty, "%-30s: ", table_stats_strs[i]);
+ vty_out (vty, "%12llu", ts.counts[i]);
+ }
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+ return CMD_SUCCESS;
+}
+
+static int
+bgp_table_stats_vty (struct vty *vty, const char *name,
+ const char *afi_str, const char *safi_str)
+{
+ struct bgp *bgp;
+ afi_t afi;
+ safi_t safi;
+
+ if (name)
+ bgp = bgp_lookup_by_name (name);
+ else
+ bgp = bgp_get_default ();
+
+ if (!bgp)
+ {
+ vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (strncmp (afi_str, "ipv", 3) == 0)
+ {
+ if (strncmp (afi_str, "ipv4", 4) == 0)
+ afi = AFI_IP;
+ else if (strncmp (afi_str, "ipv6", 4) == 0)
+ afi = AFI_IP6;
+ else
+ {
+ vty_out (vty, "%% Invalid address family %s%s",
+ afi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (strncmp (safi_str, "m", 1) == 0)
+ safi = SAFI_MULTICAST;
+ else if (strncmp (safi_str, "u", 1) == 0)
+ safi = SAFI_UNICAST;
+ else if (strncmp (safi_str, "vpnv4", 5) == 0 || strncmp (safi_str, "vpnv6", 5) == 0)
+ safi = SAFI_MPLS_LABELED_VPN;
+ else
+ {
+ vty_out (vty, "%% Invalid subsequent address family %s%s",
+ safi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ else
+ {
+ vty_out (vty, "%% Invalid address family %s%s",
+ afi_str, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_table_stats (vty, bgp, afi, safi);
+}
+
+DEFUN (show_bgp_statistics,
+ show_bgp_statistics_cmd,
+ "show bgp (ipv4|ipv6) (unicast|multicast) statistics",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+{
+ return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
+}
+
+ALIAS (show_bgp_statistics,
+ show_bgp_statistics_vpnv4_cmd,
+ "show bgp (ipv4) (vpnv4) statistics",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+
+DEFUN (show_bgp_statistics_view,
+ show_bgp_statistics_view_cmd,
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) statistics",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "Address family\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+{
+ return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
+}
+
+ALIAS (show_bgp_statistics_view,
+ show_bgp_statistics_view_vpnv4_cmd,
+ "show bgp view WORD (ipv4) (vpnv4) statistics",
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "BGP RIB advertisement statistics\n")
+\f
+enum bgp_pcounts
+{
+ PCOUNT_ADJ_IN = 0,
+ PCOUNT_DAMPED,
+ PCOUNT_REMOVED,
+ PCOUNT_HISTORY,
+ PCOUNT_STALE,
+ PCOUNT_VALID,
+ PCOUNT_ALL,
+ PCOUNT_COUNTED,
+ PCOUNT_PFCNT, /* the figure we display to users */
+ PCOUNT_MAX,
+};
+
+static const char *pcount_strs[] =
+{
+ [PCOUNT_ADJ_IN] = "Adj-in",
+ [PCOUNT_DAMPED] = "Damped",
+ [PCOUNT_REMOVED] = "Removed",
+ [PCOUNT_HISTORY] = "History",
+ [PCOUNT_STALE] = "Stale",
+ [PCOUNT_VALID] = "Valid",
+ [PCOUNT_ALL] = "All RIB",
+ [PCOUNT_COUNTED] = "PfxCt counted",
+ [PCOUNT_PFCNT] = "Useable",
+ [PCOUNT_MAX] = NULL,
+};
+
+struct peer_pcounts
+{
+ unsigned int count[PCOUNT_MAX];
+ const struct peer *peer;
+ const struct bgp_table *table;
+};
+
+static int
+bgp_peer_count_walker (struct thread *t)
+{
+ struct bgp_node *rn;
+ struct peer_pcounts *pc = THREAD_ARG (t);
+ const struct peer *peer = pc->peer;
+
+ for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn))
+ {
+ struct bgp_adj_in *ain;
+ struct bgp_info *ri;
+
+ for (ain = rn->adj_in; ain; ain = ain->next)
+ if (ain->peer == peer)
+ pc->count[PCOUNT_ADJ_IN]++;
+
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ char buf[SU_ADDRSTRLEN];
+
+ if (ri->peer != peer)
+ continue;
+
+ pc->count[PCOUNT_ALL]++;
+
+ if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED))
+ pc->count[PCOUNT_DAMPED]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+ pc->count[PCOUNT_HISTORY]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED))
+ pc->count[PCOUNT_REMOVED]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
+ pc->count[PCOUNT_STALE]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_VALID))
+ pc->count[PCOUNT_VALID]++;
+ if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ pc->count[PCOUNT_PFCNT]++;
+
+ if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
+ {
+ pc->count[PCOUNT_COUNTED]++;
+ if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ plog_warn (peer->log,
+ "%s [pcount] %s/%d is counted but flags 0x%x",
+ peer->host,
+ inet_ntop(rn->p.family, &rn->p.u.prefix,
+ buf, SU_ADDRSTRLEN),
+ rn->p.prefixlen,
+ ri->flags);
+ }
+ else
+ {
+ if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
+ plog_warn (peer->log,
+ "%s [pcount] %s/%d not counted but flags 0x%x",
+ peer->host,
+ inet_ntop(rn->p.family, &rn->p.u.prefix,
+ buf, SU_ADDRSTRLEN),
+ rn->p.prefixlen,
+ ri->flags);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi)
+{
+ struct peer_pcounts pcounts = { .peer = peer };
+ unsigned int i;
+
+ if (!peer || !peer->bgp || !peer->afc[afi][safi]
+ || !peer->bgp->rib[afi][safi])
+ {
+ vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ memset (&pcounts, 0, sizeof(pcounts));
+ pcounts.peer = peer;
+ pcounts.table = peer->bgp->rib[afi][safi];
+
+ /* in-place call via thread subsystem so as to record execution time
+ * stats for the thread-walk (i.e. ensure this can't be blamed on
+ * on just vty_read()).
+ */
+ thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0);
+
+ vty_out (vty, "Prefix counts for %s, %s%s",
+ peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
+ vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE);
+ vty_out (vty, "%sCounts from RIB table walk:%s%s",
+ VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+
+ for (i = 0; i < PCOUNT_MAX; i++)
+ vty_out (vty, "%20s: %-10d%s",
+ pcount_strs[i], pcounts.count[i], VTY_NEWLINE);
+
+ if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi])
+ {
+ vty_out (vty, "%s [pcount] PfxCt drift!%s",
+ peer->host, VTY_NEWLINE);
+ vty_out (vty, "Please report this bug, with the above command output%s",
+ VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_neighbor_prefix_counts,
+ show_ip_bgp_neighbor_prefix_counts_cmd,
+ "show ip bgp neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_bgp_ipv6_neighbor_prefix_counts,
+ show_bgp_ipv6_neighbor_prefix_counts_cmd,
+ "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ BGP_STR
+ "Address family\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_peer_counts (vty, peer, AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_prefix_counts,
+ show_ip_bgp_ipv4_neighbor_prefix_counts_cmd,
+ "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ if (! peer)
+ return CMD_WARNING;
+
+ if (strncmp (argv[0], "m", 1) == 0)
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MULTICAST);
+
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_vpnv4_neighbor_prefix_counts,
+ show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd,
+ "show ip bgp vpnv4 all neighbors (A.B.C.D|X:X::X:X) prefix-counts",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display detailed prefix count information\n")
+{
+ struct peer *peer;
+
+ peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (! peer)
+ return CMD_WARNING;
+
+ return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN);
+}
+
+
+static void
+show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
+ int in)
+{
+ struct bgp_table *table;
+ struct bgp_adj_in *ain;
+ struct bgp_adj_out *adj;
+ unsigned long output_count;
+ struct bgp_node *rn;
+ int header1 = 1;
+ struct bgp *bgp;
+ int header2 = 1;
+
+ bgp = peer->bgp;
+
+ if (! bgp)
+ return;
+
+ table = bgp->rib[afi][safi];
+
+ output_count = 0;
+
+ if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
+ PEER_STATUS_DEFAULT_ORIGINATE))
+ {
+ vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+ vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
vty_out (vty, "Originating default network 0.0.0.0%s%s",
return CMD_SUCCESS;
}
-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",
+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_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"
{
struct peer *peer;
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ 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_IP, SAFI_UNICAST, 0);
}
+ALIAS (show_ip_bgp_view_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_STR
+ IP_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display the routes advertised to a BGP neighbor\n")
+
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",
}
#endif /* HAVE_IPV6 */
\f
-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",
+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_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"
{
struct peer *peer;
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ 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_IP, SAFI_UNICAST, 1);
}
+ALIAS (show_ip_bgp_view_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_STR
+ IP_STR
+ BGP_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display the received routes from neighbor\n")
+
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",
return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
}
+DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes,
+ show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd,
+#ifdef HAVE_IPV6
+ "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#else
+ "show bgp view WORD ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#endif
+ SHOW_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+#ifdef HAVE_IPV6
+ "Address family\n"
+#endif
+ "Address family modifier\n"
+ "Address family modifier\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Display the advertised routes to neighbor\n"
+ "Display the received routes from neighbor\n")
+{
+ int afi;
+ int safi;
+ int in;
+ struct peer *peer;
+
+#ifdef HAVE_IPV6
+ peer = peer_lookup_in_view (vty, argv[0], argv[3]);
+#else
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+#endif
+
+ if (! peer)
+ return CMD_WARNING;
+
+#ifdef HAVE_IPV6
+ 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;
+#else
+ afi = AFI_IP;
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ in = (strncmp (argv[3], "r", 1) == 0) ? 1 : 0;
+#endif
+
+ return peer_adj_routes (vty, peer, afi, safi, in);
+}
+
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",
"Information about Route Server Client\n"
NEIGHBOR_ADDR_STR)
+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_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+{
+ struct bgp_table *table;
+ struct peer *peer;
+ safi_t safi;
+
+ if (argc == 3) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ table = peer->rib[AFI_IP][safi];
+
+ return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+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_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+
DEFUN (show_ip_bgp_view_rsclient_route,
show_ip_bgp_view_rsclient_route_cmd,
- "show 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) A.B.C.D",
SHOW_STR
IP_STR
BGP_STR
NEIGHBOR_ADDR_STR
"Network in the BGP routing table to display\n")
+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_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP, safi, NULL, 0);
+}
+
+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_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+
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",
struct peer *peer;
/* BGP structure lookup. */
- if (argc == 3)
+ if (argc == 3)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 3)
+ 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;
+
+ if (! peer->afc[AFI_IP][SAFI_UNICAST])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+ PEER_FLAG_RSERVER_CLIENT))
+{
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ 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);
+}
+
+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_STR
+ IP_STR
+ BGP_STR
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\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_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
{
bgp = bgp_lookup_by_name (argv[0]);
if (bgp == NULL)
}
}
- if (argc == 3)
- peer = peer_lookup_in_view (vty, argv[0], argv[1]);
- else
- peer = peer_lookup_in_view (vty, NULL, argv[0]);
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
if (! peer)
return CMD_WARNING;
-
- if (! peer->afc[AFI_IP][SAFI_UNICAST])
+
+ if (! peer->afc[AFI_IP][safi])
{
vty_out (vty, "%% Activate the neighbor for the address family first%s",
VTY_NEWLINE);
return CMD_WARNING;
}
- if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
PEER_FLAG_RSERVER_CLIENT))
{
vty_out (vty, "%% Neighbor is not a Route-Server client%s",
VTY_NEWLINE);
return CMD_WARNING;
}
-
- 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);
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP, safi, NULL, 1);
}
-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",
+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_STR
- IP_STR
BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
"Information about Route Server Client\n"
NEIGHBOR_ADDR_STR
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
-
#ifdef HAVE_IPV6
DEFUN (show_bgp_view_neighbor_routes,
show_bgp_view_neighbor_routes_cmd,
"Information about Route Server Client\n"
NEIGHBOR_ADDR_STR)
+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_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+{
+ struct bgp_table *table;
+ struct peer *peer;
+ safi_t safi;
+
+ if (argc == 3) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP6][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ table = peer->rib[AFI_IP6][safi];
+
+ return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+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_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR)
+
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",
NEIGHBOR_ADDR_STR
"Network in the BGP routing table to display\n")
+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_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "Network in the BGP routing table to display\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP6][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ {
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP6, safi, NULL, 0);
+}
+
+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_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "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",
NEIGHBOR_ADDR_STR
"IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+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_STR
+ BGP_STR
+ "BGP view\n"
+ "BGP view name\n"
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ safi_t safi;
+
+ /* BGP structure lookup. */
+ if (argc == 4)
+ {
+ bgp = bgp_lookup_by_name (argv[0]);
+ if (bgp == NULL)
+ {
+ vty_out (vty, "Can't find BGP view %s%s", argv[0], 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;
+ }
+ }
+
+ if (argc == 4) {
+ peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+ safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ } else {
+ peer = peer_lookup_in_view (vty, NULL, argv[1]);
+ safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+ }
+
+ if (! peer)
+ return CMD_WARNING;
+
+ if (! peer->afc[AFI_IP6][safi])
+ {
+ vty_out (vty, "%% Activate the neighbor for the address family first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+ if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+{
+ vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+ (argc == 4) ? argv[3] : argv[2],
+ AFI_IP6, safi, NULL, 1);
+}
+
+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_STR
+ BGP_STR
+ "Address family\n"
+ "Address Family modifier\n"
+ "Address Family modifier\n"
+ "Information about Route Server Client\n"
+ NEIGHBOR_ADDR_STR
+ "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+
#endif /* HAVE_IPV6 */
\f
struct bgp_table *bgp_distance_table;
};
static struct bgp_distance *
-bgp_distance_new ()
+bgp_distance_new (void)
{
- struct bgp_distance *new;
- new = XMALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
- memset (new, 0, sizeof (struct bgp_distance));
- return new;
+ return XCALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
}
static void
return CMD_SUCCESS;
}
-static void
-bgp_distance_reset ()
-{
- struct bgp_node *rn;
- struct bgp_distance *bdistance;
-
- for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn))
- if ((bdistance = rn->info) != NULL)
- {
- if (bdistance->access_list)
- free (bdistance->access_list);
- bgp_distance_free (bdistance);
- rn->info = NULL;
- bgp_unlock_node (rn);
- }
-}
-
/* Apply BGP information to distance method. */
u_char
bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
if ((table = rn->info) != NULL)
if ((rm = bgp_node_match (table, &match)) != NULL)
- if (! prefix_check || rm->p.prefixlen == match.prefixlen)
- {
- ri = rm->info;
- while (ri)
- {
- if (ri->damp_info)
- {
- ri_temp = ri->next;
- bgp_damp_info_free (ri->damp_info, 1);
- ri = ri_temp;
- }
- else
- ri = ri->next;
- }
- }
+ {
+ if (! prefix_check || rm->p.prefixlen == match.prefixlen)
+ {
+ ri = rm->info;
+ while (ri)
+ {
+ if (ri->extra && ri->extra->damp_info)
+ {
+ ri_temp = ri->next;
+ bgp_damp_info_free (ri->extra->damp_info, 1);
+ ri = ri_temp;
+ }
+ else
+ ri = ri->next;
+ }
+ }
+
+ bgp_unlock_node (rm);
+ }
}
}
else
{
if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
- if (! prefix_check || rn->p.prefixlen == match.prefixlen)
- {
- ri = rn->info;
- while (ri)
- {
- if (ri->damp_info)
- {
- ri_temp = ri->next;
- bgp_damp_info_free (ri->damp_info, 1);
- ri = ri_temp;
- }
- else
- ri = ri->next;
- }
- }
+ {
+ if (! prefix_check || rn->p.prefixlen == match.prefixlen)
+ {
+ ri = rn->info;
+ while (ri)
+ {
+ if (ri->extra && ri->extra->damp_info)
+ {
+ ri_temp = ri->next;
+ bgp_damp_info_free (ri->extra->damp_info, 1);
+ ri = ri_temp;
+ }
+ else
+ ri = ri->next;
+ }
+ }
+
+ bgp_unlock_node (rn);
+ }
}
return CMD_SUCCESS;
if (bgp_static->rmap.name)
vty_out (vty, " route-map %s", bgp_static->rmap.name);
- else if (bgp_static->backdoor)
- vty_out (vty, " backdoor");
+ else
+ {
+ if (bgp_static->backdoor)
+ vty_out (vty, " backdoor");
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
/* Allocate routing table structure and install commands. */
void
-bgp_route_init ()
+bgp_route_init (void)
{
/* Init BGP distance table. */
- bgp_distance_table = bgp_table_init ();
+ bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST);
/* IPv4 BGP commands. */
install_element (BGP_NODE, &bgp_network_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_network_route_map_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_network_mask_route_map_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_route_map_cmd);
+
install_element (BGP_IPV4_NODE, &aggregate_address_cmd);
install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd);
install_element (BGP_IPV4_NODE, &aggregate_address_summary_only_cmd);
install_element (VIEW_NODE, &show_ip_bgp_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_cmd);
install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_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_bgp_ipv4_safi_prefix_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);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community2_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community3_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_afi_safi_community4_cmd);
install_element (VIEW_NODE, &show_ip_bgp_community_exact_cmd);
install_element (VIEW_NODE, &show_ip_bgp_community2_exact_cmd);
install_element (VIEW_NODE, &show_ip_bgp_community3_exact_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_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_bgp_view_afi_safi_neighbor_adv_recd_routes_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);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd);
install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
+
+ /* Restricted node: VIEW_NODE - (set of dangerous commands) */
+ install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_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_bgp_ipv4_safi_prefix_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);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_view_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community2_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community3_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community4_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community2_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community3_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community4_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community2_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community3_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_community4_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_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_bgp_ipv4_safi_prefix_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);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community2_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community3_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community4_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_community_exact_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_community2_exact_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_community3_exact_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_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_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_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_neighbor_flap_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
/* BGP dampening clear commands */
install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
+ /* prefix count */
+ install_element (ENABLE_NODE, &show_ip_bgp_neighbor_prefix_counts_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_prefix_counts_cmd);
+ install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_neighbor_prefix_counts_cmd);
#ifdef HAVE_IPV6
+ install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_prefix_counts_cmd);
+
/* New config IPv6 BGP commands. */
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_summary_only_cmd);
+ install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
+ install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
+
/* Old config IPv6 BGP commands. */
install_element (BGP_NODE, &old_ipv6_bgp_network_cmd);
install_element (BGP_NODE, &old_no_ipv6_bgp_network_cmd);
install_element (VIEW_NODE, &show_bgp_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_cmd);
install_element (VIEW_NODE, &show_bgp_route_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_route_cmd);
install_element (VIEW_NODE, &show_bgp_prefix_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_cmd);
install_element (VIEW_NODE, &show_bgp_regexp_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_regexp_cmd);
install_element (VIEW_NODE, &show_bgp_prefix_list_cmd);
install_element (VIEW_NODE, &show_bgp_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_bgp_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_bgp_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
install_element (VIEW_NODE, &show_bgp_view_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_cmd);
install_element (VIEW_NODE, &show_bgp_view_route_cmd);
install_element (VIEW_NODE, &show_bgp_view_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd);
install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
install_element (VIEW_NODE, &show_bgp_view_rsclient_route_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
install_element (VIEW_NODE, &show_bgp_view_rsclient_prefix_cmd);
+ install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
+
+ /* Restricted:
+ * VIEW_NODE - (set of dangerous commands) - (commands dependent on prev)
+ */
+ install_element (RESTRICTED_NODE, &show_bgp_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community2_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community2_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community3_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community3_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community4_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community2_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community2_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community3_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community3_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_community4_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_exact_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_prefix_cmd);
+ install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_cmd);
install_element (ENABLE_NODE, &show_bgp_route_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_route_cmd);
install_element (ENABLE_NODE, &show_bgp_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_regexp_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_regexp_cmd);
install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd);
install_element (ENABLE_NODE, &show_bgp_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_prefix_cmd);
+ install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
install_element (ENABLE_NODE, &show_bgp_view_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_cmd);
install_element (ENABLE_NODE, &show_bgp_view_route_cmd);
install_element (ENABLE_NODE, &show_bgp_view_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_route_cmd);
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd);
-
+ install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
+
+ /* Statistics */
+ install_element (ENABLE_NODE, &show_bgp_statistics_cmd);
+ install_element (ENABLE_NODE, &show_bgp_statistics_vpnv4_cmd);
+ install_element (ENABLE_NODE, &show_bgp_statistics_view_cmd);
+ install_element (ENABLE_NODE, &show_bgp_statistics_view_vpnv4_cmd);
+
/* old command */
install_element (VIEW_NODE, &show_ipv6_bgp_cmd);
install_element (VIEW_NODE, &show_ipv6_bgp_route_cmd);
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);
+
+ /* Deprecated AS-Pathlimit commands */
+ install_element (BGP_NODE, &bgp_network_ttl_cmd);
+ install_element (BGP_NODE, &bgp_network_mask_ttl_cmd);
+ install_element (BGP_NODE, &bgp_network_mask_natural_ttl_cmd);
+ install_element (BGP_NODE, &bgp_network_backdoor_ttl_cmd);
+ install_element (BGP_NODE, &bgp_network_mask_backdoor_ttl_cmd);
+ install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd);
+
+ install_element (BGP_NODE, &no_bgp_network_ttl_cmd);
+ install_element (BGP_NODE, &no_bgp_network_mask_ttl_cmd);
+ install_element (BGP_NODE, &no_bgp_network_mask_natural_ttl_cmd);
+ install_element (BGP_NODE, &no_bgp_network_backdoor_ttl_cmd);
+ install_element (BGP_NODE, &no_bgp_network_mask_backdoor_ttl_cmd);
+ install_element (BGP_NODE, &no_bgp_network_mask_natural_backdoor_ttl_cmd);
+
+ install_element (BGP_IPV4_NODE, &bgp_network_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &bgp_network_mask_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &bgp_network_backdoor_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &bgp_network_mask_backdoor_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_backdoor_ttl_cmd);
+
+ install_element (BGP_IPV4_NODE, &no_bgp_network_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &no_bgp_network_mask_ttl_cmd);
+ install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_ttl_cmd);
+ 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_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, &no_bgp_network_ttl_cmd);
+ install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_ttl_cmd);
+ install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_ttl_cmd);
+ 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);
+
+#ifdef HAVE_IPV6
+ install_element (BGP_IPV6_NODE, &ipv6_bgp_network_ttl_cmd);
+ install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_ttl_cmd);
+#endif
+}
+
+void
+bgp_route_finish (void)
+{
+ bgp_table_unlock (bgp_distance_table);
+ bgp_distance_table = NULL;
}