]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_iface.c
Merge pull request #10400 from opensourcerouting/pim6-compilefix
[mirror_frr.git] / pimd / pim_iface.c
index 8c03475ae54b9958c73f3403affcb0b30fa54448..d6016d060b9d9ccf693237591107406949029272 100644 (file)
 #include "pim_igmp_join.h"
 #include "pim_vxlan.h"
 
+#if PIM_IPV == 4
 static void pim_if_igmp_join_del_all(struct interface *ifp);
 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
                          struct in_addr group_addr,
                          struct in_addr source_addr);
+#endif
 
 void pim_if_init(struct pim_instance *pim)
 {
@@ -83,6 +85,7 @@ static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
        XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
 }
 
+__attribute__((unused))
 static int pim_sec_addr_comp(const void *p1, const void *p2)
 {
        const struct pim_secondary_addr *sec1 = p1;
@@ -124,16 +127,16 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
        pim_ifp->pim = ifp->vrf->info;
        pim_ifp->mroute_vif_index = -1;
 
+#if PIM_IPV == 4
        pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
-       pim_ifp->igmp_default_robustness_variable =
+       pim_ifp->gm_default_robustness_variable =
                IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
-       pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
-       pim_ifp->igmp_query_max_response_time_dsec =
+       pim_ifp->gm_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
+       pim_ifp->gm_query_max_response_time_dsec =
                IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
-       pim_ifp->igmp_specific_query_max_response_time_dsec =
+       pim_ifp->gm_specific_query_max_response_time_dsec =
                IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
-       pim_ifp->igmp_last_member_query_count =
-               IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+       pim_ifp->gm_last_member_query_count = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
 
        /* BSM config on interface: true by default */
        pim_ifp->bsm_enable = true;
@@ -145,8 +148,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
          The number of seconds represented by the [Query Response Interval]
          must be less than the [Query Interval].
         */
-       assert(pim_ifp->igmp_query_max_response_time_dsec
-              < pim_ifp->igmp_default_query_interval);
+       assert(pim_ifp->gm_query_max_response_time_dsec <
+              pim_ifp->gm_default_query_interval);
 
        if (pim)
                PIM_IF_DO_PIM(pim_ifp->options);
@@ -155,12 +158,12 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
 
        PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
 
-       pim_ifp->igmp_join_list = NULL;
+       pim_ifp->gm_join_list = NULL;
        pim_ifp->pim_neighbor_list = NULL;
        pim_ifp->upstream_switch_list = NULL;
        pim_ifp->pim_generation_id = 0;
 
-       /* list of struct igmp_sock */
+       /* list of struct gm_sock */
        pim_igmp_if_init(pim_ifp, ifp);
 
        /* list of struct pim_neighbor */
@@ -186,6 +189,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
        pim_sock_reset(ifp);
 
        pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
+#endif
        pim_ifp->pim->mcast_if_count++;
 
        return pim_ifp;
@@ -194,13 +198,16 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
 void pim_if_delete(struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
-       struct pim_ifchannel *ch;
 
        assert(ifp);
        pim_ifp = ifp->info;
        assert(pim_ifp);
 
-       if (pim_ifp->igmp_join_list) {
+       pim_ifp->pim->mcast_if_count--;
+#if PIM_IPV == 4
+       struct pim_ifchannel *ch;
+
+       if (pim_ifp->gm_join_list) {
                pim_if_igmp_join_del_all(ifp);
        }
 
@@ -210,7 +217,6 @@ void pim_if_delete(struct interface *ifp)
        pim_neighbor_delete_all(ifp, "Interface removed from configuration");
 
        pim_if_del_vif(ifp);
-       pim_ifp->pim->mcast_if_count--;
 
        pim_igmp_if_fini(pim_ifp);
 
@@ -219,14 +225,8 @@ void pim_if_delete(struct interface *ifp)
        list_delete(&pim_ifp->sec_addr_list);
 
        XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
-
-       while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
-               ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
-
-               pim_ifchannel_delete(ch);
-       }
-
        XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
+#endif
 
        ifp->info = NULL;
 }
@@ -300,27 +300,20 @@ static int detect_primary_address_change(struct interface *ifp,
                                         const char *caller)
 {
        struct pim_interface *pim_ifp = ifp->info;
-       struct in_addr new_prim_addr;
+       pim_addr new_prim_addr;
        int changed;
 
        if (force_prim_as_any)
-               new_prim_addr.s_addr = INADDR_ANY;
+               new_prim_addr = PIMADDR_ANY;
        else
                new_prim_addr = pim_find_primary_addr(ifp);
 
-       changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
+       changed = pim_addr_cmp(new_prim_addr, pim_ifp->primary_address);
 
-       if (PIM_DEBUG_ZEBRA) {
-               char new_prim_str[INET_ADDRSTRLEN];
-               char old_prim_str[INET_ADDRSTRLEN];
-               pim_inet4_dump("<new?>", new_prim_addr, new_prim_str,
-                              sizeof(new_prim_str));
-               pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str,
-                              sizeof(old_prim_str));
-               zlog_debug("%s: old=%s new=%s on interface %s: %s", __func__,
-                          old_prim_str, new_prim_str, ifp->name,
-                          changed ? "changed" : "unchanged");
-       }
+       if (PIM_DEBUG_ZEBRA)
+               zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
+                          __func__, &pim_ifp->primary_address, &new_prim_addr,
+                          ifp->name, changed ? "changed" : "unchanged");
 
        if (changed) {
                /* Before updating pim_ifp send Hello time with 0 hold time */
@@ -402,19 +395,18 @@ static int pim_sec_addr_update(struct interface *ifp)
        }
 
        for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
