]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_mroute.c
Merge pull request #5494 from opensourcerouting/mlag-module
[mirror_frr.git] / pimd / pim_mroute.c
index a2e6aabcf6a3158bdd4d086a1aa72391d1486a2f..1fe2289a8ef934dacb709216741618bd4f1c8a1a 100644 (file)
@@ -147,7 +147,7 @@ static int pim_mroute_set(struct pim_instance *pim, int enable)
        return 0;
 }
 
-static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = {
+static const char *const igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = {
        "<unknown_upcall?>", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"};
 
 static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
@@ -277,8 +277,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                        pim_upstream_keep_alive_timer_start(
                                up, pim_ifp->pim->keep_alive_time);
                        pim_upstream_inherited_olist(pim_ifp->pim, up);
-                       pim_upstream_switch(pim_ifp->pim, up,
-                                           PIM_UPSTREAM_JOINED);
+                       pim_upstream_update_join_desired(pim_ifp->pim, up);
 
                        if (PIM_DEBUG_MROUTE)
                                zlog_debug("%s: Creating %s upstream on LHR",
@@ -324,6 +323,15 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                                        pim_str_sg_dump(&sg));
                        return 0;
                }
+
+               if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
+                       if (PIM_DEBUG_PIM_REG)
+                               zlog_debug(
+                                       "%s register forward skipped, not FHR",
+                                       up->sg_str);
+                       return 0;
+               }
+
                pim_register_send((uint8_t *)buf + sizeof(struct ip),
                                  ntohs(ip_hdr->ip_len) - sizeof(struct ip),
                                  pim_ifp->primary_address, rpg, 0, up);
@@ -879,6 +887,46 @@ int pim_mroute_del_vif(struct interface *ifp)
        return 0;
 }
 
+/*
+ * Prevent creating MFC entry with OIF=IIF.
+ *
+ * This is a protection against implementation mistakes.
+ *
+ * PIM protocol implicitely ensures loopfree multicast topology.
+ *
+ * IGMP must be protected against adding looped MFC entries created
+ * by both source and receiver attached to the same interface. See
+ * TODO T22.
+ * We shall allow igmp to create upstream when it is DR for the intf.
+ * Assume RP reachable via non DR.
+ */
+bool pim_mroute_allow_iif_in_oil(struct channel_oil *c_oil,
+               int oif_index)
+{
+#ifdef PIM_ENFORCE_LOOPFREE_MFC
+       struct interface *ifp_out;
+       struct pim_interface *pim_ifp;
+
+       if (c_oil->up &&
+               PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(c_oil->up->flags))
+               return true;
+
+       ifp_out = pim_if_find_by_vif_index(c_oil->pim, oif_index);
+       if (!ifp_out)
+               return false;
+       pim_ifp = ifp_out->info;
+       if (!pim_ifp)
+               return false;
+       if ((c_oil->oif_flags[oif_index] & PIM_OIF_FLAG_PROTO_IGMP) &&
+                       PIM_I_am_DR(pim_ifp))
+               return true;
+
+       return false;
+#else
+       return true;
+#endif
+}
+
 static inline void pim_mroute_copy(struct mfcctl *oil,
                struct channel_oil *c_oil)
 {
@@ -889,6 +937,12 @@ static inline void pim_mroute_copy(struct mfcctl *oil,
        oil->mfcc_parent = c_oil->oil.mfcc_parent;
 
        for (i = 0; i < MAXVIFS; ++i) {
+               if ((oil->mfcc_parent == i) &&
+                               !pim_mroute_allow_iif_in_oil(c_oil, i)) {
+                       oil->mfcc_ttls[i] = 0;
+                       continue;
+               }
+
                if (c_oil->oif_flags[i] & PIM_OIF_FLAG_MUTE)
                        oil->mfcc_ttls[i] = 0;
                else