#include "bgpd/bgp_evpn_vty.h"
#include "bgpd/bgp_flowspec.h"
#include "bgpd/bgp_flowspec_util.h"
+#include "bgpd/bgp_pbr.h"
#ifndef VTYSH_EXTRACT_PL
#include "bgpd/bgp_route_clippy.c"
{0}
};
+#define VRFID_NONE_STR "-"
+
struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p,
struct prefix_rd *prd)
struct bgp_info *bgp_info_unlock(struct bgp_info *binfo)
{
+ /* unlink reference to parent, if any. */
+ if (binfo->extra && binfo->extra->parent) {
+ bgp_info_unlock((struct bgp_info *)binfo->extra->parent);
+ binfo->extra->parent = NULL;
+ }
assert(binfo && binfo->lock > 0);
binfo->lock--;
}
if (family == AF_INET6)
memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
+ if (family == AF_EVPN)
+ memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
}
int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
/* If best route remains the same and this is not due to user-initiated
* clear, see exactly what needs to be done.
*/
-
if (old_select && old_select == new_select
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|| new_select->sub_type == BGP_ROUTE_AGGREGATE
- || new_select->sub_type == BGP_ROUTE_IMPORTED))
+ || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
+
+ /* if this is an evpn imported type-5 prefix,
+ * we need to withdraw the route first to clear
+ * the nh neigh and the RMAC entry.
+ */
+ if (old_select &&
+ is_route_parent_evpn(old_select))
+ bgp_zebra_withdraw(p, old_select, bgp, safi);
bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
- else {
+ } else {
/* Withdraw the route from the kernel. */
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
&& (old_select->sub_type == BGP_ROUTE_NORMAL
/* advertise/withdraw type-5 routes */
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (advertise_type5_routes(bgp, afi) && new_select &&
- (!new_select->extra || !new_select->extra->parent))
- bgp_evpn_advertise_type5_route(bgp, &rn->p,
- new_select->attr,
- afi, safi);
- else if (advertise_type5_routes(bgp, afi) && old_select &&
- (!old_select->extra || !old_select->extra->parent))
+ (!new_select->extra || !new_select->extra->parent)) {
+
+ /* apply the route-map */
+ if (bgp->adv_cmd_rmap[afi][safi].map) {
+ int ret = 0;
+
+ ret = route_map_apply(
+ bgp->adv_cmd_rmap[afi][safi].map,
+ &rn->p, RMAP_BGP, new_select);
+ if (ret == RMAP_MATCH)
+ bgp_evpn_advertise_type5_route(
+ bgp, &rn->p, new_select->attr,
+ afi, safi);
+ } else {
+ bgp_evpn_advertise_type5_route(bgp,
+ &rn->p,
+ new_select->attr,
+ afi, safi);
+
+ }
+ } else if (advertise_type5_routes(bgp, afi) && old_select &&
+ (!old_select->extra || !old_select->extra->parent))
bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
}
json_object *json_nexthops = NULL;
json_object *json_nexthop_global = NULL;
json_object *json_nexthop_ll = NULL;
+ char vrf_id_str[VRF_NAMSIZ] = {0};
+ bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
+ ? true
+ : false;
+ bool nexthop_othervrf = false;
+ vrf_id_t nexthop_vrfid = VRF_DEFAULT;
+ const char *nexthop_vrfname = "Default";
if (json_paths)
json_path = json_object_new_object();
return;
}
+ /*
+ * If vrf id of nexthop is different from that of prefix,
+ * set up printable string to append
+ */
+ if (binfo->extra && binfo->extra->bgp_orig) {
+ const char *self = "";
+
+ if (nexthop_self)
+ self = "<";
+
+ nexthop_othervrf = true;
+ nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
+
+ if (binfo->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
+ snprintf(vrf_id_str, sizeof(vrf_id_str),
+ "@%s%s", VRFID_NONE_STR, self);
+ else
+ snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
+ binfo->extra->bgp_orig->vrf_id, self);
+
+ if (binfo->extra->bgp_orig->inst_type !=
+ BGP_INSTANCE_TYPE_DEFAULT)
+
+ nexthop_vrfname = binfo->extra->bgp_orig->name;
+ } else {
+ const char *self = "";
+
+ if (nexthop_self)
+ self = "<";
+
+ snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
+ }
+
/*
* For ENCAP and EVPN routes, nexthop address family is not
* neccessarily the same as the prefix address family.
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
- vty_out(vty, "%s", nexthop);
+ vty_out(vty, "%s%s", nexthop, vrf_id_str);
} else if (safi == SAFI_EVPN) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
- vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
+ vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
+ vrf_id_str);
} else if (safi == SAFI_FLOWSPEC) {
if (attr->nexthop.s_addr != 0) {
if (json_paths) {
json_object_boolean_true_add(json_nexthop_global,
"used");
} else {
+ char buf[BUFSIZ];
+
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
- vty_out(vty, "%-16s",
- inet_ntoa(attr->mp_nexthop_global_in));
+ snprintf(buf, sizeof(buf), "%s%s",
+ inet_ntoa(attr->mp_nexthop_global_in),
+ vrf_id_str);
else
- vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
+ snprintf(buf, sizeof(buf), "%s%s",
+ inet_ntoa(attr->nexthop),
+ vrf_id_str);
+ vty_out(vty, "%-16s", buf);
}
}
vty_out(vty, "%*s", len, " ");
} else {
len = vty_out(
- vty, "%s",
+ vty, "%s%s",
inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
- buf, BUFSIZ));
+ buf, BUFSIZ),
+ vrf_id_str);
len = 16 - len;
if (len < 1)
}
} else {
len = vty_out(
- vty, "%s",
+ vty, "%s%s",
inet_ntop(AF_INET6,
&attr->mp_nexthop_global, buf,
- BUFSIZ));
+ BUFSIZ),
+ vrf_id_str);
len = 16 - len;
if (len < 1)
else
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
+ if (json_paths) {
+ if (nexthop_self)
+ json_object_boolean_true_add(json_path,
+ "announceNexthopSelf");
+ if (nexthop_othervrf) {
+ json_object_string_add(json_path, "nhVrfName",
+ nexthop_vrfname);
+
+ json_object_int_add(json_path, "nhVrfId",
+ ((nexthop_vrfid == VRF_UNKNOWN)
+ ? -1
+ : (int)nexthop_vrfid));
+ }
+ }
+
if (json_paths) {
if (json_nexthop_global || json_nexthop_ll) {
json_nexthops = json_object_new_array();
json_object *json_cluster_list = NULL;
json_object *json_cluster_list_list = NULL;
json_object *json_ext_community = NULL;
- json_object *json_lcommunity = NULL;
json_object *json_last_update = NULL;
json_object *json_pmsi = NULL;
json_object *json_nexthop_global = NULL;
int addpath_capable;
int has_adj;
unsigned int first_as;
+ bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
+ ? true
+ : false;
if (json_paths) {
json_path = json_object_new_object();
}
}
+ /*
+ * Note when vrfid of nexthop is different from that of prefix
+ */
+ if (binfo->extra && binfo->extra->bgp_orig) {
+ vrf_id_t nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
+
+ if (json_paths) {
+ const char *vn;
+
+ if (binfo->extra->bgp_orig->inst_type ==
+ BGP_INSTANCE_TYPE_DEFAULT)
+
+ vn = "Default";
+ else
+ vn = binfo->extra->bgp_orig->name;
+
+ json_object_string_add(json_path, "nhVrfName",
+ vn);
+
+ if (nexthop_vrfid == VRF_UNKNOWN) {
+ json_object_int_add(json_path,
+ "nhVrfId", -1);
+ } else {
+ json_object_int_add(json_path,
+ "nhVrfId", (int)nexthop_vrfid);
+ }
+ } else {
+ if (nexthop_vrfid == VRF_UNKNOWN)
+ vty_out(vty, " vrf ?");
+ else
+ vty_out(vty, " vrf %u", nexthop_vrfid);
+ }
+ }
+
+ if (nexthop_self) {
+ if (json_paths) {
+ json_object_boolean_true_add(json_path,
+ "announceNexthopSelf");
+ } else {
+ vty_out(vty, " announce-nh-self");
+ }
+ }
+
if (!json_paths)
vty_out(vty, "\n");
/* Line 6 display Large community */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
if (json_paths) {
- json_lcommunity = json_object_new_object();
- json_object_string_add(json_lcommunity,
- "string",
- attr->lcommunity->str);
+ if (!attr->lcommunity->json)
+ lcommunity_str(attr->lcommunity, true);
+ json_object_lock(attr->lcommunity->json);
json_object_object_add(json_path,
"largeCommunity",
- json_lcommunity);
+ attr->lcommunity->json);
} else {
vty_out(vty, " Large Community: %s\n",
attr->lcommunity->str);
if (!use_json && header) {
vty_out(vty, "BGP table version is %" PRIu64
- ", local router ID is %s\n",
+ ", local router ID is %s, vrf id ",
table->version,
inet_ntoa(bgp->router_id));
+ if (bgp->vrf_id == VRF_UNKNOWN)
+ vty_out(vty, "%s", VRFID_NONE_STR);
+ else
+ vty_out(vty, "%u", bgp->vrf_id);
+ vty_out(vty, "\n");
vty_out(vty, BGP_SHOW_SCODE_HEADER);
+ vty_out(vty, BGP_SHOW_NCODE_HEADER);
vty_out(vty, BGP_SHOW_OCODE_HEADER);
if (type == bgp_show_type_dampend_paths
|| type == bgp_show_type_damp_neighbor)
"0.0.0.0");
} else {
vty_out(vty, "BGP table version is %" PRIu64
- ", local router ID is %s\n",
+ ", local router ID is %s, vrf id ",
table->version, inet_ntoa(bgp->router_id));
+ if (bgp->vrf_id == VRF_UNKNOWN)
+ vty_out(vty, "%s", VRFID_NONE_STR);
+ else
+ vty_out(vty, "%u", bgp->vrf_id);
+ vty_out(vty, "\n");
vty_out(vty, BGP_SHOW_SCODE_HEADER);
+ vty_out(vty, BGP_SHOW_NCODE_HEADER);
vty_out(vty, BGP_SHOW_OCODE_HEADER);
vty_out(vty, "Originating default network 0.0.0.0\n\n");
json_ocode);
} else {
vty_out(vty,
- "BGP table version is 0, local router ID is %s\n",
+ "BGP table version is 0, local router ID is %s, vrf id ",
inet_ntoa(
- bgp->router_id));
+ bgp->router_id));
+ if (bgp->vrf_id == VRF_UNKNOWN)
+ vty_out(vty, "%s",
+ VRFID_NONE_STR);
+ else
+ vty_out(vty, "%u",
+ bgp->vrf_id);
+ vty_out(vty, "\n");
vty_out(vty,
BGP_SHOW_SCODE_HEADER);
+ vty_out(vty,
+ BGP_SHOW_NCODE_HEADER);
vty_out(vty,
BGP_SHOW_OCODE_HEADER);
}
} else {
vty_out(vty,
"BGP table version is %" PRIu64
- ", local router ID is %s\n",
+ ", local router ID is %s, vrf id ",
table->version,
inet_ntoa(
bgp->router_id));
+ if (bgp->vrf_id ==
+ VRF_UNKNOWN)
+ vty_out(vty,
+ "%s",
+ VRFID_NONE_STR);
+ else
+ vty_out(vty,
+ "%u",
+ bgp->vrf_id);
+ vty_out(vty, "\n");
vty_out(vty,
BGP_SHOW_SCODE_HEADER);
+ vty_out(vty,
+ BGP_SHOW_NCODE_HEADER);
vty_out(vty,
BGP_SHOW_OCODE_HEADER);
}