#include "workqueue.h"
#include "queue.h"
#include "memory.h"
+#include "srv6.h"
#include "lib/json.h"
#include "lib_errors.h"
-
+#include "zclient.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
-
+const char *get_afi_safi_str(afi_t afi,
+ safi_t safi, bool for_json);
/* PMSI strings. */
#define PMSI_TNLTYPE_STR_NO_INFO "No info"
#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
return path;
}
+/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
+static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
+{
+ struct peer *peer;
+ struct bgp_path_info *old_pi, *nextpi;
+ bool set_flag = 0;
+ struct bgp *bgp = NULL;
+ struct bgp_table *table = NULL;
+ afi_t afi = 0;
+ safi_t safi = 0;
+ char buf[PREFIX2STR_BUFFER];
+
+ /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
+ * then the route selection is deferred
+ */
+ if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
+ return 0;
+
+ if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
+ if (BGP_DEBUG(update, UPDATE_OUT)) {
+ prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
+ zlog_debug("Route %s is in workqueue and being processed, not deferred.",
+ buf);
+ }
+ return 0;
+ }
+
+ table = bgp_node_table(rn);
+ if (table) {
+ bgp = table->bgp;
+ afi = table->afi;
+ safi = table->safi;
+ }
+
+ for (old_pi = bgp_node_get_bgp_path_info(rn);
+ (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
+ if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
+ continue;
+
+ /* Route selection is deferred if there is a stale path which
+ * which indicates peer is in restart mode
+ */
+ if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE) &&
+ (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
+ set_flag = 1;
+ } else {
+ /* If the peer is graceful restart capable and peer is
+ * restarting mode, set the flag BGP_NODE_SELECT_DEFER
+ */
+ peer = old_pi->peer;
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer) &&
+ BGP_PEER_RESTARTING_MODE(peer) &&
+ (old_pi && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
+ set_flag = 1;
+ }
+ }
+ if (set_flag)
+ break;
+ }
+
+ /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
+ * is active
+ */
+ if (set_flag && table) {
+ if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
+ SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
+ prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
+ if (rn->rt_node == NULL)
+ rn->rt_node = listnode_add(
+ bgp->gr_info[afi][safi].route_list, rn);
+ if (BGP_DEBUG(update, UPDATE_OUT))
+ zlog_debug("DEFER route %s, rn %p, node %p",
+ buf, rn, rn->rt_node);
+ return 0;
+ }
+ }
+ return -1;
+}
+
void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
{
struct bgp_path_info *top;
bgp_path_info_lock(pi);
bgp_lock_node(rn);
peer_lock(pi->peer); /* bgp_path_info peer reference */
+ bgp_node_set_defer_flag(rn, false);
}
/* Do the actual removal of info from RIB, for use by bgp_process
return 1;
}
+static int bgp_route_select_timer_expire(struct thread *thread)
+{
+ struct afi_safi_info *info;
+ afi_t afi;
+ safi_t safi;
+ struct bgp *bgp;
+
+ info = THREAD_ARG(thread);
+ afi = info->afi;
+ safi = info->safi;
+ bgp = info->bgp;
+
+ if (BGP_DEBUG(update, UPDATE_OUT))
+ zlog_debug("afi %d, safi %d : route select timer expired",
+ afi, safi);
+
+ bgp->gr_info[afi][safi].t_route_select = NULL;
+
+ XFREE(MTYPE_TMP, info);
+
+ /* Best path selection */
+ return bgp_best_path_select_defer(bgp, afi, safi);
+}
+
void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_path_info_pair *result, afi_t afi,
afi2str(afi), safi2str(safi));
}
+ /* The best path calculation for the route is deferred if
+ * BGP_NODE_SELECT_DEFER is set
+ */
+ if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+ if (BGP_DEBUG(update, UPDATE_OUT))
+ zlog_debug("SELECT_DEFER falg set for route %p", rn);
+ return;
+ }
+
/* Best path selection. */
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
return;
}
+/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
+int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ struct bgp_node *rn;
+ int cnt = 0;
+ struct afi_safi_info *thread_info;
+ struct listnode *node = NULL, *nnode = NULL;
+
+ if (bgp->gr_info[afi][safi].t_route_select)
+ BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
+
+ if (BGP_DEBUG(update, UPDATE_OUT)) {
+ zlog_debug("%s: processing route for %s : cnt %d",
+ __func__, get_afi_safi_str(afi, safi, false),
+ listcount(bgp->gr_info[afi][safi].route_list));
+ }
+
+ /* Process the route list */
+ node = listhead(bgp->gr_info[afi][safi].route_list);
+ while (node) {
+ rn = listgetdata(node);
+ nnode = node->next;
+ list_delete_node(bgp->gr_info[afi][safi].route_list, node);
+ rn->rt_node = NULL;
+
+ if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+ UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
+ bgp_process_main_one(bgp, rn, afi, safi);
+ cnt++;
+ if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
+ break;
+ }
+ node = nnode;
+ }
+
+ /* Send EOR message when all routes are processed */
+ if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
+ bgp_send_delayed_eor(bgp);
+ /* Send route processing complete message to RIB */
+ bgp_zebra_update(afi, safi, bgp->vrf_id,
+ ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
+ return 0;
+ }
+
+ thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
+
+ thread_info->afi = afi;
+ thread_info->safi = safi;
+ thread_info->bgp = bgp;
+
+ /* If there are more routes to be processed, start the
+ * selection timer
+ */
+ thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
+ BGP_ROUTE_SELECT_DELAY,
+ &bgp->gr_info[afi][safi].t_route_select);
+ return 0;
+}
+
static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
{
struct bgp_process_queue *pqnode = data;
if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
return;
+ /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
+ * the workqueue
+ */
+ if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+ if (BGP_DEBUG(update, UPDATE_OUT))
+ zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
+ rn);
+ return;
+ }
+
if (wq == NULL)
return;
void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
struct peer *peer, afi_t afi, safi_t safi)
{
+
+ struct bgp *bgp = NULL;
+ bool delete_route = false;
+
bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
- if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
bgp_path_info_delete(rn, pi); /* keep historical info */
- hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
+ /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
+ * flag
+ */
+ if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
+ delete_route = true;
+ else
+ if (bgp_node_set_defer_flag(rn, true) < 0)
+ delete_route = true;
+ if (delete_route) {
+ if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+ UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
+ bgp = pi->peer->bgp;
+ if ((rn->rt_node) &&
+ (bgp->gr_info[afi][safi]
+ .route_list)) {
+ list_delete_node(
+ bgp->gr_info[afi][safi]
+ .route_list,
+ rn->rt_node);
+ rn->rt_node = NULL;
+ }
+ }
+ }
+ }
+ hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
bgp_process(peer->bgp, rn, afi, safi);
}
if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
bgp_path_info_unset_flag(
rn, pi, BGP_PATH_STALE);
+ bgp_node_set_defer_flag(rn, false);
bgp_process(bgp, rn, afi, safi);
}
}
}
/* graceful restart STALE flag unset. */
- if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
+ if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
+ bgp_node_set_defer_flag(rn, false);
+ }
/* The attribute is changed. */
bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
bgp_set_valid_label(&extra->label[0]);
}
+ /* Update SRv6 SID */
+ if (attr->srv6_l3vpn) {
+ extra = bgp_path_info_extra_get(pi);
+ if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
+ sid_copy(&extra->sid[0],
+ &attr->srv6_l3vpn->sid);
+ extra->num_sids = 1;
+ }
+ } else if (attr->srv6_vpn) {
+ extra = bgp_path_info_extra_get(pi);
+ if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
+ sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
+ extra->num_sids = 1;
+ }
+ }
+
#if ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
bgp_set_valid_label(&extra->label[0]);
}
+ /* Update SRv6 SID */
+ if (safi == SAFI_MPLS_VPN) {
+ extra = bgp_path_info_extra_get(new);
+ if (attr->srv6_l3vpn) {
+ sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
+ extra->num_sids = 1;
+ } else if (attr->srv6_vpn) {
+ sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
+ extra->num_sids = 1;
+ }
+ }
+
/* Update Overlay Index */
if (afi == AFI_L2VPN) {
overlay_index_update(new->attr,
int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
+ if (peer->sort == BGP_PEER_IBGP)
+ return 1;
+
if (peer->sort == BGP_PEER_EBGP
&& (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
|| FILTER_LIST_OUT_NAME(filter)
int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
+ if (peer->sort == BGP_PEER_IBGP)
+ return 1;
+
if (peer->sort == BGP_PEER_EBGP
&& (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
|| FILTER_LIST_IN_NAME(filter)
if (pnt + BGP_ADDPATH_ID_LEN >= lim)
return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
- addpath_id = ntohl(*((uint32_t *)pnt));
+ memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
+ addpath_id = ntohl(addpath_id);
pnt += BGP_ADDPATH_ID_LEN;
}
vty_out(vty, " ");
}
-static char *bgp_nexthop_fqdn(struct peer *peer)
+static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
{
- if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+ if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)
+ && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
return peer->hostname;
return NULL;
}
struct bgp_path_info *path, int display, safi_t safi,
json_object *json_paths)
{
- struct attr *attr;
+ struct attr *attr = path->attr;
json_object *json_path = NULL;
json_object *json_nexthops = NULL;
json_object *json_nexthop_global = NULL;
bool nexthop_othervrf = false;
vrf_id_t nexthop_vrfid = VRF_DEFAULT;
const char *nexthop_vrfname = VRF_DEFAULT_NAME;
- char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
+ char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
if (json_paths)
json_path = json_object_new_object();
route_vty_out_route(p, vty, json_path);
}
- /* Print attribute */
- attr = path->attr;
-
/*
* If vrf id of nexthop is different from that of prefix,
* set up printable string to append
if (json_paths) {
json_nexthop_global = json_object_new_object();
- json_object_string_add(
- json_nexthop_global, "afi",
- nexthop_fqdn ? "fqdn"
- : (af == AF_INET) ? "ip" : "ipv6");
- json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn"
- : (af == AF_INET) ? "ip" : "ipv6",
- nexthop_fqdn ? nexthop_fqdn : nexthop);
+ json_object_string_add(json_nexthop_global, "ip",
+ nexthop);
+
+ if (nexthop_hostname)
+ json_object_string_add(json_nexthop_global,
+ "hostname",
+ nexthop_hostname);
+
+ json_object_string_add(json_nexthop_global, "afi",
+ (af == AF_INET) ? "ipv4"
+ : "ipv6");
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
vty_out(vty, "%s%s",
- nexthop_fqdn ? nexthop_fqdn : nexthop,
+ nexthop_hostname ? nexthop_hostname : nexthop,
vrf_id_str);
} else if (safi == SAFI_EVPN) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
- json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn ? nexthop_fqdn
- : inet_ntoa(attr->nexthop));
+ json_object_string_add(json_nexthop_global, "ip",
+ inet_ntoa(attr->nexthop));
+
+ if (nexthop_hostname)
+ json_object_string_add(json_nexthop_global,
+ "hostname",
+ nexthop_hostname);
+
json_object_string_add(json_nexthop_global, "afi",
"ipv4");
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
vty_out(vty, "%-16s%s",
- nexthop_fqdn ?: inet_ntoa(attr->nexthop),
+ nexthop_hostname ? nexthop_hostname
+ : inet_ntoa(attr->nexthop),
vrf_id_str);
} else if (safi == SAFI_FLOWSPEC) {
if (attr->nexthop.s_addr != 0) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
- json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntoa(attr->nexthop));
+
json_object_string_add(json_nexthop_global,
"afi", "ipv4");
+ json_object_string_add(
+ json_nexthop_global, "ip",
+ inet_ntoa(attr->nexthop));
+
+ if (nexthop_hostname)
+ json_object_string_add(
+ json_nexthop_global, "hostname",
+ nexthop_hostname);
+
json_object_boolean_true_add(
json_nexthop_global,
"used");
} else {
vty_out(vty, "%-16s",
- nexthop_fqdn
- ? nexthop_fqdn
+ nexthop_hostname
+ ? nexthop_hostname
: inet_ntoa(attr->nexthop));
}
}
if (json_paths) {
json_nexthop_global = json_object_new_object();
- json_object_string_add(json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntoa(attr->nexthop));
+ json_object_string_add(json_nexthop_global, "ip",
+ inet_ntoa(attr->nexthop));
+
+ if (nexthop_hostname)
+ json_object_string_add(json_nexthop_global,
+ "hostname",
+ nexthop_hostname);
json_object_string_add(json_nexthop_global, "afi",
"ipv4");
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "%s%s",
- nexthop_fqdn ? nexthop_fqdn
- : inet_ntoa(attr->nexthop),
+ nexthop_hostname ? nexthop_hostname
+ : inet_ntoa(attr->nexthop),
vrf_id_str);
vty_out(vty, "%-16s", buf);
}
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntop(AF_INET6,
- &attr->mp_nexthop_global,
- buf, BUFSIZ));
+ json_nexthop_global, "ip",
+ inet_ntop(AF_INET6, &attr->mp_nexthop_global,
+ buf, BUFSIZ));
+
+ if (nexthop_hostname)
+ json_object_string_add(json_nexthop_global,
+ "hostname",
+ nexthop_hostname);
+
json_object_string_add(json_nexthop_global, "afi",
"ipv6");
json_object_string_add(json_nexthop_global, "scope",
|| (path->peer->conf_if)) {
json_nexthop_ll = json_object_new_object();
json_object_string_add(
- json_nexthop_ll,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntop(
- AF_INET6,
- &attr->mp_nexthop_local,
- buf, BUFSIZ));
+ json_nexthop_ll, "ip",
+ inet_ntop(AF_INET6,
+ &attr->mp_nexthop_local, buf,
+ BUFSIZ));
+
+ if (nexthop_hostname)
+ json_object_string_add(
+ json_nexthop_ll, "hostname",
+ nexthop_hostname);
+
json_object_string_add(json_nexthop_ll, "afi",
"ipv6");
json_object_string_add(json_nexthop_ll, "scope",
} else {
len = vty_out(
vty, "%s%s",
- nexthop_fqdn
- ? nexthop_fqdn
+ nexthop_hostname
+ ? nexthop_hostname
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
} else {
len = vty_out(
vty, "%s%s",
- nexthop_fqdn
- ? nexthop_fqdn
+ nexthop_hostname
+ ? nexthop_hostname
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_global,
char buf[INET6_ADDRSTRLEN];
char buf1[BUFSIZ];
char buf2[EVPN_ROUTE_STRLEN];
- struct attr *attr;
+ struct attr *attr = path->attr;
int sockunion_vty_out(struct vty *, union sockunion *);
time_t tbuf;
json_object *json_bestpath = NULL;
bool nexthop_self =
CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
int i;
- char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
+ char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
if (json_paths) {
json_path = json_object_new_object();
}
}
- attr = path->attr;
-
/* Line1 display AS-path, Aggregator */
if (attr->aspath) {
if (json_paths) {
|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
- if (json_paths)
+ if (json_paths) {
json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntoa(
- attr->mp_nexthop_global_in));
- else
+ json_nexthop_global, "ip",
+ inet_ntoa(attr->mp_nexthop_global_in));
+
+ if (nexthop_hostname)
+ json_object_string_add(
+ json_nexthop_global, "hostname",
+ nexthop_hostname);
+ } else
vty_out(vty, " %s",
- nexthop_fqdn
- ? nexthop_fqdn
+ nexthop_hostname
+ ? nexthop_hostname
: inet_ntoa(
- attr->mp_nexthop_global_in));
+ attr->mp_nexthop_global_in));
} else {
- if (json_paths)
+ if (json_paths) {
json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntoa(attr->nexthop));
- else
+ json_nexthop_global, "ip",
+ inet_ntoa(attr->nexthop));
+
+ if (nexthop_hostname)
+ json_object_string_add(
+ json_nexthop_global, "hostname",
+ nexthop_hostname);
+ } else
vty_out(vty, " %s",
- nexthop_fqdn
- ? nexthop_fqdn
+ nexthop_hostname
+ ? nexthop_hostname
: inet_ntoa(attr->nexthop));
}
} else {
if (json_paths) {
json_object_string_add(
- json_nexthop_global,
- nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntop(AF_INET6,
- &attr->mp_nexthop_global,
- buf, INET6_ADDRSTRLEN));
+ json_nexthop_global, "ip",
+ inet_ntop(AF_INET6, &attr->mp_nexthop_global,
+ buf, INET6_ADDRSTRLEN));
+
+ if (nexthop_hostname)
+ json_object_string_add(json_nexthop_global,
+ "hostname",
+ nexthop_hostname);
+
json_object_string_add(json_nexthop_global, "afi",
"ipv6");
json_object_string_add(json_nexthop_global, "scope",
"global");
} else {
vty_out(vty, " %s",
- nexthop_fqdn
- ? nexthop_fqdn
+ nexthop_hostname
+ ? nexthop_hostname
: inet_ntop(AF_INET6,
&attr->mp_nexthop_global,
buf, INET6_ADDRSTRLEN));
if (json_paths) {
json_nexthop_ll = json_object_new_object();
json_object_string_add(
- json_nexthop_ll, nexthop_fqdn ? "fqdn" : "ip",
- nexthop_fqdn
- ? nexthop_fqdn
- : inet_ntop(AF_INET6,
- &attr->mp_nexthop_local,
- buf, INET6_ADDRSTRLEN));
+ json_nexthop_ll, "ip",
+ inet_ntop(AF_INET6, &attr->mp_nexthop_local,
+ buf, INET6_ADDRSTRLEN));
+
+ if (nexthop_hostname)
+ json_object_string_add(json_nexthop_ll,
+ "hostname",
+ nexthop_hostname);
+
json_object_string_add(json_nexthop_ll, "afi", "ipv6");
json_object_string_add(json_nexthop_ll, "scope",
"link-local");
vty_out(vty, " Remote label: %d\n", label);
}
+ /* Remote SID */
+ if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
+ inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
+ if (json_paths)
+ json_object_string_add(json_path, "remoteSid", buf);
+ else
+ vty_out(vty, " Remote SID: %s\n", buf);
+ }
+
/* Label Index */
if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
if (json_paths)
const char *prefix, afi_t afi, safi_t safi,
enum bgp_show_type type);
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);
+ afi_t afi, safi_t safi, enum bgp_show_type type,
+ bool use_json);
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
const char *comstr, int exact, afi_t afi,
safi_t safi, bool use_json);
vty_out(vty, ",\"%s\": ", buf2);
}
vty_out(vty, "%s",
- json_object_to_json_string(json_paths));
+ json_object_to_json_string_ext(
+ json_paths, JSON_C_TO_STRING_PRETTY));
json_object_free(json_paths);
json_paths = NULL;
first = 0;
DEFUN (show_ip_bgp_regexp,
show_ip_bgp_regexp_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...",
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
SHOW_STR
IP_STR
BGP_STR
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
"Display routes matching the AS path regular expression\n"
- "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
+ "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
+ JSON_STR)
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
struct bgp *bgp = NULL;
+ bool uj = use_json(argc, argv);
+ char *regstr = NULL;
int idx = 0;
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
return CMD_WARNING;
// get index of regex
- argv_find(argv, argc, "regexp", &idx);
- idx++;
+ if (argv_find(argv, argc, "REGEX", &idx))
+ regstr = argv[idx]->arg;
- char *regstr = argv_concat(argv, argc, idx);
- int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
- bgp_show_type_regexp);
- XFREE(MTYPE_TMP, regstr);
- return rc;
+ assert(regstr);
+ return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
+ bgp_show_type_regexp, uj);
}
DEFUN (show_ip_bgp_instance_all,
}
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)
+ afi_t afi, safi_t safi, enum bgp_show_type type,
+ bool use_json)
{
regex_t *regex;
int rc;
if (!config_bgp_aspath_validate(regstr)) {
- vty_out(vty, "Invalid character in as-path access-list %s\n",
+ vty_out(vty, "Invalid character in REGEX %s\n",
regstr);
return CMD_WARNING_CONFIG_FAILED;
}
return CMD_WARNING;
}
- rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
+ rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json);
bgp_regex_free(regex);
return rc;
}
unsigned int count[PCOUNT_MAX];
const struct peer *peer;
const struct bgp_table *table;
+ safi_t safi;
};
-static int bgp_peer_count_walker(struct thread *t)
+static void bgp_peer_count_proc(struct bgp_node *rn,
+ struct peer_pcounts *pc)
{
- struct bgp_node *rn;
- struct peer_pcounts *pc = THREAD_ARG(t);
+ const struct bgp_adj_in *ain;
+ const struct bgp_path_info *pi;
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_path_info *pi;
-
- for (ain = rn->adj_in; ain; ain = ain->next)
- if (ain->peer == peer)
- pc->count[PCOUNT_ADJ_IN]++;
+ for (ain = rn->adj_in; ain; ain = ain->next)
+ if (ain->peer == peer)
+ pc->count[PCOUNT_ADJ_IN]++;
- for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
+ for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
- if (pi->peer != peer)
- continue;
+ if (pi->peer != peer)
+ continue;
- pc->count[PCOUNT_ALL]++;
+ pc->count[PCOUNT_ALL]++;
- if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
- pc->count[PCOUNT_DAMPED]++;
- if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
- pc->count[PCOUNT_HISTORY]++;
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
- pc->count[PCOUNT_REMOVED]++;
- if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
- pc->count[PCOUNT_STALE]++;
- if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
- pc->count[PCOUNT_VALID]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
+ pc->count[PCOUNT_DAMPED]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
+ pc->count[PCOUNT_HISTORY]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
+ pc->count[PCOUNT_REMOVED]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
+ pc->count[PCOUNT_STALE]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
+ pc->count[PCOUNT_VALID]++;
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
+ pc->count[PCOUNT_PFCNT]++;
+
+ if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
+ pc->count[PCOUNT_COUNTED]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
+ flog_err(
+ EC_LIB_DEVELOPMENT,
+ "Attempting to count but flags say it is unusable");
+ } else {
if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
- pc->count[PCOUNT_PFCNT]++;
-
- if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
- pc->count[PCOUNT_COUNTED]++;
- if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
- flog_err(
- EC_LIB_DEVELOPMENT,
- "Attempting to count but flags say it is unusable");
- } else {
- if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
- flog_err(
- EC_LIB_DEVELOPMENT,
- "Not counted but flags say we should");
- }
+ flog_err(
+ EC_LIB_DEVELOPMENT,
+ "Not counted but flags say we should");
}
}
+}
+
+static int bgp_peer_count_walker(struct thread *t)
+{
+ struct bgp_node *rn, *rm;
+ const struct bgp_table *table;
+ struct peer_pcounts *pc = THREAD_ARG(t);
+
+ if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
+ || pc->safi == SAFI_EVPN) {
+ /* Special handling for 2-level routing tables. */
+ for (rn = bgp_table_top(pc->table); rn;
+ rn = bgp_route_next(rn)) {
+ table = bgp_node_get_bgp_table_info(rn);
+ if (table != NULL)
+ for (rm = bgp_table_top(table); rm;
+ rm = bgp_route_next(rm))
+ bgp_peer_count_proc(rm, pc);
+ }
+ } else
+ for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
+ bgp_peer_count_proc(rn, pc);
+
return 0;
}
memset(&pcounts, 0, sizeof(pcounts));
pcounts.peer = peer;
pcounts.table = peer->bgp->rib[afi][safi];
+ pcounts.safi = 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