]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_evpn_vty.c
Merge pull request #5703 from ton31337/feature/limit_outgoing_prefixes
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
index 55f85eeb83496ec2ece43c4797c6d4759695e3f7..3049a00ce3205822958d66b8738de902c7e547c2 100644 (file)
@@ -298,7 +298,7 @@ static void bgp_evpn_show_route_rd_header(struct vty *vty,
                if (json)
                        json_object_string_add(json, "rd", rd_str);
                else
-                       vty_out(vty, "as2 %s\n", rd_str);
+                       vty_out(vty, "%s\n", rd_str);
                break;
 
        case RD_TYPE_AS4:
@@ -307,7 +307,7 @@ static void bgp_evpn_show_route_rd_header(struct vty *vty,
                if (json)
                        json_object_string_add(json, "rd", rd_str);
                else
-                       vty_out(vty, "as4 %s\n", rd_str);
+                       vty_out(vty, "%s\n", rd_str);
                break;
 
        case RD_TYPE_IP:
@@ -317,7 +317,7 @@ static void bgp_evpn_show_route_rd_header(struct vty *vty,
                if (json)
                        json_object_string_add(json, "rd", rd_str);
                else
-                       vty_out(vty, "ip %s\n", rd_str);
+                       vty_out(vty, "%s\n", rd_str);
                break;
 
        default:
@@ -326,7 +326,7 @@ static void bgp_evpn_show_route_rd_header(struct vty *vty,
                        json_object_string_add(json, "rd", rd_str);
                } else {
                        snprintf(rd_str, len, "Unknown RD type");
-                       vty_out(vty, "ip %s\n", rd_str);
+                       vty_out(vty, "%s\n", rd_str);
                }
                break;
        }
@@ -364,6 +364,7 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
        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;
 
@@ -382,6 +383,19 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
                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)");
@@ -396,6 +410,17 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
                        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)
@@ -2619,10 +2644,8 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
                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;
 
@@ -2659,7 +2682,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
                                /* RD header - per RD. */
                                if (rd_header) {
                                        bgp_evpn_show_route_rd_header(
-                                               vty, rd_rn, NULL, rd_str,
+                                               vty, rd_rn, json_rd, rd_str,
                                                RD_ADDRSTRLEN);
                                        rd_header = 0;
                                }
@@ -3652,6 +3675,139 @@ DEFUN (no_bgp_evpn_advertise_type5,
        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
  */
@@ -5385,6 +5541,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
                                safi_t safi)
 {
        char buf1[RD_ADDRSTRLEN];
+       char buf2[INET6_ADDRSTRLEN];
 
        if (bgp->vnihash) {
                struct list *vnilist = hash_to_list(bgp->vnihash);
@@ -5459,6 +5616,30 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
                       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)));
@@ -5529,6 +5710,7 @@ void bgp_ethernetvpn_init(void)
        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);