]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_upstream.c
Merge pull request #5494 from opensourcerouting/mlag-module
[mirror_frr.git] / pimd / pim_upstream.c
index 66dc0a6d9691faaafc1f45f3601c32f76d05d711..a0387cdd4a9c58644e2fff5e59773ae40556bf29 100644 (file)
@@ -190,6 +190,11 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
        if (up->ref_count >= 1)
                return up;
 
+       if (PIM_DEBUG_TRACE)
+               zlog_debug(
+                               "pim_upstream free vrf:%s %s flags 0x%x",
+                               pim->vrf->name, up->sg_str, up->flags);
+
        THREAD_OFF(up->t_ka_timer);
        THREAD_OFF(up->t_rs_timer);
        THREAD_OFF(up->t_msdp_reg_timer);
@@ -333,7 +338,7 @@ static void join_timer_stop(struct pim_upstream *up)
                                        up->rpf.rpf_addr.u.prefix4);
 
        if (nbr)
-               pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+               pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
 
        pim_jp_agg_upstream_verification(up, false);
 }
@@ -355,7 +360,7 @@ void join_timer_start(struct pim_upstream *up)
        }
 
        if (nbr)
-               pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1);
+               pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1, nbr);
        else {
                THREAD_OFF(up->t_join_timer);
                thread_add_timer(router->master, on_join_timer, up,
@@ -696,21 +701,47 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                                join_timer_start(up);
                        }
                }
+               if (old_state != new_state)
+                       pim_upstream_update_use_rpt(up, true /*update_mroute*/);
        } else {
+               bool old_use_rpt;
+               bool new_use_rpt;
+               bool send_xg_jp = false;
 
                forward_off(up);
                if (old_state == PIM_UPSTREAM_JOINED)
                        pim_msdp_up_join_state_changed(pim, up);
 
+               if (old_state != new_state) {
+                       old_use_rpt =
+                               !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+                       pim_upstream_update_use_rpt(up, true /*update_mroute*/);
+                       new_use_rpt =
+                               !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags);
+                       if (new_use_rpt &&
+                                       (new_use_rpt != old_use_rpt) &&
+                                       up->parent)
+                               /* we have decided to switch from the SPT back
+                                * to the RPT which means we need to cancel
+                                * any previously sent SGrpt prunes immediately
+                                */
+                               send_xg_jp = true;
+               }
+
                /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
                   RP.
                   If I am RP for G then send S,G prune to its IIF. */
-               if (pim_upstream_is_sg_rpt(up) && up->parent
-                   && !I_am_RP(pim, up->sg.grp)) {
+               if (pim_upstream_is_sg_rpt(up) && up->parent &&
+                               !I_am_RP(pim, up->sg.grp))
+                       send_xg_jp = true;
+               else
+                       pim_jp_agg_single_upstream_send(&up->rpf, up,
+                                                       0 /* prune */);
+
+               if (send_xg_jp) {
                        if (PIM_DEBUG_PIM_TRACE_DETAIL)
                                zlog_debug(
-                                 "%s: *,G IIF %s S,G IIF %s ",
-                                 __PRETTY_FUNCTION__,
+                                 "re-join RPT; *,G IIF %s S,G IIF %s ",
                                  up->parent->rpf.source_nexthop.interface ?
                                  up->parent->rpf.source_nexthop.interface->name
                                  : "Unknown",
@@ -720,14 +751,9 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                        pim_jp_agg_single_upstream_send(&up->parent->rpf,
                                                        up->parent,
                                                        1 /* (W,G) Join */);
-               } else
-                       pim_jp_agg_single_upstream_send(&up->rpf, up,
-                                                       0 /* prune */);
+               }
                join_timer_stop(up);
        }
-
-       if (old_state != new_state)
-               pim_upstream_update_use_rpt(up, true /*update_mroute*/);
 }
 
 int pim_upstream_compare(void *arg1, void *arg2)
@@ -839,12 +865,16 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                pim_upstream_fill_static_iif(up, incoming);
                pim_ifp = up->rpf.source_nexthop.interface->info;
                assert(pim_ifp);
