]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_iface.c
Merge pull request #5767 from ton31337/fix/replace_s_addr_0_to_INADDR_ANY
[mirror_frr.git] / pimd / pim_iface.c
index 08be38c138abe570908e2949650f3152652b172b..c615540149621e2ad70d314d81082bb2a70abcdc 100644 (file)
@@ -131,8 +131,10 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
                IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
        pim_ifp->igmp_specific_query_max_response_time_dsec =
                IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
+       pim_ifp->igmp_last_member_query_count =
+               IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
 
-       /* BSM config on interface: TRUE by default */
+       /* BSM config on interface: true by default */
        pim_ifp->bsm_enable = true;
        pim_ifp->ucast_bsm_accept = true;
 
@@ -1291,11 +1293,7 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
                return ferr_ok();
        }
 
-       ij = igmp_join_new(ifp, group_addr, source_addr);
-       if (!ij) {
-               return ferr_cfg_invalid(
-                       "Failure to create new join data structure, see log file for more information");
-       }
+       (void)igmp_join_new(ifp, group_addr, source_addr);
 
        if (PIM_DEBUG_IGMP_EVENTS) {
                char group_str[INET_ADDRSTRLEN];
@@ -1478,11 +1476,18 @@ void pim_if_create_pimreg(struct pim_instance *pim)
                        snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
                                 pim->vrf->data.l.table_id);
 
-               pim->regiface = if_create(pimreg_name, pim->vrf_id);
+               pim->regiface = if_create_name(pimreg_name, pim->vrf_id);
                pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
 
                pim_if_new(pim->regiface, false, false, true,
                        false /*vxlan_term*/);
+               /*
+                * On vrf moves we delete the interface if there
+                * is nothing going on with it.  We cannot have
+                * the pimregiface deleted.
+                */
+               pim->regiface->configured = true;
+
        }
 }
 
@@ -1528,3 +1533,167 @@ int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
 
        return count;
 }
+
+int pim_ifp_create(struct interface *ifp)
+{
+       struct pim_instance *pim;
+
+       pim = pim_get_pim_instance(ifp->vrf_id);
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       ifp->vrf_id, (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (if_is_operative(ifp)) {
+               struct pim_interface *pim_ifp;
+
+               pim_ifp = ifp->info;
+               /*
+                * If we have a pim_ifp already and this is an if_add
+                * that means that we probably have a vrf move event
+                * If that is the case, set the proper vrfness.
+                */
+               if (pim_ifp)
+                       pim_ifp->pim = pim;
+               pim_if_addr_add_all(ifp);
+       }
+
+       /*
+        * If we are a vrf device that is up, open up the pim_socket for
+        * listening
+        * to incoming pim messages irrelevant if the user has configured us
+        * for pim or not.
+        */
+       if (pim_if_is_vrf_device(ifp)) {
+               struct pim_interface *pim_ifp;
+
+               if (!ifp->info) {
+                       pim_ifp = pim_if_new(ifp, false, false, false,
+                                            false /*vxlan_term*/);
+                       ifp->info = pim_ifp;
+               }
+
+               pim_sock_add(ifp);
+       }
+
+       if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
+                    sizeof(PIM_VXLAN_TERM_DEV_NAME)))
+               pim_vxlan_add_term_dev(pim, ifp);
+
+       return 0;
+}
+
+int pim_ifp_up(struct interface *ifp)
+{
+       struct pim_interface *pim_ifp;
+       struct pim_instance *pim;
+       uint32_t table_id;
+
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       ifp->vrf_id, (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       pim = pim_get_pim_instance(ifp->vrf_id);
+
+       pim_ifp = ifp->info;
+       /*
+        * If we have a pim_ifp already and this is an if_add
+        * that means that we probably have a vrf move event
+        * If that is the case, set the proper vrfness.
+        */
+       if (pim_ifp)
+               pim_ifp->pim = pim;
+
+       /*
+         pim_if_addr_add_all() suffices for bringing up both IGMP and
+         PIM
+       */
+       pim_if_addr_add_all(ifp);
+
+       /*
+        * If we have a pimreg device callback and it's for a specific
+        * table set the master appropriately
+        */
+       if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) {
+               struct vrf *vrf;
+               RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+                       if ((table_id == vrf->data.l.table_id)
+                           && (ifp->vrf_id != vrf->vrf_id)) {
+                               struct interface *master = if_lookup_by_name(
+                                       vrf->name, vrf->vrf_id);
+
+                               if (!master) {
+                                       zlog_debug(
+                                               "%s: Unable to find Master interface for %s",
+                                               __PRETTY_FUNCTION__, vrf->name);
+                                       return 0;
+                               }
+                               pim_zebra_interface_set_master(master, ifp);
+                       }
+               }
+       }
+       return 0;
+}
+
+int pim_ifp_down(struct interface *ifp)
+{
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       ifp->vrf_id, (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (!if_is_operative(ifp)) {
+               pim_ifchannel_delete_all(ifp);
+               /*
+                 pim_if_addr_del_all() suffices for shutting down IGMP,
+                 but not for shutting down PIM
+               */
+               pim_if_addr_del_all(ifp);
+
+               /*
+                 pim_sock_delete() closes the socket, stops read and timer
+                 threads,
+                 and kills all neighbors.
+               */
+               if (ifp->info) {
+                       pim_sock_delete(ifp, "link down");
+               }
+       }
+
+       if (ifp->info)
+               pim_if_del_vif(ifp);
+
+       return 0;
+}
+
+int pim_ifp_destroy(struct interface *ifp)
+{
+       struct pim_instance *pim;
+
+       if (PIM_DEBUG_ZEBRA) {
+               zlog_debug(
+                       "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->ifindex,
+                       ifp->vrf_id, (long)ifp->flags, ifp->metric, ifp->mtu,
+                       if_is_operative(ifp));
+       }
+
+       if (!if_is_operative(ifp))
+               pim_if_addr_del_all(ifp);
+
+       pim = pim_get_pim_instance(ifp->vrf_id);
+       if (pim && pim->vxlan.term_if == ifp)
+               pim_vxlan_del_term_dev(pim);
+
+       return 0;
+}