#include "pim_rp.h"
#include "pim_nht.h"
#include "pim_jp_agg.h"
+#include "pim_igmp_join.h"
static void pim_if_igmp_join_del_all(struct interface *ifp);
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
void pim_if_terminate(struct pim_instance *pim)
{
- // Nothing to do at this moment
- return;
-}
-
-static void *if_list_clean(struct pim_interface *pim_ifp)
-{
- struct pim_ifchannel *ch;
-
- if (pim_ifp->igmp_join_list)
- list_delete_and_null(&pim_ifp->igmp_join_list);
-
- if (pim_ifp->igmp_socket_list)
- list_delete_and_null(&pim_ifp->igmp_socket_list);
-
- if (pim_ifp->pim_neighbor_list)
- list_delete_and_null(&pim_ifp->pim_neighbor_list);
-
- if (pim_ifp->upstream_switch_list)
- list_delete_and_null(&pim_ifp->upstream_switch_list);
+ struct interface *ifp;
- if (pim_ifp->sec_addr_list)
- list_delete_and_null(&pim_ifp->sec_addr_list);
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ struct pim_interface *pim_ifp = ifp->info;
- while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
- ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
+ if (!pim_ifp)
+ continue;
- pim_ifchannel_delete(ch);
+ pim_if_delete(ifp);
}
-
- XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
-
- return 0;
+ return;
}
static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
return 0;
}
-struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
+struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
+ bool ispimreg)
{
struct pim_interface *pim_ifp;
zassert(!ifp->info);
pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
- if (!pim_ifp) {
- zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp));
- return 0;
- }
pim_ifp->options = 0;
pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
/* list of struct igmp_sock */
pim_ifp->igmp_socket_list = list_new();
- if (!pim_ifp->igmp_socket_list) {
- zlog_err("%s: failure: igmp_socket_list=list_new()",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
/* list of struct pim_neighbor */
pim_ifp->pim_neighbor_list = list_new();
- if (!pim_ifp->pim_neighbor_list) {
- zlog_err("%s: failure: pim_neighbor_list=list_new()",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
pim_ifp->upstream_switch_list = list_new();
- if (!pim_ifp->upstream_switch_list) {
- zlog_err("%s: failure: upstream_switch_list=list_new()",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->upstream_switch_list->del =
(void (*)(void *))pim_jp_agg_group_list_free;
pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
pim_ifp->sec_addr_list = list_new();
- if (!pim_ifp->sec_addr_list) {
- zlog_err("%s: failure: secondary addresslist",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
pim_ifp->sec_addr_list->cmp =
(int (*)(void *, void *))pim_sec_addr_comp;
pim_sock_reset(ifp);
- pim_if_add_vif(ifp);
+ pim_if_add_vif(ifp, ispimreg);
return pim_ifp;
}
pim_if_del_vif(ifp);
- list_delete_and_null(&pim_ifp->igmp_socket_list);
- list_delete_and_null(&pim_ifp->pim_neighbor_list);
- list_delete_and_null(&pim_ifp->upstream_switch_list);
- list_delete_and_null(&pim_ifp->sec_addr_list);
+ list_delete(&pim_ifp->igmp_socket_list);
+ list_delete(&pim_ifp->pim_neighbor_list);
+ list_delete(&pim_ifp->upstream_switch_list);
+ list_delete(&pim_ifp->sec_addr_list);
if (pim_ifp->boundary_oil_plist)
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
}
sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
- if (!sec_addr)
- return changed;
changed = 1;
sec_addr->addr = *addr;
/* if addr new, add IGMP socket */
if (ifc->address->family == AF_INET)
pim_igmp_sock_add(pim_ifp->igmp_socket_list,
- ifaddr, ifp);
+ ifaddr, ifp, false);
+ } else if (igmp->mtrace_only) {
+ igmp_sock_delete(igmp);
+ pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
+ ifp, false);
}
/* Replay Static IGMP groups */
}
}
} /* igmp */
+ else {
+ struct igmp_sock *igmp;
+
+ /* lookup IGMP socket */
+ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_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);
+ }
+ } /* igmp mtrace only */
if (PIM_IF_TEST_PIM(pim_ifp->options)) {
address assigned, then try to create a vif_index.
*/
if (pim_ifp->mroute_vif_index < 0) {
- pim_if_add_vif(ifp);
+ pim_if_add_vif(ifp, false);
}
pim_ifchannel_scan_forward_start(ifp);
}
* address assigned, then try to create a vif_index.
*/
if (pim_ifp->mroute_vif_index < 0) {
- pim_if_add_vif(ifp);
+ pim_if_add_vif(ifp, false);
}
pim_ifchannel_scan_forward_start(ifp);
see also pim_if_find_vifindex_by_ifindex()
*/
-int pim_if_add_vif(struct interface *ifp)
+int pim_if_add_vif(struct interface *ifp, bool ispimreg)
{
struct pim_interface *pim_ifp = ifp->info;
struct in_addr ifaddr;
}
ifaddr = pim_ifp->primary_address;
- if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF
- && PIM_INADDR_IS_ANY(ifaddr)) {
+ if (!ispimreg && PIM_INADDR_IS_ANY(ifaddr)) {
zlog_warn(
"%s: could not get address for interface %s ifindex=%d",
__PRETTY_FUNCTION__, ifp->name, ifp->ifindex);
return -1;
}
- if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr,
- ifname)) {
+ if (pim_igmp_join_source(join_fd, ifindex, group_addr, source_addr)) {
+ char group_str[INET_ADDRSTRLEN];
+ char source_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<grp?>", group_addr, group_str,
+ sizeof(group_str));
+ pim_inet4_dump("<src?>", source_addr, source_str,
+ sizeof(source_str));
+ zlog_warn(
+ "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
+ __PRETTY_FUNCTION__, join_fd, group_str, source_str,
+ ifindex, ifname, errno, safe_strerror(errno));
+
close(join_fd);
return -2;
}
if (join_fd < 0) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
+
pim_inet4_dump("<grp?>", group_addr, group_str,
sizeof(group_str));
pim_inet4_dump("<src?>", source_addr, source_str,
}
ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
- if (!ij) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<grp?>", group_addr, group_str,
- sizeof(group_str));
- pim_inet4_dump("<src?>", source_addr, source_str,
- sizeof(source_str));
- zlog_err(
- "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s",
- __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str,
- ifp->name);
- close(join_fd);
- return 0;
- }
ij->sock_fd = join_fd;
ij->group_addr = group_addr;
if (!pim_ifp->igmp_join_list) {
pim_ifp->igmp_join_list = list_new();
- if (!pim_ifp->igmp_join_list) {
- return ferr_cfg_invalid("Insufficient memory");
- }
pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
}
listnode_delete(pim_ifp->igmp_join_list, ij);
igmp_join_free(ij);
if (listcount(pim_ifp->igmp_join_list) < 1) {
- list_delete_and_null(&pim_ifp->igmp_join_list);
+ list_delete(&pim_ifp->igmp_join_list);
pim_ifp->igmp_join_list = 0;
}
pim->regiface = if_create(pimreg_name, pim->vrf_id);
pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
- pim_if_new(pim->regiface, 0, 0);
+ pim_if_new(pim->regiface, false, false, true);
}
}
return 0;
}
-int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp)
-{
- if (if_is_loopback(ifp))
- return 1;
-
- if (strcmp(ifp->name, pim->vrf->name) == 0)
- return 1;
-
- return 0;
-}
-
-int pim_if_is_vrf_device(struct interface *ifp)
+bool pim_if_is_vrf_device(struct interface *ifp)
{
- struct vrf *vrf;
+ if (if_is_vrf(ifp))
+ return true;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- if (strncmp(ifp->name, vrf->name, strlen(ifp->name)) == 0)
- return 1;
- }
-
- return 0;
+ return false;
}
int pim_if_ifchannel_count(struct pim_interface *pim_ifp)