diff options
Diffstat (limited to 'pimd/pim_iface.c')
| -rw-r--r-- | pimd/pim_iface.c | 405 |
1 files changed, 261 insertions, 144 deletions
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index e007bdcc10..8e0e418a99 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -50,10 +50,12 @@ #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); + struct in_addr group_addr, struct in_addr source_addr, + struct pim_interface *pim_ifp); +#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; @@ -125,15 +128,14 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim, pim_ifp->mroute_vif_index = -1; 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,22 +147,24 @@ 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); +#if PIM_IPV == 4 if (igmp) PIM_IF_DO_IGMP(pim_ifp->options); PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); +#endif - 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 */ @@ -183,7 +187,9 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim, ifp->info = pim_ifp; +#if PIM_IPV == 4 pim_sock_reset(ifp); +#endif pim_if_add_vif(ifp, ispimreg, is_vxlan_term); pim_ifp->pim->mcast_if_count++; @@ -194,23 +200,26 @@ 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 + if (pim_ifp->gm_join_list) { pim_if_igmp_join_del_all(ifp); } +#endif pim_ifchannel_delete_all(ifp); +#if PIM_IPV == 4 igmp_sock_delete_all(ifp); +#endif 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,13 +228,6 @@ 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); ifp->info = NULL; @@ -289,7 +291,7 @@ static void pim_addr_change(struct interface *ifp) HoldTime should be sent immediately. -- FIXME See TODO T31 */ - pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ + PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp->flags); if (pim_ifp->pim_sock_fd < 0) return; pim_hello_restart_now(ifp); /* send hello and restart timer */ @@ -300,27 +302,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 +397,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 +475,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 +483,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 +497,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); @@ -523,46 +516,67 @@ void pim_if_addr_add(struct connected *ifc) CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); - - ifaddr = ifc->address->u.prefix4; +#if PIM_IPV != 4 + if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) || + IN6_IS_ADDR_LOOPBACK(&ifc->address->u.prefix6)) { + if (IN6_IS_ADDR_UNSPECIFIED(&pim_ifp->ll_lowest)) + pim_ifp->ll_lowest = ifc->address->u.prefix6; + else if (IPV6_ADDR_CMP(&ifc->address->u.prefix6, + &pim_ifp->ll_lowest) < 0) + pim_ifp->ll_lowest = ifc->address->u.prefix6; + + if (IPV6_ADDR_CMP(&ifc->address->u.prefix6, + &pim_ifp->ll_highest) > 0) + pim_ifp->ll_highest = ifc->address->u.prefix6; + + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: new link-local %pI6, lowest now %pI6, highest %pI6", + ifc->ifp->name, &ifc->address->u.prefix6, + &pim_ifp->ll_lowest, &pim_ifp->ll_highest); + } +#endif 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 */ close(ij->sock_fd); join_fd = igmp_join_sock( ifp->name, ifp->ifindex, ij->group_addr, - ij->source_addr); + ij->source_addr, pim_ifp); if (join_fd < 0) { char group_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; @@ -583,23 +597,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 +662,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 +680,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 +702,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; } @@ -718,6 +735,43 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) ? "secondary" : "primary"); +#if PIM_IPV == 6 + struct pim_interface *pim_ifp = ifc->ifp->info; + + if (pim_ifp && + (!IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_lowest) || + !IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_highest))) { + struct listnode *cnode; + struct connected *cc; + + memset(&pim_ifp->ll_lowest, 0xff, sizeof(pim_ifp->ll_lowest)); + memset(&pim_ifp->ll_highest, 0, sizeof(pim_ifp->ll_highest)); + + for (ALL_LIST_ELEMENTS_RO(ifc->ifp->connected, cnode, cc)) { + if (!IN6_IS_ADDR_LINKLOCAL(&cc->address->u.prefix6) && + !IN6_IS_ADDR_LOOPBACK(&cc->address->u.prefix6)) + continue; + + if (IPV6_ADDR_CMP(&cc->address->u.prefix6, + &pim_ifp->ll_lowest) < 0) + pim_ifp->ll_lowest = cc->address->u.prefix6; + if (IPV6_ADDR_CMP(&cc->address->u.prefix6, + &pim_ifp->ll_highest) > 0) + pim_ifp->ll_highest = cc->address->u.prefix6; + } + + if (pim_ifp->ll_lowest.s6_addr[0] == 0xff) + memset(&pim_ifp->ll_lowest, 0, + sizeof(pim_ifp->ll_lowest)); + + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: removed link-local %pI6, lowest now %pI6, highest %pI6", + ifc->ifp->name, &ifc->address->u.prefix6, + &pim_ifp->ll_lowest, &pim_ifp->ll_highest); + } +#endif + detect_address_change(ifp, force_prim_as_any, __func__); pim_if_addr_del_igmp(ifc); @@ -753,7 +807,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,40 +882,58 @@ 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; - } + +#if PIM_IPV == 6 + if (pim_ifp) + return pim_ifp->ll_highest; + + pim_addr best_addr = PIMADDR_ANY; for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; + pim_addr addr; - if (p->family != AF_INET) { - v6_addrs++; + if (ifc->address->family != AF_INET6) continue; - } - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - zlog_warn( - "%s: null IPv4 address connected to interface %s", - __func__, ifp->name); + addr = pim_addr_from_prefix(ifc->address); + if (!IN6_IS_ADDR_LINKLOCAL(&addr)) continue; - } + if (pim_addr_cmp(addr, best_addr) > 0) + best_addr = addr; + } + + return best_addr; +#else + int v4_addrs = 0; + int v6_addrs = 0; - v4_addrs++; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + switch (ifc->address->family) { + case AF_INET: + v4_addrs++; + break; + case AF_INET6: + v6_addrs++; + break; + default: + continue; + } if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) continue; - return p->u.prefix4; + if (ifc->address->family != PIM_AF) + continue; + + return pim_addr_from_prefix(ifc->address); } /* @@ -883,10 +955,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; + return PIMADDR_ANY; +#endif } static int pim_iface_next_vif_index(struct interface *ifp) @@ -917,7 +987,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 +1006,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 +1165,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 +1181,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 +1195,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 +1223,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); @@ -1183,12 +1248,16 @@ static struct igmp_join *igmp_join_find(struct list *join_list, } static int igmp_join_sock(const char *ifname, ifindex_t ifindex, - struct in_addr group_addr, struct in_addr source_addr) + struct in_addr group_addr, struct in_addr source_addr, + struct pim_interface *pim_ifp) { int join_fd; + pim_ifp->igmp_ifstat_joins_sent++; + join_fd = pim_socket_raw(IPPROTO_IGMP); if (join_fd < 0) { + pim_ifp->igmp_ifstat_joins_failed++; return -1; } @@ -1204,6 +1273,8 @@ static int igmp_join_sock(const char *ifname, ifindex_t ifindex, __func__, join_fd, group_str, source_str, ifindex, ifname, errno, safe_strerror(errno)); + pim_ifp->igmp_ifstat_joins_failed++; + close(join_fd); return -2; } @@ -1211,19 +1282,20 @@ 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) +#if PIM_IPV == 4 +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; assert(pim_ifp); join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, - source_addr); + source_addr, pim_ifp); if (join_fd < 0) { char group_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; @@ -1245,16 +1317,18 @@ 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; } +#endif /* PIM_IPV == 4 */ +#if PIM_IPV == 4 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 +1336,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 */ @@ -1291,13 +1365,13 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, return ferr_ok(); } - +#endif /* PIM_IPV == 4 */ 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 +1380,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 +1413,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 +1438,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 +1472,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 +1485,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 +1561,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 +1570,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 +1607,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; @@ -1559,6 +1644,7 @@ int pim_ifp_create(struct interface *ifp) pim_if_create_pimreg(pim); } +#if PIM_IPV == 4 /* * If we are a vrf device that is up, open up the pim_socket for * listening @@ -1586,15 +1672,16 @@ 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) { + uint32_t table_id; struct pim_interface *pim_ifp; struct pim_instance *pim; - uint32_t table_id; if (PIM_DEBUG_ZEBRA) { zlog_debug( @@ -1646,7 +1733,7 @@ int pim_ifp_up(struct interface *ifp) return 0; } -int pim_ifp_down(struct interface *ifp) +static int pim_ifp_down(struct interface *ifp) { if (PIM_DEBUG_ZEBRA) { zlog_debug( @@ -1664,6 +1751,7 @@ int pim_ifp_down(struct interface *ifp) */ pim_if_addr_del_all(ifp); +#if PIM_IPV == 4 /* pim_sock_delete() closes the socket, stops read and timer threads, @@ -1672,18 +1760,21 @@ int pim_ifp_down(struct interface *ifp) if (ifp->info) { pim_sock_delete(ifp, "link down"); } +#endif } - if (ifp->info) + if (ifp->info) { pim_if_del_vif(ifp); +#if PIM_IPV == 4 + 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", @@ -1695,9 +1786,35 @@ int pim_ifp_destroy(struct interface *ifp) if (!if_is_operative(ifp)) pim_if_addr_del_all(ifp); +#if PIM_IPV == 4 + struct pim_instance *pim; + 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); +} |
