]> 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 cfaa04a8c971d01df863feac01c11d0ad105f90b..7bfeee9669a00e37fe1dd6dd228c9f1c9eca3c61 100644 (file)
@@ -225,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--;
 
@@ -1336,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,
@@ -2336,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
@@ -2353,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);
        }
 
@@ -6478,7 +6509,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
                                ? true
                                : false;
        bool nexthop_othervrf = false;
-       vrf_id_t nexthop_vrfid;
+       vrf_id_t nexthop_vrfid = VRF_DEFAULT;
        const char *nexthop_vrfname = "Default";
 
        if (json_paths)
@@ -7383,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;
@@ -8010,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);