]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: clear upstream rpf information when RP becomes not reachable
authorSarita Patra <saritap@vmware.com>
Fri, 22 Feb 2019 15:29:24 +0000 (07:29 -0800)
committerSarita Patra <saritap@vmware.com>
Mon, 25 Feb 2019 07:27:08 +0000 (23:27 -0800)
When route to RP gets modified, FRR receives a notification from
zebra, and call the function pim_resolve_upstream_nh() to compute the
nexthop and update upstream->rpf structure.
Issue: In case when RP becomes not reachable, FRR only uninstall
the mroute from the kernal, but not update the upstream->rpf structure.

Fix: When FRR receives a notification from zebra saying RP becomes
not reachable, then update the following fields.
1. update channel_oil incoming interface as MAXVIFS
2. Un-install the mroute from the kernel.
3. Switch upstream state from JOINED to NOTJOINED.
4. Clear the nexthop information of the upstream.

Signed-off-by: Sarita Patra <saritap@vmware.com>
pimd/pim_nht.c
pimd/pim_rpf.c
pimd/pim_rpf.h
pimd/pim_upstream.c
pimd/pim_zebra.c

index 87775665955dd5f5885e7d9a0f9bdd59d2ce149c..37970923c15d3059edf9174f849c34545ede3e7b 100644 (file)
@@ -292,7 +292,7 @@ static int pim_update_upstream_nh_helper(struct hash_backet *backet, void *arg)
        old.source_nexthop.interface = up->rpf.source_nexthop.interface;
        rpf_result = pim_rpf_update(pim, up, &old, 0);
        if (rpf_result == PIM_RPF_FAILURE) {
-               pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+               pim_upstream_rpf_clear(pim, up);
                return HASHWALK_CONTINUE;
        }
 
index d689b276b786a15fd1319646960778169f329438..8adf253e551928fc43cc2cb254b4ba35d899a70f 100644 (file)
@@ -313,6 +313,34 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
        return PIM_RPF_OK;
 }
 
+/*
+ * In the case of RP deletion and RP unreachablity,
+ * uninstall the mroute in the kernel and clear the
+ * rpf information in the pim upstream and pim channel
+ * oil data structure.
+ */
+void pim_upstream_rpf_clear(struct pim_instance *pim,
+                           struct pim_upstream *up)
+{
+       if (up->rpf.source_nexthop.interface) {
+               if (up->channel_oil) {
+                       up->channel_oil->oil.mfcc_parent = MAXVIFS;
+                       up->channel_oil->is_valid = 0;
+                       pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+
+               }
+               pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
+               up->rpf.source_nexthop.interface = NULL;
+               up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr =
+                       PIM_NET_INADDR_ANY;
+               up->rpf.source_nexthop.mrib_metric_preference =
+                       router->infinite_assert_metric.metric_preference;
+               up->rpf.source_nexthop.mrib_route_metric =
+                       router->infinite_assert_metric.route_metric;
+               up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
+       }
+}
+
 /*
   RFC 4601: 4.1.6.  State Summarization Macros
 
index b9fe162f21c66714fca28cea618ff40d195c4ba4..a4793df667f379ce10aba5c21a4052c481d958b6 100644 (file)
@@ -64,7 +64,8 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
 enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
                                   struct pim_upstream *up, struct pim_rpf *old,
                                   uint8_t is_new);
-
+void pim_upstream_rpf_clear(struct pim_instance *pim,
+                           struct pim_upstream *up);
 int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf);
 int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf);
 
index 2a2b944354d3bd0b57dc6604c0fe3d5f9efdc79c..f1fb99832bf658f3009447869ffa5996365df8f5 100644 (file)
@@ -941,7 +941,7 @@ void pim_upstream_update_join_desired(struct pim_instance *pim,
                PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags);
 
        /* switched from false to true */
