summaryrefslogtreecommitdiff
path: root/pimd/pim_igmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_igmp.c')
-rw-r--r--pimd/pim_igmp.c107
1 files changed, 61 insertions, 46 deletions
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 71b2d9187a..28f2b30ef4 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -810,13 +810,8 @@ static void igmp_group_free(struct igmp_group *group)
XFREE(MTYPE_PIM_IGMP_GROUP, group);
}
-static void igmp_group_count_incr(struct igmp_sock *igmp)
+static void igmp_group_count_incr(struct pim_interface *pim_ifp)
{
- struct pim_interface *pim_ifp = igmp->interface->info;
-
- if (!pim_ifp)
- return;
-
++pim_ifp->pim->igmp_group_count;
if (pim_ifp->pim->igmp_group_count
== pim_ifp->pim->igmp_watermark_limit) {
@@ -827,13 +822,8 @@ static void igmp_group_count_incr(struct igmp_sock *igmp)
}
}
-static void igmp_group_count_decr(struct igmp_sock *igmp)
+static void igmp_group_count_decr(struct pim_interface *pim_ifp)
{
- struct pim_interface *pim_ifp = igmp->interface->info;
-
- if (!pim_ifp)
- return;
-
if (pim_ifp->pim->igmp_group_count == 0) {
zlog_warn("Cannot decrement igmp group count below 0(vrf: %s)",
VRF_LOGNAME(pim_ifp->pim->vrf));
@@ -848,14 +838,14 @@ void igmp_group_delete(struct igmp_group *group)
struct listnode *src_node;
struct listnode *src_nextnode;
struct igmp_source *src;
+ struct pim_interface *pim_ifp = group->interface->info;
if (PIM_DEBUG_IGMP_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
- zlog_debug("Deleting IGMP group %s from socket %d interface %s",
- group_str, group->group_igmp_sock->fd,
- group->group_igmp_sock->interface->name);
+ zlog_debug("Deleting IGMP group %s from interface %s",
+ group_str, group->interface->name);
}
for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode,
@@ -866,9 +856,9 @@ void igmp_group_delete(struct igmp_group *group)
THREAD_OFF(group->t_group_query_retransmit_timer);
group_timer_off(group);
- igmp_group_count_decr(group->group_igmp_sock);
- listnode_delete(group->group_igmp_sock->igmp_group_list, group);
- hash_release(group->group_igmp_sock->igmp_group_hash, group);
+ igmp_group_count_decr(pim_ifp);
+ listnode_delete(pim_ifp->igmp_group_list, group);
+ hash_release(pim_ifp->igmp_group_hash, group);
igmp_group_free(group);
}
@@ -886,11 +876,6 @@ void igmp_sock_free(struct igmp_sock *igmp)
assert(!igmp->t_igmp_read);
assert(!igmp->t_igmp_query_timer);
assert(!igmp->t_other_querier_timer);
- assert(igmp->igmp_group_list);
- assert(!listcount(igmp->igmp_group_list));
-
- list_delete(&igmp->igmp_group_list);
- hash_free(igmp->igmp_group_hash);
XFREE(MTYPE_PIM_IGMP_SOCKET, igmp);
}
@@ -898,14 +883,6 @@ void igmp_sock_free(struct igmp_sock *igmp)
void igmp_sock_delete(struct igmp_sock *igmp)
{
struct pim_interface *pim_ifp;
- struct listnode *grp_node;
- struct listnode *grp_nextnode;
- struct igmp_group *grp;
-
- for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode,
- grp)) {
- igmp_group_delete(grp);
- }
sock_close(igmp);
@@ -914,6 +891,9 @@ void igmp_sock_delete(struct igmp_sock *igmp)
listnode_delete(pim_ifp->igmp_socket_list, igmp);
igmp_sock_free(igmp);
+
+ if (!listcount(pim_ifp->igmp_socket_list))
+ pim_igmp_if_reset(pim_ifp);
}
void igmp_sock_delete_all(struct interface *ifp)
@@ -948,12 +928,52 @@ static bool igmp_group_hash_equal(const void *arg1, const void *arg2)
return false;
}
+void pim_igmp_if_init(struct pim_interface *pim_ifp, struct interface *ifp)
+{
+ char hash_name[64];
+
+ pim_ifp->igmp_socket_list = list_new();
+ pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
+
+ pim_ifp->igmp_group_list = list_new();
+ pim_ifp->igmp_group_list->del = (void (*)(void *))igmp_group_free;
+
+ snprintf(hash_name, sizeof(hash_name), "IGMP %s hash",
+ ifp->name);
+ pim_ifp->igmp_group_hash = hash_create(igmp_group_hash_key,
+ igmp_group_hash_equal,
+ hash_name);
+}
+
+void pim_igmp_if_reset(struct pim_interface *pim_ifp)
+{
+ struct listnode *grp_node, *grp_nextnode;
+ struct igmp_group *grp;
+
+ for (ALL_LIST_ELEMENTS(pim_ifp->igmp_group_list, grp_node, grp_nextnode,
+ grp)) {
+ igmp_group_delete(grp);
+ }
+}
+
+void pim_igmp_if_fini(struct pim_interface *pim_ifp)
+{
+ pim_igmp_if_reset(pim_ifp);
+
+ assert(pim_ifp->igmp_group_list);
+ assert(!listcount(pim_ifp->igmp_group_list));
+
+ list_delete(&pim_ifp->igmp_group_list);
+ hash_free(pim_ifp->igmp_group_hash);
+
+ list_delete(&pim_ifp->igmp_socket_list);
+}
+
static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
struct interface *ifp, int mtrace_only)
{
struct pim_interface *pim_ifp;
struct igmp_sock *igmp;
- char hash_name[64];
pim_ifp = ifp->info;
@@ -965,13 +985,6 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp));
- igmp->igmp_group_list = list_new();
- igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free;
-
- snprintf(hash_name, sizeof(hash_name), "IGMP %s hash", ifp->name);
- igmp->igmp_group_hash = hash_create(igmp_group_hash_key,
- igmp_group_hash_equal, hash_name);
-
igmp->fd = fd;
igmp->interface = ifp;
igmp->ifaddr = ifaddr;
@@ -1114,7 +1127,7 @@ static int igmp_group_timer(struct thread *t)
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
zlog_debug("%s: Timer for group %s on interface %s", __func__,
- group_str, group->group_igmp_sock->interface->name);
+ group_str, group->interface->name);
}
assert(group->group_filtermode_isexcl);
@@ -1151,7 +1164,7 @@ static void group_timer_off(struct igmp_group *group)
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
zlog_debug("Cancelling TIMER event for group %s on %s",
- group_str, group->group_igmp_sock->interface->name);
+ group_str, group->interface->name);
}
THREAD_OFF(group->t_group_timer);
}
@@ -1188,16 +1201,18 @@ struct igmp_group *find_group_by_addr(struct igmp_sock *igmp,
struct in_addr group_addr)
{
struct igmp_group lookup;
+ struct pim_interface *pim_ifp = igmp->interface->info;
lookup.group_addr.s_addr = group_addr.s_addr;
- return hash_lookup(igmp->igmp_group_hash, &lookup);
+ return hash_lookup(pim_ifp->igmp_group_hash, &lookup);
}
struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
struct in_addr group_addr)
{
struct igmp_group *group;
+ struct pim_interface *pim_ifp = igmp->interface->info;
group = find_group_by_addr(igmp, group_addr);
if (group) {
@@ -1239,7 +1254,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
group->t_group_query_retransmit_timer = NULL;
group->group_specific_query_retransmit_count = 0;
group->group_addr = group_addr;
- group->group_igmp_sock = igmp;
+ group->interface = igmp->interface;
group->last_igmp_v1_report_dsec = -1;
group->last_igmp_v2_report_dsec = -1;
group->group_creation = pim_time_monotonic_sec();
@@ -1248,8 +1263,8 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
/* initialize new group as INCLUDE {empty} */
group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */
- listnode_add(igmp->igmp_group_list, group);
- group = hash_get(igmp->igmp_group_hash, group, hash_alloc_intern);
+ listnode_add(pim_ifp->igmp_group_list, group);
+ group = hash_get(pim_ifp->igmp_group_hash, group, hash_alloc_intern);
if (PIM_DEBUG_IGMP_TRACE) {
char group_str[INET_ADDRSTRLEN];
@@ -1260,7 +1275,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
group_str, igmp->fd, igmp->interface->name);
}
- igmp_group_count_incr(igmp);
+ igmp_group_count_incr(pim_ifp);
/*
RFC 3376: 6.2.2. Definition of Group Timers