]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Make the rpf scan per vrf.
authorDonald Sharp <sharpd@cumulusnetworks.com>
Sun, 18 Mar 2018 01:13:09 +0000 (21:13 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Sun, 18 Mar 2018 01:13:09 +0000 (21:13 -0400)
We know the vrf that we are in when we need to initiate a
rescan of the rpf cache.  So pass it in and use that information.
This should help the rescan at scale with several vrf's cutting
out a lot of unnecessary work.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
pimd/pim_cmd.c
pimd/pim_instance.h
pimd/pim_neighbor.c
pimd/pim_zebra.c
pimd/pim_zebra.h
pimd/pimd.c
pimd/pimd.h

index 803e7bb01325c586553d62f47e3dcd1c9174f979..a8935bf80d94afbd9d567d29f0f678a45ce9a80c 100644 (file)
@@ -2566,8 +2566,8 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
        }
 }
 
-static void show_rpf_refresh_stats(struct vty *vty, time_t now,
-                                  json_object *json)
+static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
+                                  time_t now, json_object *json)
 {
        char refresh_uptime[10];
 
@@ -2579,7 +2579,7 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now,
                                    qpim_rpf_cache_refresh_delay_msec);
                json_object_int_add(
                        json, "rpfCacheRefreshTimer",
-                       pim_time_timer_remain_msec(qpim_rpf_cache_refresher));
+                       pim_time_timer_remain_msec(pim->rpf_cache_refresher));
                json_object_int_add(json, "rpfCacheRefreshRequests",
                                    qpim_rpf_cache_refresh_requests);
                json_object_int_add(json, "rpfCacheRefreshEvents",
@@ -2600,7 +2600,7 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now,
                        "Nexthop Lookups:            %lld\n"
                        "Nexthop Lookups Avoided:    %lld\n",
                        qpim_rpf_cache_refresh_delay_msec,
-                       pim_time_timer_remain_msec(qpim_rpf_cache_refresher),
+                       pim_time_timer_remain_msec(pim->rpf_cache_refresher),
                        (long long)qpim_rpf_cache_refresh_requests,
                        (long long)qpim_rpf_cache_refresh_events,
                        refresh_uptime, (long long)qpim_nexthop_lookups,
@@ -2642,9 +2642,9 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, u_char uj)
 
        if (uj) {
                json = json_object_new_object();
-               show_rpf_refresh_stats(vty, now, json);
+               show_rpf_refresh_stats(vty, pim, now, json);
        } else {
-               show_rpf_refresh_stats(vty, now, json);
+               show_rpf_refresh_stats(vty, pim, now, json);
                vty_out(vty, "\n");
                vty_out(vty,
                        "Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref\n");
@@ -4337,7 +4337,7 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
 
        vty_out(vty, "\n");
 
-       show_rpf_refresh_stats(vty, now, NULL);
+       show_rpf_refresh_stats(vty, pim, now, NULL);
 
        vty_out(vty, "\n");
 
index 5422e8fe0d5d70ff87de3b2dc56c3f16acb0bdad..e672c39fdc19830ce36471d2adc4af1ebfd79af1 100644 (file)
@@ -94,6 +94,9 @@ struct pim_instance {
 
        unsigned int keep_alive_time;
        unsigned int rp_keep_alive_time;
+
+       /* If we need to rescan all our upstreams */
+       struct thread *rpf_cache_refresher;
 };
 
 void pim_vrf_init(void);
index 134dbd8712d49bfee6365fe281cac8e220cfb3f4..20a942b4fdfd9d571f274d2a016812120be4f288 100644 (file)
@@ -545,7 +545,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
 
        pim_rp_setup(pim_ifp->pim);
 
-       sched_rpf_cache_refresh();
+       sched_rpf_cache_refresh(pim_ifp->pim);
        return neigh;
 }
 
@@ -667,7 +667,7 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
 
        pim_neighbor_free(neigh);
 
-       sched_rpf_cache_refresh();
+       sched_rpf_cache_refresh(pim_ifp->pim);
 }
 
 void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message)
index 81c0cb6efbbffdd8d5bc213e11e18cffdfd944bc..ecb97e8e4413cc4479610cfac0456239af47e781 100644 (file)
@@ -394,133 +394,105 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
        return 0;
 }
 
