]> 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)
committerDonald Sharp <sharpd@nvidia.com>
Thu, 26 May 2022 14:45:35 +0000 (10:45 -0400)
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>
pimd/pim_rp.c

index fdf4b99c3263236eaeaafa5f7b8dc64bbae082f9..3da0a3530361284f43ad1cec729bee8968d15b66 100644 (file)
@@ -274,10 +274,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;
@@ -423,7 +442,7 @@ int pim_rp_new(struct pim_instance *pim, pim_addr rp_addr, struct prefix group,
        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;
 
@@ -601,13 +620,16 @@ int pim_rp_new(struct pim_instance *pim, pim_addr rp_addr, struct prefix group,
        }
 
        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 (pim_addr_is_any(up->sg.src)) {