-               struct prefix *p = ifc->address;
+               pim_addr addr = pim_addr_from_prefix(ifc->address);
 
-               if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
+               if (pim_addr_is_any(addr))
                        continue;
-               }
 
-               if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
+               if (!pim_addr_cmp(addr, pim_ifp->primary_address)) {
                        /* don't add the primary address into the secondary
                         * address list */
                        continue;
                }
 
-               if (pim_sec_addr_add(pim_ifp, p)) {
+               if (pim_sec_addr_add(pim_ifp, ifc->address)) {
                        changed = 1;
                }
        }
@@ -481,7 +473,7 @@ static void detect_address_change(struct interface *ifp, int force_prim_as_any,
         * address change on all of them when the lo address changes */
 }
 
-int pim_update_source_set(struct interface *ifp, struct in_addr source)
+int pim_update_source_set(struct interface *ifp, pim_addr source)
 {
        struct pim_interface *pim_ifp = ifp->info;
 
@@ -489,7 +481,7 @@ int pim_update_source_set(struct interface *ifp, struct in_addr source)
                return PIM_IFACE_NOT_FOUND;
        }
 
-       if (pim_ifp->update_source.s_addr == source.s_addr) {
+       if (!pim_addr_cmp(pim_ifp->update_source, source)) {
                return PIM_UPDATE_SOURCE_DUP;
        }
 
@@ -503,7 +495,6 @@ void pim_if_addr_add(struct connected *ifc)
 {
        struct pim_interface *pim_ifp;
        struct interface *ifp;
-       struct in_addr ifaddr;
        bool vxlan_term;
 
        assert(ifc);
@@ -524,38 +515,39 @@ void pim_if_addr_add(struct connected *ifc)
                                   ? "secondary"
                                   : "primary");
 
-       ifaddr = ifc->address->u.prefix4;
-
        detect_address_change(ifp, 0, __func__);
 
        // if (ifc->address->family != AF_INET)
        //  return;
 
+#if PIM_IPV == 4
+       struct in_addr ifaddr = ifc->address->u.prefix4;
+
        if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
-               struct igmp_sock *igmp;
+               struct gm_sock *igmp;
 
                /* lookup IGMP socket */
-               igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
+               igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
                                                   ifaddr);
                if (!igmp) {
                        /* if addr new, add IGMP socket */
                        if (ifc->address->family == AF_INET)
-                               pim_igmp_sock_add(pim_ifp->igmp_socket_list,
+                               pim_igmp_sock_add(pim_ifp->gm_socket_list,
                                                  ifaddr, ifp, false);
                } else if (igmp->mtrace_only) {
                        igmp_sock_delete(igmp);
-                       pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
-                                         ifp, false);
+                       pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
+                                         false);
                }
 
                /* Replay Static IGMP groups */
