*/
#include <zebra.h>
+#include <math.h>
#include "prefix.h"
#include "linklist.h"
}
}
+void bgp_attr_add_gshut_community(struct attr *attr)
+{
+ struct community *old;
+ struct community *new;
+ struct community *merge;
+ struct community *gshut;
+
+ old = attr->community;
+ gshut = community_str2com("graceful-shutdown");
+
+ if (old) {
+ merge = community_merge(community_dup(old), gshut);
+
+ if (old->refcnt== 0)
+ community_free(old);
+
+ new = community_uniq_sort(merge);
+ community_free(merge);
+ } else {
+ new = community_dup(gshut);
+ }
+
+ community_free(gshut);
+ attr->community = new;
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
+
+ /* When we add the graceful-shutdown community we must also
+ * lower the local-preference */
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+ attr->local_pref = BGP_GSHUT_LOCAL_PREF;
+}
+
+
static void subgroup_announce_reset_nhop(u_char family, struct attr *attr)
{
if (family == AF_INET)
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) {
struct bgp_info info;
+ struct bgp_info_extra dummy_info_extra;
struct attr dummy_attr;
info.peer = peer;
info.attr = attr;
+
+ if (ri->extra) {
+ memcpy(&dummy_info_extra, ri->extra,
+ sizeof(struct bgp_info_extra));
+ info.extra = &dummy_info_extra;
+ }
+
/* don't confuse inbound and outbound setting */
RESET_FLAG(attr->rmap_change_flags);
}
}
+ if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+ if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+ attr->local_pref = BGP_GSHUT_LOCAL_PREF;
+ } else {
+ bgp_attr_add_gshut_community(attr);
+ }
+ }
+
/* After route-map has been applied, we check to see if the nexthop to
* be carried in the attribute (that is used for the announcement) can
* be cleared off or not. We do this in all cases where we would be
struct bgp_process_queue {
struct bgp *bgp;
- struct bgp_node *rn;
- afi_t afi;
- safi_t safi;
+ STAILQ_HEAD(, bgp_node)pqueue;
+#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
+ unsigned int flags;
+ unsigned int queued;
};
-static wq_item_status bgp_process_main(struct work_queue *wq, void *data)
+static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
+ afi_t afi, safi_t safi)
{
- struct bgp_process_queue *pq = data;
- struct bgp *bgp = pq->bgp;
- struct bgp_node *rn = pq->rn;
- afi_t afi = pq->afi;
- safi_t safi = pq->safi;
struct prefix *p = &rn->p;
struct bgp_info *new_select;
struct bgp_info *old_select;
bgp->main_peers_update_hold = 0;
bgp_start_routeadv(bgp);
- return WQ_SUCCESS;
+ return;
}
/* Best path selection. */
* to do this upon changes to best path except of the label index
* changes.
*/
- if (safi == SAFI_UNICAST) {
+ if (bgp->allocate_mpls_labels[afi][safi]) {
if (new_select) {
if (!old_select
|| bgp_label_index_differs(new_select, old_select)
} else
bgp_register_for_label(rn, new_select);
}
- } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
+ } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
bgp_unregister_for_label(rn);
+ }
+ } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
+ bgp_unregister_for_label(rn);
}
/* If best route remains the same and this is not due to user-initiated
vnc_import_bgp_add_route(bgp, p, old_select);
vnc_import_bgp_exterior_add_route(bgp, p, old_select);
#endif
- if (bgp_fibupd_safi(safi) && !bgp->name
+ if (bgp_fibupd_safi(safi)
&& !bgp_option_check(BGP_OPT_NO_FIB)
&& new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_NORMAL)
}
UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
- return WQ_SUCCESS;
+ return;
}
/* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
bgp_info_reap(rn, old_select);
UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
- return WQ_SUCCESS;
+ return;
}
-static void bgp_processq_del(struct work_queue *wq, void *data)
+static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
{
- struct bgp_process_queue *pq = data;
+ struct bgp_process_queue *pqnode = data;
+ struct bgp *bgp = pqnode->bgp;
struct bgp_table *table;
+ struct bgp_node *rn, *nrn;
+
+ /* eoiu marker */
+ if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
+ bgp_process_main_one(bgp, NULL, 0, 0);
- bgp_unlock(pq->bgp);
- if (pq->rn) {
- table = bgp_node_table(pq->rn);
- bgp_unlock_node(pq->rn);
+ return WQ_SUCCESS;
+ }
+
+ STAILQ_FOREACH_SAFE(rn, &pqnode->pqueue, pq, nrn) {
+ table = bgp_node_table(rn);
+
+ bgp_process_main_one(bgp, rn, table->afi, table->safi);
+
+ bgp_unlock_node(rn);
bgp_table_unlock(table);
}
- XFREE(MTYPE_BGP_PROCESS_QUEUE, pq);
+
+ return WQ_SUCCESS;
+}
+
+static void bgp_processq_del(struct work_queue *wq, void *data)
+{
+ struct bgp_process_queue *pqnode = data;
+
+ bgp_unlock(pqnode->bgp);
+
+ XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
}
void bgp_process_queue_init(void)
}
}
- bm->process_main_queue->spec.workfunc = &bgp_process_main;
+ bm->process_main_queue->spec.workfunc = &bgp_process_wq;
bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
bm->process_main_queue->spec.max_retries = 0;
bm->process_main_queue->spec.hold = 50;
bm->process_main_queue->spec.yield = 50 * 1000L;
}
+static struct bgp_process_queue *bgp_process_queue_work(struct work_queue *wq,
+ struct bgp *bgp)
+{
+ struct bgp_process_queue *pqnode;
+
+ pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, sizeof(struct bgp_process_queue));
+
+ /* unlocked in bgp_processq_del */
+ pqnode->bgp = bgp_lock(bgp);
+ STAILQ_INIT(&pqnode->pqueue);
+
+ work_queue_add(wq, pqnode);
+
+ return pqnode;
+}
+
void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
{
+#define ARBITRARY_PROCESS_QLEN 10000
+ struct work_queue *wq = bm->process_main_queue;
struct bgp_process_queue *pqnode;
/* already scheduled for processing? */
if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
return;
- if (bm->process_main_queue == NULL)
+ if (wq == NULL)
return;
- pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
- sizeof(struct bgp_process_queue));
- if (!pqnode)
- return;
+ /* Add route nodes to an existing work queue item until reaching the
+ limit only if is from the same BGP view and it's not an EOIU marker */
+ if (work_queue_item_count(wq)) {
+ struct work_queue_item *item = work_queue_last_item(wq);
+ pqnode = item->data;
+
+ if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER) ||
+ pqnode->bgp != bgp || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
+ pqnode = bgp_process_queue_work(wq, bgp);
+ } else
+ pqnode = bgp_process_queue_work(wq, bgp);
- /* all unlocked in bgp_processq_del */
+ /* all unlocked in bgp_process_wq */
bgp_table_lock(bgp_node_table(rn));
- pqnode->rn = bgp_lock_node(rn);
- pqnode->bgp = bgp;
- bgp_lock(bgp);
- pqnode->afi = afi;
- pqnode->safi = safi;
- work_queue_add(bm->process_main_queue, pqnode);
+
SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
+ bgp_lock_node(rn);
+
+ STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
+ pqnode->queued++;
+
return;
}
if (bm->process_main_queue == NULL)
return;
- pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
- sizeof(struct bgp_process_queue));
- if (!pqnode)
- return;
+ pqnode = bgp_process_queue_work(bm->process_main_queue, bgp);
- pqnode->rn = NULL;
- pqnode->bgp = bgp;
- bgp_lock(bgp);
- work_queue_add(bm->process_main_queue, pqnode);
+ SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
}
static int bgp_maximum_prefix_restart_timer(struct thread *thread)
int always)
{
iana_afi_t pkt_afi;
- safi_t pkt_safi;
+ iana_safi_t pkt_safi;
if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
return 0;
goto filtered;
}
+ if (peer->sort == BGP_PEER_EBGP) {
+
+ /* If we receive the graceful-shutdown community from an eBGP peer we
+ * must lower local-preference */
+ if (new_attr.community &&
+ community_include(new_attr.community, COMMUNITY_GSHUT)) {
+ new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+ new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
+
+ /* If graceful-shutdown is configured then add the GSHUT community to
+ * all paths received from eBGP peers */
+ } else if (bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+ bgp_attr_add_gshut_community(&new_attr);
+ }
+ }
+
/* next hop check. */
if (bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) {
reason = "martian or self next-hop;";
bgp_static_withdraw(bgp, p, afi, safi);
return;
}
+
+ if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ bgp_attr_add_gshut_community(&attr_tmp);
+
attr_new = bgp_attr_intern(&attr_tmp);
- } else
+ } else {
+
+ if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ bgp_attr_add_gshut_community(&attr);
+
attr_new = bgp_attr_intern(&attr);
+ }
for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
}
if (routermac) {
bgp_static->router_mac =
- XCALLOC(MTYPE_ATTR, ETHER_ADDR_LEN + 1);
+ XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
prefix_str2mac(routermac,
bgp_static->router_mac);
}
/* Redistribute route treatment. */
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
- const struct in_addr *nexthop,
- const struct in6_addr *nexthop6, unsigned int ifindex,
+ const union g_addr *nexthop, unsigned int ifindex,
u_int32_t metric, u_char type, u_short instance,
route_tag_t tag)
{
/* Make default attribute. */
bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
- if (nexthop)
- attr.nexthop = *nexthop;
- attr.nh_ifindex = ifindex;
-
- if (nexthop6) {
- attr.mp_nexthop_global = *nexthop6;
- attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+ if (nexthop) {
+ switch (p->family) {
+ case AF_INET:
+ attr.nexthop = nexthop->ipv4;
+ break;
+ case AF_INET6:
+ attr.mp_nexthop_global = nexthop->ipv6;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+ }
}
+ attr.nh_ifindex = ifindex;
attr.med = metric;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
}
}
+ if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ bgp_attr_add_gshut_community(&attr_new);
+
bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
SAFI_UNICAST, p, NULL);
} else
len += vty_out(vty, "/%d", p->prefixlen);
} else if (p->family == AF_ETHERNET) {
+ prefix2str(p, buf, PREFIX_STRLEN);
+ len = vty_out(vty, "%s", buf);
+ } else if (p->family == AF_EVPN) {
#if defined(HAVE_CUMULUS)
len = vty_out(vty, "%s",
bgp_evpn_route2str((struct prefix_evpn *)p, buf,
len = vty_out(
vty, "%s",
binfo->peer->conf_if);
- len =
- 7 - len; /* len of IPv6
- addr + max
- len of def
- ifname */
+ len = 16 - len; /* len of IPv6
+ addr + max
+ len of def
+ ifname */
if (len < 1)
vty_out(vty, "\n%*s",
- 45, " ");
+ 36, " ");
else
vty_out(vty, "%*s", len,
" ");
if (attr) {
if (((p->family == AF_INET)
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
- || (safi == SAFI_EVPN && p->family == AF_ETHERNET
+ || (safi == SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
}
} else if (((p->family == AF_INET6)
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
- || (safi == SAFI_EVPN && p->family == AF_ETHERNET
+ || (safi == SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
char buf_a[BUFSIZ];
/* Line2 display Next-hop, Neighbor, Router-id */
/* Display the nexthop */
- if ((p->family == AF_INET || p->family == AF_ETHERNET)
+ if ((p->family == AF_INET || p->family == AF_ETHERNET ||
+ p->family == AF_EVPN)
&& (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN
|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
const char *prefix, afi_t afi, safi_t safi,
enum bgp_show_type type);
-static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
+static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
+ const char *regstr, afi_t afi,
safi_t safi, enum bgp_show_type type);
-static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
- struct cmd_token **argv, int exact, afi_t afi,
+static int bgp_show_community(struct vty *vty, struct bgp *bgp,
+ const char *comstr, int exact, afi_t afi,
safi_t safi);
static int bgp_show_table(struct vty *vty, struct bgp *bgp,
if (bgp == NULL) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
+ else
+ vty_out(vty, "{}\n");
return CMD_WARNING;
}
if (!bgp) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
+ else
+ vty_out(vty, "{}\n");
return CMD_WARNING;
}
}
static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi);
-/* BGP route print out function. */
+
+/* BGP route print out function without JSON */
DEFUN (show_ip_bgp,
show_ip_bgp_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
- [<\
- cidr-only\
- |dampening <flap-statistics|dampened-paths|parameters>\
- |route-map WORD\
- |prefix-list WORD\
- |filter-list WORD\
- |statistics\
- |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
- |community-list <(1-500)|WORD> [exact-match]\
- |A.B.C.D/M longer-prefixes\
- |X:X::X:X/M longer-prefixes>\
- ] [json]",
+ <dampening <parameters>\
+ |route-map WORD\
+ |prefix-list WORD\
+ |filter-list WORD\
+ |statistics\
+ |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
+ |community-list <(1-500)|WORD> [exact-match]\
+ |A.B.C.D/M longer-prefixes\
+ |X:X::X:X/M longer-prefixes\
+ >",
SHOW_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
- "Display only routes with non-natural netmasks\n"
"Display detailed information about dampening\n"
- "Display flap statistics of routes\n"
- "Display paths suppressed due to dampening\n"
"Display detail of configured dampening parameters\n"
"Display routes matching the route-map\n"
"A route-map to match on\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"
+ "Graceful shutdown (well-known community)\n"
"Exact match of the communities\n"
"Display routes matching the community-list\n"
"community-list number\n"
"IPv4 prefix\n"
"Display route and more specific routes\n"
"IPv6 prefix\n"
- "Display route and more specific routes\n"
- JSON_STR)
+ "Display route and more specific routes\n")
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
int exact_match = 0;
- enum bgp_show_type sh_type = bgp_show_type_normal;
struct bgp *bgp = NULL;
int idx = 0;
+ int idx_community_type = 0;
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp);
if (!idx)
return CMD_WARNING;
- int uj = use_json(argc, argv);
- if (uj)
- argc--;
-
- if (argv_find(argv, argc, "cidr-only", &idx))
- return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
- NULL, uj);
-
if (argv_find(argv, argc, "dampening", &idx)) {
- if (argv_find(argv, argc, "dampened-paths", &idx))
- return bgp_show(vty, bgp, afi, safi,
- bgp_show_type_dampend_paths, NULL, uj);
- else if (argv_find(argv, argc, "flap-statistics", &idx))
- return bgp_show(vty, bgp, afi, safi,
- bgp_show_type_flap_statistics, NULL,
- uj);
- else if (argv_find(argv, argc, "parameters", &idx))
+ if (argv_find(argv, argc, "parameters", &idx))
return bgp_show_dampening_parameters(vty, afi, safi);
}
if (argv_find(argv, argc, "community", &idx)) {
/* show a specific community */
- if (argv_find(argv, argc, "local-AS", &idx)
- || argv_find(argv, argc, "no-advertise", &idx)
- || argv_find(argv, argc, "no-export", &idx)) {
- if (argv_find(argv, argc, "exact_match", &idx))
+ if (argv_find(argv, argc, "local-AS", &idx_community_type)
+ || argv_find(argv, argc, "no-advertise", &idx_community_type)
+ || argv_find(argv, argc, "no-export", &idx_community_type)
+ || argv_find(argv, argc, "graceful-shutdown", &idx_community_type)
+ || argv_find(argv, argc, "AA:NN", &idx_community_type)) {
+
+ if (argv_find(argv, argc, "exact-match", &idx))
exact_match = 1;
- return bgp_show_community(vty, bgp, argc, argv,
+ return bgp_show_community(vty, bgp, argv[idx_community_type]->arg,
exact_match, afi, safi);
}
- /* show all communities */
- else
- return bgp_show(vty, bgp, afi, safi,
- bgp_show_type_community_all, NULL, uj);
}
if (argv_find(argv, argc, "community-list", &idx)) {
safi,
bgp_show_type_prefix_longer);
+ return CMD_WARNING;
+}
+
+/* BGP route print out function with JSON */
+DEFUN (show_ip_bgp_json,
+ show_ip_bgp_json_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
+ [<\
+ cidr-only\
+ |dampening <flap-statistics|dampened-paths>\
+ |community \
+ >] [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display only routes with non-natural netmasks\n"
+ "Display detailed information about dampening\n"
+ "Display flap statistics of routes\n"
+ "Display paths suppressed due to dampening\n"
+ "Display routes matching the communities\n"
+ JSON_STR)
+{
+ afi_t afi = AFI_IP6;
+ safi_t safi = SAFI_UNICAST;
+ enum bgp_show_type sh_type = bgp_show_type_normal;
+ struct bgp *bgp = NULL;
+ int idx = 0;
+
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp);
+ if (!idx)
+ return CMD_WARNING;
+
+ int uj = use_json(argc, argv);
+ if (uj)
+ argc--;
+
+ if (argv_find(argv, argc, "cidr-only", &idx))
+ return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
+ NULL, uj);
+
+ if (argv_find(argv, argc, "dampening", &idx)) {
+ if (argv_find(argv, argc, "dampened-paths", &idx))
+ return bgp_show(vty, bgp, afi, safi,
+ bgp_show_type_dampend_paths, NULL, uj);
+ else if (argv_find(argv, argc, "flap-statistics", &idx))
+ return bgp_show(vty, bgp, afi, safi,
+ bgp_show_type_flap_statistics, NULL,
+ uj);
+ }
+
+ if (argv_find(argv, argc, "community", &idx)) {
+ /* show all communities */
+ return bgp_show(vty, bgp, afi, safi,
+ bgp_show_type_community_all, NULL, uj);
+ }
+
if (safi == SAFI_MPLS_VPN)
return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
NULL, 0, uj);
idx++;
char *regstr = argv_concat(argv, argc, idx);
- int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi,
+ int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
bgp_show_type_regexp);
XFREE(MTYPE_TMP, regstr);
return rc;
return CMD_SUCCESS;
}
-static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
+static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
+ const char *regstr, afi_t afi,
safi_t safi, enum bgp_show_type type)
{
regex_t *regex;
return CMD_WARNING;
}
- rc = bgp_show(vty, NULL, afi, safi, type, regex, 0);
+ rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
bgp_regex_free(regex);
return rc;
}
return bgp_show(vty, bgp, afi, safi, type, rmap, 0);
}
-static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc,
- struct cmd_token **argv, int exact, afi_t afi,
+static int bgp_show_community(struct vty *vty, struct bgp *bgp,
+ const char *comstr, int exact, afi_t afi,
safi_t safi)
{
struct community *com;
- struct buffer *b;
- int i;
- char *str;
- int first = 0;
int ret = 0;
- b = buffer_new(1024);
- for (i = 0; i < argc; i++) {
- if (first)
- buffer_putc(b, ' ');
- else {
- if (strmatch(argv[i]->text, "unicast")
- || strmatch(argv[i]->text, "multicast"))
- continue;
- first = 1;
- }
-
- buffer_putstr(b, argv[i]->arg);
- }
- buffer_putc(b, '\0');
-
- str = buffer_getstr(b);
- buffer_free(b);
-
- com = community_str2com(str);
- XFREE(MTYPE_TMP, str);
+ com = community_str2com(comstr);
if (!com) {
- vty_out(vty, "%% Community malformed: \n");
+ vty_out(vty, "%% Community malformed: %s\n", comstr);
return CMD_WARNING;
}
struct bgp_table_stats {
struct bgp_table *table;
unsigned long long counts[BGP_STATS_MAX];
+ double total_space;
};
#if 0
ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
/* announced address space */
if (space)
- ts->counts[BGP_STATS_SPACE] +=
- 1 << (space - rn->p.prefixlen);
+ ts->total_space += pow(2.0,
+ space - rn->p.prefixlen);
} else if (prn->info)
ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
break;
case BGP_STATS_SPACE:
vty_out(vty, "%-30s: ", table_stats_strs[i]);
- vty_out(vty, "%12llu\n", ts.counts[i]);
- if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
- break;
- vty_out(vty, "%30s: ", "%% announced ");
- vty_out(vty, "%12.2f\n",
- 100 * (float)ts.counts[BGP_STATS_SPACE]
- / (float)((uint64_t)1UL
- << ts.counts
- [BGP_STATS_MAXBITLEN]));
- vty_out(vty, "%30s: ", "/8 equivalent ");
- vty_out(vty, "%12.2f\n",
- (float)ts.counts[BGP_STATS_SPACE]
- / (float)(1UL
- << (ts.counts
- [BGP_STATS_MAXBITLEN]
- - 8)));
- 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)));
+ vty_out(vty, "%12g\n", ts.total_space);
+
+ if (afi == AFI_IP6) {
+ vty_out(vty, "%30s: ", "/32 equivalent ");
+ vty_out(vty, "%12g\n",
+ ts.total_space * pow(2.0, -128+32));
+ vty_out(vty, "%30s: ", "/48 equivalent ");
+ vty_out(vty, "%12g\n",
+ ts.total_space * pow(2.0, -128+48));
+ } else {
+ vty_out(vty, "%30s: ", "% announced ");
+ vty_out(vty, "%12.2f\n",
+ ts.total_space * 100. * pow(2.0, -32));
+ vty_out(vty, "%30s: ", "/8 equivalent ");
+ vty_out(vty, "%12.2f\n",
+ ts.total_space * pow(2.0, -32+8));
+ vty_out(vty, "%30s: ", "/24 equivalent ");
+ vty_out(vty, "%12.2f\n",
+ ts.total_space * pow(2.0, -32+24));
+ }
break;
default:
vty_out(vty, "%-30s: ", table_stats_strs[i]);
afi_t afi, safi_t safi,
enum bgp_show_type type, u_char use_json)
{
+ /* labeled-unicast routes live in the unicast table */
+ if (safi == SAFI_LABELED_UNICAST)
+ safi = SAFI_UNICAST;
+
if (!peer || !peer->afc[afi][safi]) {
if (use_json) {
json_object *json_no = NULL;
/* IPv4 labeled-unicast configuration. */
install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
install_element(VIEW_NODE, &show_ip_bgp_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);