]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
Merge pull request #2240 from donaldsharp/ubuntu_bull
[mirror_frr.git] / bgpd / bgp_route.c
index 06670d10dda6114a134630e66b56361262f2a084..7bfeee9669a00e37fe1dd6dd228c9f1c9eca3c61 100644 (file)
@@ -100,6 +100,8 @@ static const struct message bgp_pmsi_tnltype_str[] = {
        {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)
@@ -223,6 +225,11 @@ struct bgp_info *bgp_info_lock(struct bgp_info *binfo)
 
 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--;
 
@@ -1334,6 +1341,8 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
        }
        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,
@@ -2334,10 +2343,18 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                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
@@ -2351,12 +2368,28 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
        /* 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);
        }
 
@@ -4624,7 +4657,7 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
                if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
                        struct bgp_encap_type_vxlan bet;
                        memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
-                       bet.vnid = p->u.prefix_evpn.eth_tag;
+                       bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
                        bgp_encap_type_vxlan_to_tlv(&bet, &attr);
                }
                if (bgp_static->router_mac) {
@@ -5099,10 +5132,10 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                                return CMD_WARNING_CONFIG_FAILED;
                        }
                        if ((gw_ip.family == AF_INET
-                            && IS_EVPN_PREFIX_IPADDR_V6(
+                            && is_evpn_prefix_ipaddr_v6(
                                        (struct prefix_evpn *)&p))
                            || (gw_ip.family == AF_INET6
-                               && IS_EVPN_PREFIX_IPADDR_V4(
+                               && is_evpn_prefix_ipaddr_v4(
                                           (struct prefix_evpn *)&p))) {
                                vty_out(vty,
                                        "%% GatewayIp family differs with IP prefix\n");
@@ -6471,6 +6504,13 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
        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();
@@ -6499,6 +6539,39 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                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.
@@ -6541,7 +6614,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                        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();
@@ -6553,7 +6626,8 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                        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) {
@@ -6587,11 +6661,17 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                        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);
                }
        }
 
@@ -6658,11 +6738,12 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                                                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)
@@ -6672,10 +6753,11 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                                }
                        } 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)
@@ -6733,6 +6815,21 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
        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();
@@ -7063,10 +7160,10 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
                vty_out(vty, "%s", str);
                XFREE(MTYPE_TMP, str);
 
-               if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) {
+               if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
                        vty_out(vty, "/%s",
                                inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
-               } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) {
+               } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
                        vty_out(vty, "/%s",
                                inet_ntop(AF_INET6,
                                          &(attr->evpn_overlay.gw_ip.ipv6), buf,
@@ -7317,7 +7414,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
        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;
@@ -7333,6 +7429,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
        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();
@@ -7636,6 +7735,49 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                        }
                }
 
+               /*
+                * 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");
 
@@ -7898,13 +8040,12 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                /* 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);
@@ -8333,10 +8474,16 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
 
                        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)
@@ -10146,9 +10293,15 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                                               "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");
@@ -10179,11 +10332,20 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                                                        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);
                                        }
@@ -10237,12 +10399,24 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                                                } 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);
                                                }
@@ -11253,14 +11427,15 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                        prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
                        if (p->u.prefix_evpn.route_type == 5) {
                                char local_buf[PREFIX_STRLEN];
-                               uint8_t family = IS_EVPN_PREFIX_IPADDR_V4((
+                               uint8_t family = is_evpn_prefix_ipaddr_v4((
                                                         struct prefix_evpn *)p)
                                                         ? AF_INET
                                                         : AF_INET6;
-                               inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
+                               inet_ntop(family,
+                                         &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
                                          local_buf, PREFIX_STRLEN);
                                sprintf(buf, "%s/%u", local_buf,
-                                       p->u.prefix_evpn.ip_prefix_length);
+                                       p->u.prefix_evpn.prefix_addr.ip_prefix_length);
                        } else {
                                prefix2str(p, buf, sizeof(buf));
                        }
@@ -11272,7 +11447,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                                          sizeof(buf2));
                        vty_out(vty,
                                "  network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
-                               buf, rdbuf, p->u.prefix_evpn.eth_tag,
+                               buf, rdbuf,
+                               p->u.prefix_evpn.prefix_addr.eth_tag,
                                decode_label(&bgp_static->label), esi, buf2,
                                macrouter);