-               if (pim_ifp->igmp_join_list) {
+               if (pim_ifp->gm_join_list) {
                        struct listnode *node;
                        struct listnode *nextnode;
-                       struct igmp_join *ij;
+                       struct gm_join *ij;
                        int join_fd;
 
-                       for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
+                       for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node,
                                               nextnode, ij)) {
                                /* Close socket and reopen with Source and Group
                                 */
@@ -583,23 +575,24 @@ void pim_if_addr_add(struct connected *ifc)
                }
        } /* igmp */
        else {
-               struct igmp_sock *igmp;
+               struct gm_sock *igmp;
 
                /* lookup IGMP socket */
-               igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
+               igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
                                                   ifaddr);
                if (ifc->address->family == AF_INET) {
                        if (igmp)
                                igmp_sock_delete(igmp);
                        /* if addr new, add IGMP socket */
-                       pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
-                                         ifp, true);
+                       pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
+                                         true);
                }
        } /* igmp mtrace only */
+#endif
 
        if (PIM_IF_TEST_PIM(pim_ifp->options)) {
 
-               if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
+               if (!pim_addr_is_any(pim_ifp->primary_address)) {
 
                        /* Interface has a valid socket ? */
                        if (pim_ifp->pim_sock_fd < 0) {
@@ -647,8 +640,9 @@ void pim_if_addr_add(struct connected *ifc)
 
 static void pim_if_addr_del_igmp(struct connected *ifc)
 {
+#if PIM_IPV == 4
        struct pim_interface *pim_ifp = ifc->ifp->info;
-       struct igmp_sock *igmp;
+       struct gm_sock *igmp;
        struct in_addr ifaddr;
 
        if (ifc->address->family != AF_INET) {
@@ -664,11 +658,12 @@ static void pim_if_addr_del_igmp(struct connected *ifc)
        ifaddr = ifc->address->u.prefix4;
 
        /* lookup IGMP socket */
-       igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
+       igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr);
        if (igmp) {
                /* if addr found, del IGMP socket */
                igmp_sock_delete(igmp);
        }
+#endif
 }
 
 static void pim_if_addr_del_pim(struct connected *ifc)
@@ -685,7 +680,7 @@ static void pim_if_addr_del_pim(struct connected *ifc)
                return;
        }
 
-       if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
+       if (!pim_addr_is_any(pim_ifp->primary_address)) {
                /* Interface keeps a valid primary address */
                return;
        }
@@ -753,7 +748,7 @@ void pim_if_addr_add_all(struct interface *ifp)
                if (PIM_IF_TEST_PIM(pim_ifp->options)) {
 
                        /* Interface has a valid primary address ? */
-                       if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
+                       if (!pim_addr_is_any(pim_ifp->primary_address)) {
 
                                /* Interface has a valid socket ? */
                                if (pim_ifp->pim_sock_fd < 0) {
@@ -828,42 +823,48 @@ void pim_if_addr_del_all_igmp(struct interface *ifp)
        }
 }
 
-struct in_addr pim_find_primary_addr(struct interface *ifp)
+pim_addr pim_find_primary_addr(struct interface *ifp)
 {
        struct connected *ifc;
        struct listnode *node;
-       struct in_addr addr = {0};
        int v4_addrs = 0;
        int v6_addrs = 0;
        struct pim_interface *pim_ifp = ifp->info;
 
-       if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
+       if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source)) {
                return pim_ifp->update_source;
        }
 
        for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
-               struct prefix *p = ifc->address;
+               pim_addr addr;
 
-               if (p->family != AF_INET) {
+               switch (ifc->address->family) {
+               case AF_INET:
+                       v4_addrs++;
+                       break;
+               case AF_INET6:
                        v6_addrs++;
+                       break;
+               default:
                        continue;
                }
 
-               if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
-                       zlog_warn(
-                               "%s: null IPv4 address connected to interface %s",
-                               __func__, ifp->name);
+               if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
                        continue;
-               }
 
-               v4_addrs++;
-
-               if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+               if (ifc->address->family != PIM_AF)
                        continue;
 
-               return p->u.prefix4;
+               addr = pim_addr_from_prefix(ifc->address);
+
+#if PIM_IPV == 6
+               if (!IN6_IS_ADDR_LINKLOCAL(&addr))
+                       continue;
+#endif
+               return addr;
        }
 
+#if PIM_IPV == 4
        /*
         * If we have no v4_addrs and v6 is configured
         * We probably are using unnumbered
@@ -883,10 +884,8 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
                if (lo_ifp && (lo_ifp != ifp))
                        return pim_find_primary_addr(lo_ifp);
        }
-
-       addr.s_addr = PIM_NET_INADDR_ANY;
-
-       return addr;
+#endif
+       return PIMADDR_ANY;
 }
 
 static int pim_iface_next_vif_index(struct interface *ifp)
@@ -917,7 +916,7 @@ static int pim_iface_next_vif_index(struct interface *ifp)
 int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
 {
        struct pim_interface *pim_ifp = ifp->info;
-       struct in_addr ifaddr;
+       pim_addr ifaddr;
        unsigned char flags = 0;
 
        assert(pim_ifp);
@@ -936,7 +935,7 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
        }
 
        ifaddr = pim_ifp->primary_address;
-       if (!ispimreg && !is_vxlan_term && PIM_INADDR_IS_ANY(ifaddr)) {
+       if (!ispimreg && !is_vxlan_term && pim_addr_is_any(ifaddr)) {
                zlog_warn(
                        "%s: could not get address for interface %s ifindex=%d",
                        __func__, ifp->name, ifp->ifindex);
@@ -1095,8 +1094,7 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
   router (Section 4.3.4).  The primary IP address of a neighbor is the
   address that it uses as the source of its PIM Hello messages.
 */
-struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
-                                         struct in_addr addr)
+struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, pim_addr addr)
 {
        struct listnode *neighnode;
        struct pim_neighbor *neigh;
@@ -1112,15 +1110,13 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
                return 0;
        }
 
