static void bgp_evpn_show_route_rd_header(struct vty *vty,
struct bgp_node *rd_rn,
- json_object *json)
+ json_object *json,
+ char *rd_str, int len)
{
uint16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
uint8_t *pnt;
- char rd_str[RD_ADDRSTRLEN];
pnt = rd_rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type(pnt);
- if (json)
- return;
-
- vty_out(vty, "Route Distinguisher: ");
+ if (!json)
+ vty_out(vty, "Route Distinguisher: ");
switch (type) {
case RD_TYPE_AS:
decode_rd_as(pnt + 2, &rd_as);
- snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
+ snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
+ if (json)
+ json_object_string_add(json, "rd", rd_str);
+ else
+ vty_out(vty, "%s\n", rd_str);
+ break;
+
+ case RD_TYPE_AS4:
+ decode_rd_as4(pnt + 2, &rd_as);
+ snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
+ if (json)
+ json_object_string_add(json, "rd", rd_str);
+ else
+ vty_out(vty, "%s\n", rd_str);
break;
case RD_TYPE_IP:
decode_rd_ip(pnt + 2, &rd_ip);
- snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
+ snprintf(rd_str, len, "%s:%d", inet_ntoa(rd_ip.ip),
rd_ip.val);
+ if (json)
+ json_object_string_add(json, "rd", rd_str);
+ else
+ vty_out(vty, "%s\n", rd_str);
break;
default:
- snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
+ if (json) {
+ snprintf(rd_str, len, "Unknown");
+ json_object_string_add(json, "rd", rd_str);
+ } else {
+ snprintf(rd_str, len, "Unknown RD type");
+ vty_out(vty, "%s\n", rd_str);
+ }
break;
}
-
- vty_out(vty, "%s\n", rd_str);
}
static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
struct ecommunity *ecom;
json_object *json_import_rtl = NULL;
json_object *json_export_rtl = NULL;
+ char buf2[ETHER_ADDR_STRLEN];
json_import_rtl = json_export_rtl = 0;
json_object_string_add(json, "originatorIp",
inet_ntoa(bgp_vrf->originator_ip));
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
+ json_object_string_add(json, "advertiseSviMacip", "n/a");
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_NOSLASHESCAPE);
+ json_object_string_add(json, "advertisePip",
+ bgp_vrf->evpn_info->advertise_pip ?
+ "Enabled" : "Disabled");
+ json_object_string_add(json, "sysIP",
+ inet_ntop(AF_INET,
+ &bgp_vrf->evpn_info->pip_ip,
+ buf1, INET_ADDRSTRLEN));
+ json_object_string_add(json, "sysMac",
+ prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
+ buf2, sizeof(buf2)));
+ json_object_string_add(json, "rmac",
+ prefix_mac2str(&bgp_vrf->rmac,
+ buf2, sizeof(buf2)));
} else {
vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
vty_out(vty, " (known to the kernel)");
vty_out(vty, " Originator IP: %s\n",
inet_ntoa(bgp_vrf->originator_ip));
vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
+ vty_out(vty, " Advertise-svi-macip : %s\n", "n/a");
+ vty_out(vty, " Advertise-pip: %s\n",
+ bgp_vrf->evpn_info->advertise_pip ? "Yes" : "No");
+ vty_out(vty, " System-IP: %s\n",
+ inet_ntop(AF_INET, &bgp_vrf->evpn_info->pip_ip,
+ buf1, INET_ADDRSTRLEN));
+ vty_out(vty, " System-MAC: %s\n",
+ prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
+ buf2, sizeof(buf2)));
+ vty_out(vty, " Router-MAC: %s\n",
+ prefix_mac2str(&bgp_vrf->rmac,
+ buf2, sizeof(buf2)));
}
if (!json)
struct ecommunity *ecom;
json_object *json_import_rtl = NULL;
json_object *json_export_rtl = NULL;
+ struct bgp *bgp_evpn;
+
+ bgp_evpn = bgp_get_evpn();
if (json) {
json_import_rtl = json_object_new_array();
inet_ntoa(vpn->originator_ip));
json_object_string_add(json, "mcastGroup",
inet_ntoa(vpn->mcast_grp));
- json_object_string_add(json, "advertiseGatewayMacip",
- vpn->advertise_gw_macip ? "Yes" : "No");
+ /* per vni knob is enabled -- Enabled
+ * Global knob is enabled -- Active
+ * default -- Disabled
+ */
+ if (!vpn->advertise_gw_macip &&
+ bgp_evpn && bgp_evpn->advertise_gw_macip)
+ json_object_string_add(json, "advertiseGatewayMacip",
+ "Active");
+ else if (vpn->advertise_gw_macip)
+ json_object_string_add(json, "advertiseGatewayMacip",
+ "Enabled");
+ else
+ json_object_string_add(json, "advertiseGatewayMacip",
+ "Disabled");
+ if (!vpn->advertise_svi_macip && bgp_evpn &&
+ bgp_evpn->evpn_info->advertise_svi_macip)
+ json_object_string_add(json, "advertiseSviMacip",
+ "Active");
+ else if (vpn->advertise_svi_macip)
+ json_object_string_add(json, "advertiseSviMacip",
+ "Enabled");
+ else
+ json_object_string_add(json, "advertiseSviMacip",
+ "Disabled");
} else {
vty_out(vty, "VNI: %d", vpn->vni);
if (is_vni_live(vpn))
inet_ntoa(vpn->originator_ip));
vty_out(vty, " Mcast group: %s\n",
inet_ntoa(vpn->mcast_grp));
- vty_out(vty, " Advertise-gw-macip : %s\n",
- vpn->advertise_gw_macip ? "Yes" : "No");
- vty_out(vty, " Advertise-svi-macip : %s\n",
- vpn->advertise_svi_macip ? "Yes" : "No");
+ if (!vpn->advertise_gw_macip &&
+ bgp_evpn && bgp_evpn->advertise_gw_macip)
+ vty_out(vty, " Advertise-gw-macip : %s\n",
+ "Active");
+ else if (vpn->advertise_gw_macip)
+ vty_out(vty, " Advertise-gw-macip : %s\n",
+ "Enabled");
+ else
+ vty_out(vty, " Advertise-gw-macip : %s\n",
+ "Disabled");
+ if (!vpn->advertise_svi_macip && bgp_evpn &&
+ bgp_evpn->evpn_info->advertise_svi_macip)
+ vty_out(vty, " Advertise-svi-macip : %s\n",
+ "Active");
+ else if (vpn->advertise_svi_macip)
+ vty_out(vty, " Advertise-svi-macip : %s\n",
+ "Enabled");
+ else
+ vty_out(vty, " Advertise-svi-macip : %s\n",
+ "Disabled");
}
if (!json)
struct bgp_path_info *pi;
int rd_header;
int header = 1;
- char rd_str[BUFSIZ];
+ char rd_str[RD_ADDRSTRLEN];
char buf[BUFSIZ];
int no_display;
unsigned long output_count = 0;
unsigned long total_count = 0;
json_object *json = NULL;
- json_object *json_nroute = NULL;
json_object *json_array = NULL;
json_object *json_prefix_info = NULL;
- memset(rd_str, 0, BUFSIZ);
+ memset(rd_str, 0, RD_ADDRSTRLEN);
bgp = bgp_get_evpn();
if (bgp == NULL) {
for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
rn = bgp_route_next(rn)) {
uint64_t tbl_ver;
+ json_object *json_nroute = NULL;
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
continue;
continue;
no_display = 0;
- if (use_json) {
- json_array = json_object_new_array();
- json_prefix_info = json_object_new_object();
-
- json_object_string_add(json_prefix_info,
- "prefix", bgp_evpn_route2str(
- (struct prefix_evpn *)&rm->p, buf,
- BUFSIZ));
-
- json_object_int_add(json_prefix_info,
- "prefixLen", rm->p.prefixlen);
-
- if (rd_header)
- json_nroute = json_object_new_object();
- }
-
for (; pi; pi = pi->next) {
total_count++;
if (type == bgp_show_type_neighbor) {
header = 0;
}
if (rd_header) {
- uint16_t type;
- struct rd_as rd_as;
- struct rd_ip rd_ip;
- uint8_t *pnt;
-
- pnt = rn->p.u.val;
-
- /* Decode RD type. */
- type = decode_rd_type(pnt);
- /* Decode RD value. */
- if (type == RD_TYPE_AS)
- decode_rd_as(pnt + 2, &rd_as);
- else if (type == RD_TYPE_AS4)
- decode_rd_as4(pnt + 2, &rd_as);
- else if (type == RD_TYPE_IP)
- decode_rd_ip(pnt + 2, &rd_ip);
- if (use_json) {
- if (type == RD_TYPE_AS
- || type == RD_TYPE_AS4)
- sprintf(rd_str, "%u:%d",
- rd_as.as,
- rd_as.val);
- else if (type == RD_TYPE_IP)
- sprintf(rd_str, "%s:%d",
- inet_ntoa(
- rd_ip.ip),
- rd_ip.val);
- json_object_string_add(
- json_nroute,
- "rd",
- rd_str);
-
- } else {
- vty_out(vty,
- "Route Distinguisher: ");
- if (type == RD_TYPE_AS)
- vty_out(vty,
- "as2 %u:%d",
- rd_as.as,
- rd_as.val);
- else if (type == RD_TYPE_AS4)
- vty_out(vty,
- "as4 %u:%d",
- rd_as.as,
- rd_as.val);
- else if (type == RD_TYPE_IP)
- vty_out(vty, "ip %s:%d",
- inet_ntoa(
- rd_ip.ip),
- rd_ip.val);
- vty_out(vty, "\n\n");
- }
+ if (use_json)
+ json_nroute =
+ json_object_new_object();
+ bgp_evpn_show_route_rd_header(vty, rn,
+ json_nroute, rd_str,
+ RD_ADDRSTRLEN);
rd_header = 0;
}
+ if (use_json && !json_array)
+ json_array = json_object_new_array();
if (option == SHOW_DISPLAY_TAGS)
route_vty_out_tag(vty, &rm->p, pi,
if (no_display)
output_count++;
- if (use_json) {
+ if (use_json && json_array) {
+ json_prefix_info = json_object_new_object();
+
+ json_object_string_add(json_prefix_info,
+ "prefix", bgp_evpn_route2str(
+ (struct prefix_evpn *)&rm->p, buf,
+ BUFSIZ));
+
+ json_object_int_add(json_prefix_info,
+ "prefixLen", rm->p.prefixlen);
+
json_object_object_add(json_prefix_info,
"paths", json_array);
json_object_object_add(json_nroute, buf,
json_prefix_info);
+ json_array = NULL;
}
}
- if (use_json)
+ if (use_json && json_nroute)
json_object_object_add(json, rd_str, json_nroute);
}
prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
sizeof(rd_str));
- if (json) {
+ if (json)
json_rd = json_object_new_object();
- json_object_string_add(json_rd, "rd", rd_str);
- }
rd_header = 1;
/* RD header - per RD. */
if (rd_header) {
bgp_evpn_show_route_rd_header(
- vty, rd_rn, json);
+ vty, rd_rn, json_rd, rd_str,
+ RD_ADDRSTRLEN);
rd_header = 0;
}
return CMD_SUCCESS;
}
+DEFPY (bgp_evpn_advertise_pip_ip_mac,
+ bgp_evpn_advertise_pip_ip_mac_cmd,
+ "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
+ NO_STR
+ "evpn system primary IP\n"
+ IP_STR
+ "ip address\n"
+ MAC_STR MAC_STR MAC_STR)
+{
+ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
+ struct bgp *bgp_evpn = NULL;
+
+ if (EVPN_ENABLED(bgp_vrf)) {
+ vty_out(vty,
+ "This command is supported under L3VNI BGP EVPN VRF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ bgp_evpn = bgp_get_evpn();
+
+ if (!no) {
+ /* pip is already enabled */
+ if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
+ return CMD_SUCCESS;
+
+ bgp_vrf->evpn_info->advertise_pip = true;
+ if (ip.s_addr != INADDR_ANY) {
+ /* Already configured with same IP */
+ if (IPV4_ADDR_SAME(&ip,
+ &bgp_vrf->evpn_info->pip_ip_static))
+ return CMD_SUCCESS;
+
+ bgp_vrf->evpn_info->pip_ip_static = ip;
+ bgp_vrf->evpn_info->pip_ip = ip;
+ } else {
+ bgp_vrf->evpn_info->pip_ip_static.s_addr
+ = INADDR_ANY;
+ /* default instance router-id assignemt */
+ if (bgp_evpn)
+ bgp_vrf->evpn_info->pip_ip =
+ bgp_evpn->router_id;
+ }
+ /* parse sys mac */
+ if (!is_zero_mac(&mac->eth_addr)) {
+ /* Already configured with same MAC */
+ if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
+ &mac->eth_addr, ETH_ALEN) == 0)
+ return CMD_SUCCESS;
+
+ memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
+ &mac->eth_addr, ETH_ALEN);
+ memcpy(&bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->evpn_info->pip_rmac_static,
+ ETH_ALEN);
+ } else {
+ /* Copy zebra sys mac */
+ if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
+ memcpy(&bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->evpn_info->pip_rmac_zebra,
+ ETH_ALEN);
+ }
+ } else {
+ if (argc == 2) {
+ if (!bgp_vrf->evpn_info->advertise_pip)
+ return CMD_SUCCESS;
+ /* Disable PIP feature */
+ bgp_vrf->evpn_info->advertise_pip = false;
+ /* copy anycast mac */
+ memcpy(&bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->rmac, ETH_ALEN);
+ } else {
+ /* remove MAC-IP option retain PIP knob. */
+ if ((ip.s_addr != INADDR_ANY) &&
+ !IPV4_ADDR_SAME(&ip,
+ &bgp_vrf->evpn_info->pip_ip_static)) {
+ vty_out(vty,
+ "%% BGP EVPN PIP IP does not match\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (!is_zero_mac(&mac->eth_addr) &&
+ memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
+ &mac->eth_addr, ETH_ALEN) != 0) {
+ vty_out(vty,
+ "%% BGP EVPN PIP MAC does not match\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* pip_rmac can carry vrr_rmac reset only if it matches
+ * with static value.
+ */
+ if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->evpn_info->pip_rmac_static,
+ ETH_ALEN) == 0) {
+ /* Copy zebra sys mac */
+ if (!is_zero_mac(
+ &bgp_vrf->evpn_info->pip_rmac_zebra))
+ memcpy(&bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->evpn_info->pip_rmac_zebra,
+ ETH_ALEN);
+ else {
+ /* copy anycast mac */
+ memcpy(&bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->rmac, ETH_ALEN);
+ }
+ }
+ }
+ /* reset user configured sys MAC */
+ memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
+ /* reset user configured sys IP */
+ bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
+ /* Assign default PIP IP (bgp instance router-id) */
+ if (bgp_evpn)
+ bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
+ else
+ bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
+ }
+
+ if (is_evpn_enabled()) {
+ struct listnode *node = NULL;
+ struct bgpevpn *vpn = NULL;
+
+ update_advertise_vrf_routes(bgp_vrf);
+
+ /* Update (svi) type-2 routes */
+ for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
+ if (!bgp_evpn_is_svi_macip_enabled(vpn))
+ continue;
+ update_routes_for_vni(bgp_evpn, vpn);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
/*
* Display VNI information - for all or a specific VNI
*/
bgp_evpn->advertise_gw_macip
? "Enabled"
: "Disabled");
+ json_object_string_add(json, "advertiseSviMacip",
+ bgp_evpn->evpn_info->advertise_svi_macip
+ ? "Enabled" : "Disabled");
json_object_string_add(json, "advertiseAllVnis",
is_evpn_enabled() ? "Enabled"
: "Disabled");
safi_t safi)
{
char buf1[RD_ADDRSTRLEN];
+ char buf2[INET6_ADDRSTRLEN];
if (bgp->vnihash) {
struct list *vnilist = hash_to_list(bgp->vnihash);
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
vty_out(vty, " default-originate ipv6\n");
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
+ if (!bgp->evpn_info->advertise_pip)
+ vty_out(vty, " no advertise-pip\n");
+ if (bgp->evpn_info->advertise_pip) {
+ if (bgp->evpn_info->pip_ip_static.s_addr
+ != INADDR_ANY) {
+ vty_out(vty, " advertise-pip ip %s",
+ inet_ntop(AF_INET,
+ &bgp->evpn_info->pip_ip_static,
+ buf2, INET_ADDRSTRLEN));
+ if (!is_zero_mac(&(
+ bgp->evpn_info->pip_rmac_static))) {
+ char buf[ETHER_ADDR_STRLEN];
+
+ vty_out(vty, " mac %s",
+ prefix_mac2str(
+ &bgp->evpn_info
+ ->pip_rmac,
+ buf, sizeof(buf)));
+ }
+ vty_out(vty, "\n");
+ }
+ }
+ }
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
vty_out(vty, " rd %s\n",
prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
+ install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
/* test commands */
install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);