summaryrefslogtreecommitdiffstats
path: root/pimd/pim_igmpv3.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2021-08-24 15:25:48 +0200
committerDavid Lamparter <equinox@opensourcerouting.org>2021-08-27 10:42:53 +0200
commitdda4d23ccad4264d80cbf39091b08ed070a3791b (patch)
tree111f6a18301704e082048c1e0c1ae8a83a610a8b /pimd/pim_igmpv3.c
parentpimd: de-circularize includes (diff)
downloadfrr-dda4d23ccad4264d80cbf39091b08ed070a3791b.tar.xz
frr-dda4d23ccad4264d80cbf39091b08ed070a3791b.zip
pimd: IGMP memberships are not querier specific
IGMP group/source memberships are a property of the interface; the particular IP address that the querier used to collect the data is irrelevant. ... and IGMP packets get delivered only once to pimd anyway, since we receive them on the "global" per-VRF IGMP socket. (The one in igmp_sock is only used for sending queries.) Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'pimd/pim_igmpv3.c')
-rw-r--r--pimd/pim_igmpv3.c176
1 files changed, 82 insertions, 94 deletions
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index bc67a1dd1..f13dfe1b8 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -57,16 +57,28 @@ static void on_trace(const char *label, struct interface *ifp,
}
}
+static inline long igmp_gmi_msec(struct igmp_group *group)
+{
+ struct pim_interface *pim_ifp = group->interface->info;
+ struct igmp_sock *igmp;
+ struct listnode *sock_node;
+
+ long qrv = 0, qqi = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
+ qrv = MAX(qrv, igmp->querier_robustness_variable);
+ qqi = MAX(qqi, igmp->querier_query_interval);
+ }
+ return PIM_IGMP_GMI_MSEC(qrv, qqi,
+ pim_ifp->igmp_query_max_response_time_dsec);
+}
+
void igmp_group_reset_gmi(struct igmp_group *group)
{
long group_membership_interval_msec;
- struct pim_interface *pim_ifp;
- struct igmp_sock *igmp;
struct interface *ifp;
- igmp = group->group_igmp_sock;
- ifp = igmp->interface;
- pim_ifp = ifp->info;
+ ifp = group->interface;
/*
RFC 3376: 8.4. Group Membership Interval
@@ -82,9 +94,7 @@ void igmp_group_reset_gmi(struct igmp_group *group)
(1000 * querier_query_interval) +
100 * query_response_interval_dsec;
*/
- group_membership_interval_msec = PIM_IGMP_GMI_MSEC(
- igmp->querier_robustness_variable, igmp->querier_query_interval,
- pim_ifp->igmp_query_max_response_time_dsec);
+ group_membership_interval_msec = igmp_gmi_msec(group);
if (PIM_DEBUG_IGMP_TRACE) {
char group_str[INET_ADDRSTRLEN];
@@ -127,7 +137,7 @@ static int igmp_source_timer(struct thread *t)
zlog_debug(
"%s: Source timer expired for group %s source %s on %s",
__func__, group_str, source_str,
- group->group_igmp_sock->interface->name);
+ group->interface->name);
}
/*
@@ -189,7 +199,7 @@ static void source_timer_off(struct igmp_group *group,
zlog_debug(
"Cancelling TIMER event for group %s source %s on %s",
group_str, source_str,
- group->group_igmp_sock->interface->name);
+ group->interface->name);
}
THREAD_OFF(source->t_source_timer);
@@ -199,7 +209,7 @@ static void igmp_source_timer_on(struct igmp_group *group,
struct igmp_source *source, long interval_msec)
{
source_timer_off(group, source);
- struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
+ struct pim_interface *pim_ifp = group->interface->info;
if (PIM_DEBUG_IGMP_EVENTS) {
char group_str[INET_ADDRSTRLEN];
@@ -211,7 +221,7 @@ static void igmp_source_timer_on(struct igmp_group *group,
zlog_debug(
"Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s",
interval_msec / 1000, interval_msec % 1000, group_str,
- source_str, group->group_igmp_sock->interface->name);
+ source_str, group->interface->name);
}
thread_add_timer_msec(router->master, igmp_source_timer, source,
@@ -225,19 +235,14 @@ static void igmp_source_timer_on(struct igmp_group *group,
igmp_source_forward_start(pim_ifp->pim, source);
}
-void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group,
- struct igmp_source *source)
+void igmp_source_reset_gmi(struct igmp_group *group, struct igmp_source *source)
{
long group_membership_interval_msec;
- struct pim_interface *pim_ifp;
struct interface *ifp;
- ifp = igmp->interface;
- pim_ifp = ifp->info;
+ ifp = group->interface;
- group_membership_interval_msec = PIM_IGMP_GMI_MSEC(
- igmp->querier_robustness_variable, igmp->querier_query_interval,
- pim_ifp->igmp_query_max_response_time_dsec);
+ group_membership_interval_msec = igmp_gmi_msec(group);
if (PIM_DEBUG_IGMP_TRACE) {
char group_str[INET_ADDRSTRLEN];
@@ -312,7 +317,7 @@ static void source_clear_send_flag(struct list *source_list)
*/
static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group)
{
- struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
+ struct pim_interface *pim_ifp = group->interface->info;
assert(group->group_filtermode_isexcl);
@@ -356,9 +361,9 @@ void igmp_source_delete(struct igmp_source *source)
pim_inet4_dump("<source?>", source->source_addr, source_str,
sizeof(source_str));
zlog_debug(
- "Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d",
- source_str, group_str, group->group_igmp_sock->fd,
- group->group_igmp_sock->interface->name,
+ "Deleting IGMP source %s for group %s from interface %s c_oil ref_count %d",
+ source_str, group_str,
+ group->interface->name,
source->source_channel_oil
? source->source_channel_oil->oil_ref_count
: 0);
@@ -376,10 +381,9 @@ void igmp_source_delete(struct igmp_source *source)
pim_inet4_dump("<source?>", source->source_addr, source_str,
sizeof(source_str));
zlog_warn(
- "%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s",
+ "%s: forwarding=ON(!) IGMP source %s for group %s from interface %s",
__func__, source_str, group_str,
- group->group_igmp_sock->fd,
- group->group_igmp_sock->interface->name);
+ group->interface->name);
/* warning only */
}
@@ -452,9 +456,8 @@ struct igmp_source *source_new(struct igmp_group *group,
pim_inet4_dump("<source?>", src_addr, source_str,
sizeof(source_str));
zlog_debug(
- "Creating new IGMP source %s for group %s on socket %d interface %s",
- source_str, group_str, group->group_igmp_sock->fd,
- group->group_igmp_sock->interface->name);
+ "Creating new IGMP source %s for group %s on interface %s",
+ source_str, group_str, group->interface->name);
}
src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src));
@@ -518,8 +521,7 @@ static void allow(struct igmp_sock *igmp, struct in_addr from,
source = igmp_find_source_by_addr(group, star);
if (source)
- igmp_source_reset_gmi(igmp, group,
- source);
+ igmp_source_reset_gmi(group, source);
}
} else {
igmp_group_delete(group);
@@ -555,7 +557,7 @@ static void allow(struct igmp_sock *igmp, struct in_addr from,
igmp_source_reset_gmi() below, resetting the source timers to
GMI, accomplishes this.
*/
- igmp_source_reset_gmi(igmp, group, source);
+ igmp_source_reset_gmi(group, source);
} /* scan received sources */
}
@@ -598,8 +600,7 @@ static void isex_excl(struct igmp_group *group, int num_sources,
* (A-X-Y) */
source = source_new(group, *src_addr);
assert(!source->t_source_timer); /* timer == 0 */
- igmp_source_reset_gmi(group->group_igmp_sock, group,
- source);
+ igmp_source_reset_gmi(group, source);
assert(source->t_source_timer); /* (A-X-Y) timer > 0 */
}
@@ -615,8 +616,7 @@ static void isex_excl(struct igmp_group *group, int num_sources,
source = igmp_find_source_by_addr(group, star);
if (source) {
IGMP_SOURCE_DONT_DELETE(source->source_flags);
- igmp_source_reset_gmi(group->group_igmp_sock, group,
- source);
+ igmp_source_reset_gmi(group, source);
}
}
@@ -706,7 +706,6 @@ void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from,
static void toin_incl(struct igmp_group *group, int num_sources,
struct in_addr *sources)
{
- struct igmp_sock *igmp = group->group_igmp_sock;
int num_sources_tosend = listcount(group->group_source_list);
int i;
@@ -732,7 +731,7 @@ static void toin_incl(struct igmp_group *group, int num_sources,
}
/* (B)=GMI */
- igmp_source_reset_gmi(igmp, group, source);
+ igmp_source_reset_gmi(group, source);
}
/* Send sources marked with SEND flag: Q(G,A-B) */
@@ -744,7 +743,6 @@ static void toin_incl(struct igmp_group *group, int num_sources,
static void toin_excl(struct igmp_group *group, int num_sources,
struct in_addr *sources)
{
- struct igmp_sock *igmp = group->group_igmp_sock;
int num_sources_tosend;
int i;
@@ -773,7 +771,7 @@ static void toin_excl(struct igmp_group *group, int num_sources,
}
/* (A)=GMI */
- igmp_source_reset_gmi(igmp, group, source);
+ igmp_source_reset_gmi(group, source);
}
/* Send sources marked with SEND flag: Q(G,X-A) */
@@ -986,6 +984,27 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from,
allow(igmp, from, group_addr, num_sources, sources);
}
+static void igmp_send_query_group(struct igmp_group *group, char *query_buf,
+ size_t query_buf_size, int num_sources,
+ int s_flag)
+{
+ struct interface *ifp = group->interface;
+ struct pim_interface *pim_ifp = ifp->info;
+ struct igmp_sock *igmp;
+ struct listnode *sock_node;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
+ igmp_send_query(pim_ifp->igmp_version, group, igmp->fd,
+ ifp->name, query_buf, query_buf_size,
+ num_sources, group->group_addr,
+ group->group_addr,
+ pim_ifp->igmp_specific_query_max_response_time_dsec,
+ s_flag,
+ igmp->querier_robustness_variable,
+ igmp->querier_query_interval);
+ }
+}
+
/*
RFC3376: 6.6.3.1. Building and Sending Group Specific Queries
@@ -995,7 +1014,6 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from,
*/
static void group_retransmit_group(struct igmp_group *group)
{
- struct igmp_sock *igmp;
struct pim_interface *pim_ifp;
long lmqc; /* Last Member Query Count */
long lmqi_msec; /* Last Member Query Interval */
@@ -1003,8 +1021,7 @@ static void group_retransmit_group(struct igmp_group *group)
int s_flag;
int query_buf_size;
- igmp = group->group_igmp_sock;
- pim_ifp = igmp->interface->info;
+ pim_ifp = group->interface->info;
if (pim_ifp->igmp_version == 3) {
query_buf_size = PIM_IGMP_BUFSIZE_WRITE;
@@ -1033,7 +1050,7 @@ static void group_retransmit_group(struct igmp_group *group)
sizeof(group_str));
zlog_debug(
"retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d",
- group_str, igmp->interface->name, s_flag,
+ group_str, group->interface->name, s_flag,
group->group_specific_query_retransmit_count);
}
@@ -1045,14 +1062,7 @@ static void group_retransmit_group(struct igmp_group *group)
interest.
*/
- igmp_send_query(pim_ifp->igmp_version, group, igmp->fd,
- igmp->interface->name, query_buf, sizeof(query_buf),
- 0 /* num_sources_tosend */,
- group->group_addr /* dst_addr */,
- group->group_addr /* group_addr */,
- pim_ifp->igmp_specific_query_max_response_time_dsec,
- s_flag, igmp->querier_robustness_variable,
- igmp->querier_query_interval);
+ igmp_send_query_group(group, query_buf, sizeof(query_buf), 0, s_flag);
}
/*
@@ -1070,7 +1080,6 @@ static void group_retransmit_group(struct igmp_group *group)
static int group_retransmit_sources(struct igmp_group *group,
int send_with_sflag_set)
{
- struct igmp_sock *igmp;
struct pim_interface *pim_ifp;
long lmqc; /* Last Member Query Count */
long lmqi_msec; /* Last Member Query Interval */
@@ -1090,8 +1099,7 @@ static int group_retransmit_sources(struct igmp_group *group,
source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET);
source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET);
- igmp = group->group_igmp_sock;
- pim_ifp = igmp->interface->info;
+ pim_ifp = group->interface->info;
lmqc = pim_ifp->igmp_last_member_query_count;
lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
@@ -1131,7 +1139,7 @@ static int group_retransmit_sources(struct igmp_group *group,
sizeof(group_str));
zlog_debug(
"retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d",
- group_str, igmp->interface->name, num_sources_tosend1,
+ group_str, group->interface->name, num_sources_tosend1,
num_sources_tosend2, send_with_sflag_set,
num_retransmit_sources_left);
}
@@ -1154,7 +1162,7 @@ static int group_retransmit_sources(struct igmp_group *group,
zlog_warn(
"%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)",
__func__, group_str,
- igmp->interface->name,
+ group->interface->name,
num_sources_tosend1, sizeof(query_buf1),
query_buf1_max_sources);
} else {
@@ -1169,15 +1177,10 @@ static int group_retransmit_sources(struct igmp_group *group,
interest.
*/
- igmp_send_query(
- pim_ifp->igmp_version, group, igmp->fd,
- igmp->interface->name, query_buf1,
- sizeof(query_buf1), num_sources_tosend1,
- group->group_addr, group->group_addr,
- pim_ifp->igmp_specific_query_max_response_time_dsec,
- 1 /* s_flag */,
- igmp->querier_robustness_variable,
- igmp->querier_query_interval);
+ igmp_send_query_group(group, query_buf1,
+ sizeof(query_buf1),
+ num_sources_tosend1,
+ 1 /* s_flag */);
}
} /* send_with_sflag_set */
@@ -1197,7 +1200,7 @@ static int group_retransmit_sources(struct igmp_group *group,
sizeof(group_str));
zlog_warn(
"%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)",
- __func__, group_str, igmp->interface->name,
+ __func__, group_str, group->interface->name,
num_sources_tosend2, sizeof(query_buf2),
query_buf2_max_sources);
} else {
@@ -1211,15 +1214,10 @@ static int group_retransmit_sources(struct igmp_group *group,
interest.
*/
- igmp_send_query(
- pim_ifp->igmp_version, group, igmp->fd,
- igmp->interface->name, query_buf2,
- sizeof(query_buf2), num_sources_tosend2,
- group->group_addr, group->group_addr,
- pim_ifp->igmp_specific_query_max_response_time_dsec,
- 0 /* s_flag */,
- igmp->querier_robustness_variable,
- igmp->querier_query_interval);
+ igmp_send_query_group(group, query_buf2,
+ sizeof(query_buf2),
+ num_sources_tosend2,
+ 0 /* s_flag */);
}
}
@@ -1239,7 +1237,7 @@ static int igmp_group_retransmit(struct thread *t)
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
zlog_debug("group_retransmit_timer: group %s on %s", group_str,
- group->group_igmp_sock->interface->name);
+ group->interface->name);
}
/* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */
@@ -1287,7 +1285,6 @@ static int igmp_group_retransmit(struct thread *t)
*/
static void group_retransmit_timer_on(struct igmp_group *group)
{
- struct igmp_sock *igmp;
struct pim_interface *pim_ifp;
long lmqi_msec; /* Last Member Query Interval */
@@ -1296,8 +1293,7 @@ static void group_retransmit_timer_on(struct igmp_group *group)
return;
}
- igmp = group->group_igmp_sock;
- pim_ifp = igmp->interface->info;
+ pim_ifp = group->interface->info;
lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
@@ -1308,7 +1304,7 @@ static void group_retransmit_timer_on(struct igmp_group *group)
zlog_debug(
"Scheduling %ld.%03ld sec retransmit timer for group %s on %s",
lmqi_msec / 1000, lmqi_msec % 1000, group_str,
- igmp->interface->name);
+ group->interface->name);
}
thread_add_timer_msec(router->master, igmp_group_retransmit, group,
@@ -1332,11 +1328,9 @@ static long igmp_source_timer_remain_msec(struct igmp_source *source)
static void group_query_send(struct igmp_group *group)
{
struct pim_interface *pim_ifp;
- struct igmp_sock *igmp;
long lmqc; /* Last Member Query Count */
- igmp = group->group_igmp_sock;
- pim_ifp = igmp->interface->info;
+ pim_ifp = group->interface->info;
lmqc = pim_ifp->igmp_last_member_query_count;
/* lower group timer to lmqt */
@@ -1359,7 +1353,6 @@ static void group_query_send(struct igmp_group *group)
static void source_query_send_by_flag(struct igmp_group *group,
int num_sources_tosend)
{
- struct igmp_sock *igmp;
struct pim_interface *pim_ifp;
struct listnode *src_node;
struct igmp_source *src;
@@ -1369,8 +1362,7 @@ static void source_query_send_by_flag(struct igmp_group *group,
assert(num_sources_tosend > 0);
- igmp = group->group_igmp_sock;
- pim_ifp = igmp->interface->info;
+ pim_ifp = group->interface->info;
lmqc = pim_ifp->igmp_last_member_query_count;
lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
@@ -1504,7 +1496,6 @@ void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from,
void igmp_group_timer_lower_to_lmqt(struct igmp_group *group)
{
- struct igmp_sock *igmp;
struct interface *ifp;
struct pim_interface *pim_ifp;
char *ifname;
@@ -1523,8 +1514,7 @@ void igmp_group_timer_lower_to_lmqt(struct igmp_group *group)
return;
}
- igmp = group->group_igmp_sock;
- ifp = igmp->interface;
+ ifp = group->interface;
pim_ifp = ifp->info;
ifname = ifp->name;
@@ -1551,7 +1541,6 @@ void igmp_group_timer_lower_to_lmqt(struct igmp_group *group)
void igmp_source_timer_lower_to_lmqt(struct igmp_source *source)
{
struct igmp_group *group;
- struct igmp_sock *igmp;
struct interface *ifp;
struct pim_interface *pim_ifp;
char *ifname;
@@ -1560,8 +1549,7 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source)
int lmqt_msec; /* Last Member Query Time */
group = source->source_group;
- igmp = group->group_igmp_sock;
- ifp = igmp->interface;
+ ifp = group->interface;
pim_ifp = ifp->info;
ifname = ifp->name;