-       if (is_join_desired && !was_join_desired) {
+       if (is_join_desired) {
                pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
                return;
        }
index 6a5e6e726f6ab9a3e4e894374b69347bb19bd4ed..78cccd5877732e0594fc75aa69f706626d8fbca0 100644 (file)
@@ -472,55 +472,72 @@ void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
                                    struct pim_upstream *up,
                                    struct pim_rpf *old)
 {
-       struct pim_neighbor *nbr;
+       if (old->source_nexthop.interface) {
+               struct pim_neighbor *nbr;
 
-       nbr = pim_neighbor_find(old->source_nexthop.interface,
-                               old->rpf_addr.u.prefix4);
-       if (nbr)
-               pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+               nbr = pim_neighbor_find(old->source_nexthop.interface,
+                                       old->rpf_addr.u.prefix4);
+               if (nbr)
+                       pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
 
-       /*
-        * We have detected a case where we might need
-        * to rescan the inherited o_list so do it.
-        */
-       if (up->channel_oil->oil_inherited_rescan) {
-               pim_upstream_inherited_olist_decide(pim, up);
-               up->channel_oil->oil_inherited_rescan = 0;
-       }
-
-       if (up->join_state == PIM_UPSTREAM_JOINED) {
                /*
-                * If we come up real fast we can be here
-                * where the mroute has not been installed
-                * so install it.
+                * We have detected a case where we might need
+                * to rescan the inherited o_list so do it.
                 */
-               if (!up->channel_oil->installed)
-                       pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
+               if (up->channel_oil->oil_inherited_rescan) {
+                       pim_upstream_inherited_olist_decide(pim, up);
+                       up->channel_oil->oil_inherited_rescan = 0;
+               }
 
+               if (up->join_state == PIM_UPSTREAM_JOINED) {
+                       /*
+                        * If we come up real fast we can be here
+                        * where the mroute has not been installed
+                        * so install it.
+                        */
+                       if (!up->channel_oil->installed)
+                               pim_mroute_add(up->channel_oil,
+                                       __PRETTY_FUNCTION__);
+
+                       /*
+                        * RFC 4601: 4.5.7.  Sending (S,G)
+                        * Join/Prune Messages
+                        *
+                        * Transitions from Joined State
+                        *
+                        * RPF'(S,G) changes not due to an Assert
+                        *
+                        * The upstream (S,G) state machine remains
+                        * in Joined state. Send Join(S,G) to the new
+                        * upstream neighbor, which is the new value
+                        * of RPF'(S,G).  Send Prune(S,G) to the old
+                        * upstream neighbor, which is the old value
+                        * of RPF'(S,G).  Set the Join Timer (JT) to
+                        * expire after t_periodic seconds.
+                        */
+                       pim_jp_agg_switch_interface(old, &up->rpf, up);
+
+                       pim_upstream_join_timer_restart(up, old);
+               } /* up->join_state == PIM_UPSTREAM_JOINED */
+       }
+
+       else {
                /*
-                * RFC 4601: 4.5.7.  Sending (S,G)
-                * Join/Prune Messages
-                *
-                * Transitions from Joined State
-                *
-                * RPF'(S,G) changes not due to an Assert
-                *
-                * The upstream (S,G) state machine remains
-                * in Joined state. Send Join(S,G) to the new
-                * upstream neighbor, which is the new value
-                * of RPF'(S,G).  Send Prune(S,G) to the old
-                * upstream neighbor, which is the old value
-                * of RPF'(S,G).  Set the Join Timer (JT) to
-                * expire after t_periodic seconds.
+                * We have detected a case where we might need
+                * to rescan the inherited o_list so do it.
                 */
-               pim_jp_agg_switch_interface(old, &up->rpf, up);
+               if (up->channel_oil->oil_inherited_rescan) {
+                       pim_upstream_inherited_olist_decide(pim, up);
+                       up->channel_oil->oil_inherited_rescan = 0;
+               }
 
-               pim_upstream_join_timer_restart(up, old);
-       } /* up->join_state == PIM_UPSTREAM_JOINED */
+               if (!up->channel_oil->installed)
+                       pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
+       }
 
-       /* FIXME can join_desired actually be changed by
-          pim_rpf_update()
-          returning PIM_RPF_CHANGED ? */
+       /* FIXME can join_desired actually be changed by pim_rpf_update()
+        * returning PIM_RPF_CHANGED ?
+        */
        pim_upstream_update_join_desired(pim, up);
 }