]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_zebra.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / pimd / pim_zebra.c
index 38a29b72afa4b71cdd288213dea97c433c317630..10ea17cf1f80dfe0487c1a09bc99033c1e875570 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <zebra.h>
 
-#include "zebra/rib.h"
-
 #include "if.h"
 #include "log.h"
 #include "prefix.h"
@@ -112,7 +110,7 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
                struct pim_interface *pim_ifp;
 
                if (!ifp->info) {
-                       pim_ifp = pim_if_new(ifp, 0, 0);
+                       pim_ifp = pim_if_new(ifp, false, false, false);
                        ifp->info = pim_ifp;
                }
 
@@ -425,13 +423,91 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
        return 0;
 }
 
+void pim_zebra_update_all_interfaces(struct pim_instance *pim)
+{
+       struct interface *ifp;
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+               struct pim_iface_upstream_switch *us;
+               struct listnode *node;
+
+               if (!pim_ifp)
+                       continue;
+
+               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_zebra_upstream_rpf_changed(struct pim_instance *pim,
+                                   struct pim_upstream *up,
+                                   struct pim_rpf *old)
+{
+       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;
+       }
+
+       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);
+}
+
 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;
 
        for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
                enum pim_rpf_result rpf_result;
@@ -450,80 +526,12 @@ static void scan_upstream_rpf_cache(struct pim_instance *pim)
                if (rpf_result == PIM_RPF_FAILURE)
                        continue;
 
-               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;
-                       }
-
-                       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 */
+               if (rpf_result == PIM_RPF_CHANGED)
+                       pim_zebra_upstream_rpf_changed(pim, up, &old);
 
        } /* 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);
-                       }
-               }
+       pim_zebra_update_all_interfaces(pim);
 }
 
 void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
@@ -738,7 +746,7 @@ static void pim_zebra_connected(struct zclient *zclient)
 void pim_zebra_init(void)
 {
        /* Socket for receiving updates from Zebra daemon */
-       zclient = zclient_new_notify(master, &zclient_options_default);
+       zclient = zclient_new(master, &zclient_options_default);
 
        zclient->zebra_connected = pim_zebra_connected;
        zclient->router_id_update = pim_router_id_update_zebra;
@@ -868,6 +876,7 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
 void igmp_source_forward_start(struct pim_instance *pim,
                               struct igmp_source *source)
 {
+       struct pim_interface *pim_oif;
        struct igmp_group *group;
        struct prefix_sg sg;
        int result;
@@ -893,10 +902,20 @@ void igmp_source_forward_start(struct pim_instance *pim,
        }
 
        group = source->source_group;
+       pim_oif = group->group_igmp_sock->interface->info;
+       if (!pim_oif) {
+               if (PIM_DEBUG_IGMP_TRACE) {
+                       zlog_debug(
+                                  "%s: multicast not enabled on oif=%s ?",
+                                  __PRETTY_FUNCTION__,
+                                  source->source_group->group_igmp_sock
+                                  ->interface->name);
+               }
+               return;
+       }
 
        if (!source->source_channel_oil) {
                struct in_addr vif_source;
-               struct pim_interface *pim_oif;
                struct prefix nht_p, src, grp;
                struct pim_nexthop_cache out_pnc;
                struct pim_nexthop nexthop;
@@ -983,19 +1002,6 @@ void igmp_source_forward_start(struct pim_instance *pim,
                  source and receiver attached to the same interface. See TODO
                  T22.
                */
-               pim_oif =
-                       source->source_group->group_igmp_sock->interface->info;
-               if (!pim_oif) {
-                       if (PIM_DEBUG_IGMP_TRACE) {
-                               zlog_debug(
-                                       "%s: multicast not enabled on oif=%s ?",
-                                       __PRETTY_FUNCTION__,
-                                       source->source_group->group_igmp_sock
-                                               ->interface->name);
-                       }
-                       return;
-               }
-
                if (input_iface_vif_index == pim_oif->mroute_vif_index) {
                        /* ignore request for looped MFC entry */
                        if (PIM_DEBUG_IGMP_TRACE) {
@@ -1036,15 +1042,31 @@ void igmp_source_forward_start(struct pim_instance *pim,
                return;
        }
 
+       if (!(PIM_I_am_DR(pim_oif))) {
+               if (PIM_DEBUG_IGMP_TRACE)
+                       zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
+                                  __PRETTY_FUNCTION__,
+                                  pim_str_sg_dump(&sg),
+                                  group->group_igmp_sock->interface->name);
+
+               pim_channel_del_oif(source->source_channel_oil,
+                                   group->group_igmp_sock->interface,
+                                   PIM_OIF_FLAG_PROTO_IGMP);
+               return;
+       }
        /*
          Feed IGMPv3-gathered local membership information into PIM
          per-interface (S,G) state.
         */
        if (!pim_ifchannel_local_membership_add(
-                   group->group_igmp_sock->interface, &sg)) {
+                                               group->group_igmp_sock->interface, &sg)) {
                if (PIM_DEBUG_MROUTE)
                        zlog_warn("%s: Failure to add local membership for %s",
                                  __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
+
+               pim_channel_del_oif(source->source_channel_oil,
+                                   group->group_igmp_sock->interface,
+                                   PIM_OIF_FLAG_PROTO_IGMP);
                return;
        }