+               pim_upstream_update_use_rpt(up,
+                               false /*update_mroute*/);
                pim_upstream_mroute_iif_update(up->channel_oil, __func__);
 
                if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags))
                        pim_upstream_keep_alive_timer_start(
                                up, pim->keep_alive_time);
        } else if (up->upstream_addr.s_addr != INADDR_ANY) {
+               pim_upstream_update_use_rpt(up,
+                               false /*update_mroute*/);
                rpf_result = pim_rpf_update(pim, up, NULL, __func__);
                if (rpf_result == PIM_RPF_FAILURE) {
                        if (PIM_DEBUG_PIM_TRACE)
@@ -854,13 +884,9 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                }
 
                if (up->rpf.source_nexthop.interface) {
-                       pim_ifp = up->rpf.source_nexthop.interface->info;
-                       if (pim_ifp)
-                               pim_upstream_mroute_iif_update(up->channel_oil,
-                                               __func__);
+                       pim_upstream_mroute_iif_update(up->channel_oil,
+                                       __func__);
                }
-               pim_upstream_update_use_rpt(up,
-                               false /*update_mroute*/);
        }
 
        listnode_add_sort(pim->upstream_list, up);
@@ -907,6 +933,15 @@ void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
                pim_upstream_update_use_rpt(up, true /*update_mroute*/);
        }
 
+       /* re-eval joinDesired; clearing peer-msdp-sa flag can
+        * cause JD to change
+        */
+       if (!PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags) &&
+                       PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags)) {
+               PIM_UPSTREAM_FLAG_SET_SRC_MSDP(up->flags);
+               pim_upstream_update_join_desired(up->pim, up);
+       }
+
        up->flags |= flags;
        ++up->ref_count;
        if (PIM_DEBUG_PIM_TRACE)
@@ -1047,6 +1082,12 @@ static bool pim_upstream_empty_immediate_olist(struct pim_instance *pim,
        return true;
 }
 
+
+static inline bool pim_upstream_is_msdp_peer_sa(struct pim_upstream *up)
+{
+       return PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags);
+}
+
 /*
  *   bool JoinDesired(*,G) {
  *       if (immediate_olist(*,G) != NULL)
@@ -1079,7 +1120,7 @@ int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
        empty_inh_oil = pim_upstream_empty_inherited_olist(up);
        if (!empty_inh_oil &&
                        (pim_upstream_is_kat_running(up) ||
-                        I_am_RP(pim, up->sg.grp)))
+                        pim_upstream_is_msdp_peer_sa(up)))
                return true;
 
        return false;
@@ -1750,6 +1791,8 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
        struct listnode *up_node;
        struct listnode *up_nextnode;
        struct pim_upstream *up;
+       struct pim_rpf old;
+       enum pim_rpf_result rpf_result;
 
        /*
         * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
@@ -1768,9 +1811,19 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
                                zlog_debug(
                                        "%s: Upstream %s without a path to send join, checking",
                                        __PRETTY_FUNCTION__, up->sg_str);
-                       pim_rpf_update(pim, up, NULL, __func__);
+                       old.source_nexthop.interface =
+                               up->rpf.source_nexthop.interface;
+                       rpf_result = pim_rpf_update(pim, up, &old, __func__);
+                       if (rpf_result == PIM_RPF_CHANGED ||
+                                       (rpf_result == PIM_RPF_FAILURE &&
+                                        old.source_nexthop.interface))
+                               pim_zebra_upstream_rpf_changed(pim, up, &old);
+                       /* update kernel multicast forwarding cache (MFC) */
+                       pim_upstream_mroute_iif_update(up->channel_oil,
+                                       __func__);
                }
        }
+       pim_zebra_update_all_interfaces(pim);
 }
 
 unsigned int pim_upstream_hash_key(const void *arg)
@@ -1846,8 +1899,7 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
        if (pim_ifp->mroute_vif_index != c_oil->oil.mfcc_parent)
                return false;
 
-       if (up->rpf.source_nexthop.interface &&
-               pim_if_connected_to_source(up->rpf.source_nexthop.interface,
+       if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
                                       up->sg.src)) {
                return true;
        }