-static void scan_upstream_rpf_cache()
+static void scan_upstream_rpf_cache(struct pim_instance *pim)
 {
        struct listnode *up_node;
        struct listnode *up_nextnode;
        struct listnode *node;
        struct pim_upstream *up;
        struct interface *ifp;
-       struct vrf *vrf;
-       struct pim_instance *pim;
 
-       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
-               pim = vrf->info;
-               if (!pim)
-                       continue;
+       for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
+               enum pim_rpf_result rpf_result;
+               struct pim_rpf old;
+               struct prefix nht_p;
 
-               for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode,
-                                      up)) {
-                       enum pim_rpf_result rpf_result;
-                       struct pim_rpf old;
-                       struct prefix nht_p;
-
-                       nht_p.family = AF_INET;
-                       nht_p.prefixlen = IPV4_MAX_BITLEN;
-                       nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
-                       pim_resolve_upstream_nh(pim, &nht_p);
+               nht_p.family = AF_INET;
+               nht_p.prefixlen = IPV4_MAX_BITLEN;
+               nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+               pim_resolve_upstream_nh(pim, &nht_p);
 
-                       old.source_nexthop.interface =
-                               up->rpf.source_nexthop.interface;
-                       old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
-                       rpf_result = pim_rpf_update(pim, up, &old, 0);
+               old.source_nexthop.interface = up->rpf.source_nexthop.interface;
+               old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
+               rpf_result = pim_rpf_update(pim, up, &old, 0);
 
-                       if (rpf_result == PIM_RPF_FAILURE)
-                               continue;
+               if (rpf_result == PIM_RPF_FAILURE)
+                       continue;
 
-                       if (rpf_result == PIM_RPF_CHANGED) {
-                               struct pim_neighbor *nbr;
+               if (rpf_result == PIM_RPF_CHANGED) {
+                       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);
+
+                       /*
+                        * 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;
+                       }
 
-                               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);
+                       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__);
 
                                /*
-                                * We have detected a case where we might need
-                                * to rescan
-                                * the inherited o_list so do it.
+                                * 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.
                                 */
-                               if (up->channel_oil->oil_inherited_rescan) {
-                                       pim_upstream_inherited_olist_decide(pim,
-                                                                           up);
-                                       up->channel_oil->oil_inherited_rescan =
-                                               0;
-                               }
+                               pim_jp_agg_switch_interface(&old, &up->rpf, up);
 
-                               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 */
-
-                               /* FIXME can join_desired actually be changed by
-                                  pim_rpf_update()
-                                  returning PIM_RPF_CHANGED ? */
-                               pim_upstream_update_join_desired(pim, up);
-
-                       } /* PIM_RPF_CHANGED */
-
-               } /* for (qpim_upstream_list) */
-       }
+                               pim_upstream_join_timer_restart(up, &old);
+                       } /* up->join_state == PIM_UPSTREAM_JOINED */
 
-       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
-               pim = vrf->info;
-               if (!pim)
-                       continue;
+                       /* FIXME can join_desired actually be changed by
+                          pim_rpf_update()
+                          returning PIM_RPF_CHANGED ? */
+                       pim_upstream_update_join_desired(pim, up);
 
-               FOR_ALL_INTERFACES (pim->vrf, ifp)
-                       if (ifp->info) {
-                               struct pim_interface *pim_ifp = ifp->info;
-                               struct pim_iface_upstream_switch *us;
-
-                               for (ALL_LIST_ELEMENTS_RO(
-                                            pim_ifp->upstream_switch_list,
-                                            node, us)) {
-                                       struct pim_rpf rpf;
-                                       rpf.source_nexthop.interface = ifp;
-                                       rpf.rpf_addr.u.prefix4 = us->address;
-                                       pim_joinprune_send(&rpf, us->us);
-                                       pim_jp_agg_clear_group(us->us);
-                               }
+               } /* PIM_RPF_CHANGED */
+
+       } /* for (qpim_upstream_list) */
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp)
+               if (ifp->info) {
+                       struct pim_interface *pim_ifp = ifp->info;
+                       struct pim_iface_upstream_switch *us;
+
+                       for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list,
+                                                 node, us)) {
+                               struct pim_rpf rpf;
+
+                               rpf.source_nexthop.interface = ifp;
+                               rpf.rpf_addr.u.prefix4 = us->address;
+                               pim_joinprune_send(&rpf, us->us);
+                               pim_jp_agg_clear_group(us->us);
                        }
-       }
+               }
 }
 
 void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
@@ -657,53 +629,41 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
        }
 }
 
