]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Allow the LPM match work properly with prefix lists and normal rp's
authorDonald Sharp <sharpd@nvidia.com>
Tue, 24 May 2022 17:33:35 +0000 (13:33 -0400)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Mon, 30 May 2022 12:30:16 +0000 (12:30 +0000)
All rp_info's are being saved in the pim->rp_list and the non prefix-list
rp's are supposed to be saved in table pim->rp_table.  What was happening,
though, is that all the plists were being stored at the 224.0.0.0/4 node
of the tree(irrelevant to the fact that we should not be looking up the
non-prefix list rp's in the table) and since we can have multiple prefix lists
and only one rp_info stored at the 224.0.0.0/4 node of the tree, there can be situations
where the 224.0.0.0/4 node can be overwritten due to the order entered.

As such there exists situations where command enter ordering will cause
what we match to, change in pim_rp_find_match_group.

Fixes:

a) Do not store prefix list based rp_info's in the pim->rp_table
b) In pim_rp_find_match_group, ensure that the node lookup does
not correspond to a prefix list based node.
c) When in the situation there are both:
ip pim rp 4.5.6.7 224.0.0.0/16
ip pim rp 5.6.67.8 prefix-list FOO
ip prefix-list FOO permit 224.0.1.0/24
and we receive a group for 224.0.1.5, we were comparing the
224.0.0.0/16 to the 224.0.0.0/4 of the 5.6.67.8 group, when
FRR should have been comparing to entry that matched in the prefix-list

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
(cherry picked from commit 94dc0c4ed4bbca84ad32cb45bbc492e9cae90d73)

pimd/pim_rp.c

index d356aff9f1a44ea66b75a08e390b8f865921a241..f93a79e735559c763aef8207d1d1b3c1a574e98f 100644 (file)
@@ -276,10 +276,29 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
 
        route_unlock_node(rn);
 
+       /*
+        * rp's with prefix lists have the group as 224.0.0.0/4 which will
+        * match anything.  So if we have a rp_info that should match a prefix
+        * list then if we do match then best should be the answer( even
+        * if it is NULL )
+        */
+       if (!rp_info || (rp_info && rp_info->plist))
+               return best;
+
+       /*
+        * So we have a non plist rp_info found in the lookup and no plists
+        * at all to be choosen, return it!
+        */
        if (!best)
                return rp_info;
 
-       if (rp_info->group.prefixlen < best->group.prefixlen)
+       /*
+        * If we have a matching non prefix list and a matching prefix
+        * list we should return the actual rp_info that has the LPM
+        * If they are equal, use the prefix-list( but let's hope
+        * the end-operator doesn't do this )
+        */
+       if (rp_info->group.prefixlen > bp->prefixlen)
                best = rp_info;
 
        return best;
@@ -427,7 +446,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
        struct rp_info *tmp_rp_info;
        char buffer[BUFSIZ];
        struct prefix nht_p;
-       struct route_node *rn;
+       struct route_node *rn = NULL;
        struct pim_upstream *up;
        bool upstream_updated = false;
 
@@ -619,13 +638,16 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
        }
 
        listnode_add_sort(pim->rp_list, rp_info);
-       rn = route_node_get(pim->rp_table, &rp_info->group);
-       rn->info = rp_info;
+
+       if (!rp_info->plist) {
+               rn = route_node_get(pim->rp_table, &rp_info->group);
+               rn->info = rp_info;
+       }
 
        if (PIM_DEBUG_PIM_TRACE)
                zlog_debug("Allocated: %p for rp_info: %p(%pFX) Lock: %d", rn,
                           rp_info, &rp_info->group,
-                          route_node_get_lock_count(rn));
+                          rn ? route_node_get_lock_count(rn) : 0);
 
        frr_each (rb_pim_upstream, &pim->upstream_head, up) {
                if (up->sg.src.s_addr == INADDR_ANY) {