-       p.family = AF_INET;
-       p.u.prefix4 = addr;
-       p.prefixlen = IPV4_MAX_BITLEN;
+       pim_addr_to_prefix(&p, addr);
 
        for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
                                  neigh)) {
 
                /* primary address ? */
-               if (neigh->source_addr.s_addr == addr.s_addr)
+               if (!pim_addr_cmp(neigh->source_addr, addr))
                        return neigh;
 
                /* secondary address ? */
@@ -1128,13 +1124,10 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
                        return neigh;
        }
 
-       if (PIM_DEBUG_PIM_TRACE) {
-               char addr_str[INET_ADDRSTRLEN];
-               pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+       if (PIM_DEBUG_PIM_TRACE)
                zlog_debug(
-                       "%s: neighbor not found for address %s on interface %s",
-                       __func__, addr_str, ifp->name);
-       }
+                       "%s: neighbor not found for address %pPA on interface %s",
+                       __func__, &addr, ifp->name);
 
        return NULL;
 }
@@ -1159,17 +1152,18 @@ long pim_if_t_suppressed_msec(struct interface *ifp)
        return t_suppressed_msec;
 }
 
-static void igmp_join_free(struct igmp_join *ij)
+#if PIM_IPV == 4
+static void igmp_join_free(struct gm_join *ij)
 {
        XFREE(MTYPE_PIM_IGMP_JOIN, ij);
 }
 
-static struct igmp_join *igmp_join_find(struct list *join_list,
-                                       struct in_addr group_addr,
-                                       struct in_addr source_addr)
+static struct gm_join *igmp_join_find(struct list *join_list,
+                                     struct in_addr group_addr,
+                                     struct in_addr source_addr)
 {
        struct listnode *node;
-       struct igmp_join *ij;
+       struct gm_join *ij;
 
        assert(join_list);
 
@@ -1211,12 +1205,12 @@ static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
        return join_fd;
 }
 