-void pim_scan_oil(struct pim_instance *pim_matcher)
+void pim_scan_oil(struct pim_instance *pim)
 {
        struct listnode *node;
        struct listnode *nextnode;
        struct channel_oil *c_oil;
        ifindex_t ifindex;
        int vif_index = 0;
-       struct vrf *vrf;
-       struct pim_instance *pim;
 
        qpim_scan_oil_last = pim_time_monotonic_sec();
        ++qpim_scan_oil_events;
 
-       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
-               pim = vrf->info;
-               if (!pim)
-                       continue;
-
-               if (pim_matcher && pim != pim_matcher)
-                       continue;
-
-               for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode,
-                                      c_oil)) {
-                       if (c_oil->up
-                           && c_oil->up->rpf.source_nexthop.interface) {
-                               ifindex = c_oil->up->rpf.source_nexthop
-                                                 .interface->ifindex;
-                               vif_index = pim_if_find_vifindex_by_ifindex(
-                                       pim, ifindex);
-                               /* Pass Current selected NH vif index to mroute
-                                * download */
-                               if (vif_index)
-                                       pim_scan_individual_oil(c_oil,
-                                                               vif_index);
-                       } else
-                               pim_scan_individual_oil(c_oil, 0);
-               }
+       for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
+               if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
+                       ifindex = c_oil->up->rpf.source_nexthop
+                                         .interface->ifindex;
+                       vif_index =
+                               pim_if_find_vifindex_by_ifindex(pim, ifindex);
+                       /* Pass Current selected NH vif index to mroute
+                        * download */
+                       if (vif_index)
+                               pim_scan_individual_oil(c_oil, vif_index);
+               } else
+                       pim_scan_individual_oil(c_oil, 0);
        }
 }
 
 static int on_rpf_cache_refresh(struct thread *t)
 {
+       struct pim_instance *pim = THREAD_ARG(t);
+
        /* update PIM protocol state */
-       scan_upstream_rpf_cache();
+       scan_upstream_rpf_cache(pim);
 
        /* update kernel multicast forwarding cache (MFC) */
-       pim_scan_oil(NULL);
+       pim_scan_oil(pim);
 
        qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
        ++qpim_rpf_cache_refresh_events;
@@ -713,13 +673,13 @@ static int on_rpf_cache_refresh(struct thread *t)
        return 0;
 }
 
-void sched_rpf_cache_refresh(void)
+void sched_rpf_cache_refresh(struct pim_instance *pim)
 {
        ++qpim_rpf_cache_refresh_requests;
 
        pim_rpf_set_refresh_time();
 
-       if (qpim_rpf_cache_refresher) {
+       if (pim->rpf_cache_refresher) {
                /* Refresh timer is already running */
                return;
        }
@@ -731,9 +691,9 @@ void sched_rpf_cache_refresh(void)
                           qpim_rpf_cache_refresh_delay_msec);
        }
 
-       thread_add_timer_msec(master, on_rpf_cache_refresh, 0,
+       thread_add_timer_msec(master, on_rpf_cache_refresh, pim,
                              qpim_rpf_cache_refresh_delay_msec,
-                             &qpim_rpf_cache_refresher);
+                             &pim->rpf_cache_refresher);
 }
 
 static void pim_zebra_connected(struct zclient *zclient)
index d9b17cb82d00766db1f02f109a53aecda62952b7..dd8aed0d20a2e38f9f12b3cb1cdd6aeffe842843 100644 (file)
@@ -44,6 +44,6 @@ void igmp_source_forward_reevaluate_all(void);
 void pim_forward_start(struct pim_ifchannel *ch);
 void pim_forward_stop(struct pim_ifchannel *ch, bool install_it);
 
-void sched_rpf_cache_refresh(void);
+void sched_rpf_cache_refresh(struct pim_instance *pim);
 struct zclient *pim_zebra_zclient_get(void);
 #endif /* PIM_ZEBRA_H */
index 52e0920f1f9199c37ff8ccd6a2e9565b158837e1..0532ce873a4d5f0ba0274916fe3ff6cfc7a7f0a1 100644 (file)
@@ -52,7 +52,6 @@ int qpim_t_periodic =
        PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */
 struct pim_assert_metric qpim_infinite_assert_metric;
 long qpim_rpf_cache_refresh_delay_msec = 50;
-struct thread *qpim_rpf_cache_refresher = NULL;
 int64_t qpim_rpf_cache_refresh_requests = 0;
 int64_t qpim_rpf_cache_refresh_events = 0;
 int64_t qpim_rpf_cache_refresh_last = 0;
index de7f2593196ce07ec621aa127376c7939412e2d0..89582b991ec4355f300a96bad2faa05f3147a1e8 100644 (file)
@@ -140,7 +140,6 @@ struct in_addr qpim_all_pim_routers_addr;
 int qpim_t_periodic; /* Period between Join/Prune Messages */
 struct pim_assert_metric qpim_infinite_assert_metric;
 long qpim_rpf_cache_refresh_delay_msec;
-struct thread *qpim_rpf_cache_refresher;
 int64_t qpim_rpf_cache_refresh_requests;
 int64_t qpim_rpf_cache_refresh_events;
 int64_t qpim_rpf_cache_refresh_last;