-static struct igmp_join *igmp_join_new(struct interface *ifp,
-                                      struct in_addr group_addr,
-                                      struct in_addr source_addr)
+static struct gm_join *igmp_join_new(struct interface *ifp,
+                                    struct in_addr group_addr,
+                                    struct in_addr source_addr)
 {
        struct pim_interface *pim_ifp;
-       struct igmp_join *ij;
+       struct gm_join *ij;
        int join_fd;
 
        pim_ifp = ifp->info;
@@ -1245,7 +1239,7 @@ static struct igmp_join *igmp_join_new(struct interface *ifp,
        ij->source_addr = source_addr;
        ij->sock_creation = pim_time_monotonic_sec();
 
-       listnode_add(pim_ifp->igmp_join_list, ij);
+       listnode_add(pim_ifp->gm_join_list, ij);
 
        return ij;
 }
@@ -1254,7 +1248,7 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
                            struct in_addr source_addr)
 {
        struct pim_interface *pim_ifp;
-       struct igmp_join *ij;
+       struct gm_join *ij;
 
        pim_ifp = ifp->info;
        if (!pim_ifp) {
@@ -1262,12 +1256,12 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
                                        ifp->name);
        }
 
-       if (!pim_ifp->igmp_join_list) {
-               pim_ifp->igmp_join_list = list_new();
-               pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
+       if (!pim_ifp->gm_join_list) {
+               pim_ifp->gm_join_list = list_new();
+               pim_ifp->gm_join_list->del = (void (*)(void *))igmp_join_free;
        }
 
-       ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
+       ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
 
        /* This interface has already been configured to join this IGMP group
         */
@@ -1297,7 +1291,7 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
                         struct in_addr source_addr)
 {
        struct pim_interface *pim_ifp;
-       struct igmp_join *ij;
+       struct gm_join *ij;
 
        pim_ifp = ifp->info;
        if (!pim_ifp) {
@@ -1306,13 +1300,13 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
                return -1;
        }
 
-       if (!pim_ifp->igmp_join_list) {
+       if (!pim_ifp->gm_join_list) {
                zlog_warn("%s: no IGMP join on interface %s", __func__,
                          ifp->name);
                return -2;
        }
 
-       ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
+       ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
        if (!ij) {
                char group_str[INET_ADDRSTRLEN];
                char source_str[INET_ADDRSTRLEN];
@@ -1339,22 +1333,23 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
                        errno, safe_strerror(errno));
                /* warning only */
        }
-       listnode_delete(pim_ifp->igmp_join_list, ij);
+       listnode_delete(pim_ifp->gm_join_list, ij);
        igmp_join_free(ij);
-       if (listcount(pim_ifp->igmp_join_list) < 1) {
-               list_delete(&pim_ifp->igmp_join_list);
-               pim_ifp->igmp_join_list = 0;
+       if (listcount(pim_ifp->gm_join_list) < 1) {
+               list_delete(&pim_ifp->gm_join_list);
+               pim_ifp->gm_join_list = 0;
        }
 
        return 0;
 }
 
+__attribute__((unused))
 static void pim_if_igmp_join_del_all(struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
        struct listnode *node;
        struct listnode *nextnode;
-       struct igmp_join *ij;
+       struct gm_join *ij;
 
        pim_ifp = ifp->info;
        if (!pim_ifp) {
@@ -1363,12 +1358,25 @@ static void pim_if_igmp_join_del_all(struct interface *ifp)
                return;
        }
 
-       if (!pim_ifp->igmp_join_list)
+       if (!pim_ifp->gm_join_list)
                return;
 
-       for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
+       for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij))
                pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
 }
+#else /* PIM_IPV != 4 */
+ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
+                           struct in_addr source_addr)
+{
+       return ferr_ok();
+}
+
+int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
+                        struct in_addr source_addr)
+{
+       return 0;
+}
+#endif /* PIM_IPV != 4 */
 
 /*
   RFC 4601
@@ -1384,8 +1392,7 @@ static void pim_if_igmp_join_del_all(struct interface *ifp)
   gone down (and may have come back up), and so we must assume it no
   longer knows it was the winner.
  */
-void pim_if_assert_on_neighbor_down(struct interface *ifp,
-                                   struct in_addr neigh_addr)
+void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr)
 {
        struct pim_interface *pim_ifp;
        struct pim_ifchannel *ch;
@@ -1398,7 +1405,7 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
                if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
                        continue;
                /* Dead neighbor was winner ? */
-               if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
+               if (pim_addr_cmp(ch->ifassert_winner, neigh_addr))
                        continue;
 
                assert_action_a5(ch);
@@ -1474,7 +1481,7 @@ void pim_if_create_pimreg(struct pim_instance *pim)
        }
 }
 
-struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
+struct prefix *pim_if_connected_to_source(struct interface *ifp, pim_addr src)
 {
        struct listnode *cnode;
        struct connected *c;
@@ -1483,12 +1490,10 @@ struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr
        if (!ifp)
                return NULL;
 
-       p.family = AF_INET;
-       p.u.prefix4 = src;
-       p.prefixlen = IPV4_MAX_BITLEN;
+       pim_addr_to_prefix(&p, src);
 
        for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
-               if (c->address->family != AF_INET)
+               if (c->address->family != PIM_AF)
                        continue;
                if (prefix_match(c->address, &p))
                        return c->address;
@@ -1522,7 +1527,7 @@ int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
        return count;
 }
 
-int pim_ifp_create(struct interface *ifp)
+static int pim_ifp_create(struct interface *ifp)
 {
        struct pim_instance *pim;
 
@@ -1546,6 +1551,7 @@ int pim_ifp_create(struct interface *ifp)
                 */
                if (pim_ifp)
                        pim_ifp->pim = pim;
+#if PIM_IPV == 4
                pim_if_addr_add_all(ifp);
 
                /*
@@ -1557,8 +1563,10 @@ int pim_ifp_create(struct interface *ifp)
                 * this is a no-op if it's already been done.
                 */
                pim_if_create_pimreg(pim);
+#endif
        }
 
+#if PIM_IPV == 4
        /*
         * If we are a vrf device that is up, open up the pim_socket for
         * listening
@@ -1586,15 +1594,15 @@ int pim_ifp_create(struct interface *ifp)
                                "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
                                __func__, ifp->name, MAXVIFS);
        }
+#endif
 
        return 0;
 }
 
-int pim_ifp_up(struct interface *ifp)
+static 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(
@@ -1615,6 +1623,9 @@ int pim_ifp_up(struct interface *ifp)
        if (pim_ifp)
                pim_ifp->pim = pim;
 
+#if PIM_IPV == 4
+       uint32_t table_id;
+
        /*
          pim_if_addr_add_all() suffices for bringing up both IGMP and
          PIM
@@ -1643,10 +1654,11 @@ int pim_ifp_up(struct interface *ifp)
                        }
                }
        }
+#endif
        return 0;
 }
 
-int pim_ifp_down(struct interface *ifp)
+static int pim_ifp_down(struct interface *ifp)
 {
        if (PIM_DEBUG_ZEBRA) {
                zlog_debug(
@@ -1656,6 +1668,7 @@ int pim_ifp_down(struct interface *ifp)
                        ifp->mtu, if_is_operative(ifp));
        }
 
+#if PIM_IPV == 4
        if (!if_is_operative(ifp)) {
                pim_ifchannel_delete_all(ifp);
                /*
@@ -1678,14 +1691,13 @@ int pim_ifp_down(struct interface *ifp)
                pim_if_del_vif(ifp);
                pim_ifstat_reset(ifp);
        }
+#endif
 
        return 0;
 }
 
-int pim_ifp_destroy(struct interface *ifp)
+static int pim_ifp_destroy(struct interface *ifp)
 {
-       struct pim_instance *pim;
-
        if (PIM_DEBUG_ZEBRA) {
                zlog_debug(
                        "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
@@ -1694,12 +1706,38 @@ int pim_ifp_destroy(struct interface *ifp)
                        ifp->mtu, if_is_operative(ifp));
        }
 
+#if PIM_IPV == 4
+       struct pim_instance *pim;
+
        if (!if_is_operative(ifp))
                pim_if_addr_del_all(ifp);
 
        pim = ifp->vrf->info;
        if (pim && pim->vxlan.term_if == ifp)
                pim_vxlan_del_term_dev(pim);
+#endif
 
        return 0;
 }
+
+static int pim_if_new_hook(struct interface *ifp)
+{
+       return 0;
+}
+
+static int pim_if_delete_hook(struct interface *ifp)
+{
+       if (ifp->info)
+               pim_if_delete(ifp);
+
+       return 0;
+}
+
+void pim_iface_init(void)
+{
+       hook_register_prio(if_add, 0, pim_if_new_hook);
+       hook_register_prio(if_del, 0, pim_if_delete_hook);
+
+       if_zapi_callbacks(pim_ifp_create, pim_ifp_up, pim_ifp_down,
+                         pim_ifp_destroy);
+}