summaryrefslogtreecommitdiff
path: root/cleopatre/application/igmp_snoopd
diff options
context:
space:
mode:
authorYacine Belkadi2011-04-21 18:41:16 +0200
committerYacine Belkadi2011-05-05 18:19:41 +0200
commit744504a9d68a36c43209d4e1c76bfaa5a9ad7f69 (patch)
treefa1ef08a77e0da97feae2a8ed1f761637888901f /cleopatre/application/igmp_snoopd
parent1f350c26cb7e949cf4c0c0b08897445e74b54bdd (diff)
cleo/app/igmp_snoopd: add timer for [Other Querier Present Interval], refs #2371
Add a timer for detecting that no querier is present, and that a query should be sent.
Diffstat (limited to 'cleopatre/application/igmp_snoopd')
-rw-r--r--cleopatre/application/igmp_snoopd/Makefile2
-rw-r--r--cleopatre/application/igmp_snoopd/inc/internal.h10
-rw-r--r--cleopatre/application/igmp_snoopd/src/igmp_common.c27
-rw-r--r--cleopatre/application/igmp_snoopd/src/igmp_v1_v2.c2
-rw-r--r--cleopatre/application/igmp_snoopd/src/igmp_v3.c1
-rw-r--r--cleopatre/application/igmp_snoopd/src/main.c85
6 files changed, 125 insertions, 2 deletions
diff --git a/cleopatre/application/igmp_snoopd/Makefile b/cleopatre/application/igmp_snoopd/Makefile
index 268caac1cd..e4c7af968d 100644
--- a/cleopatre/application/igmp_snoopd/Makefile
+++ b/cleopatre/application/igmp_snoopd/Makefile
@@ -14,7 +14,7 @@ CC_WITHOUT_CFLAGS=$(CC_FOR_TARGET)
endif
EXTRA_CFLAGS=-I$(INCPATH) -I../../include -I$(LIBSPID_DIR)/inc -MMD -Wall -Wextra -Wstrict-prototypes -Winline
-LIBS=-lm -L$(LIBSPID_DIR) -lspid
+LIBS=-lm -lrt -L$(LIBSPID_DIR) -lspid
SRCS=$(subst $(SRCPATH)/,,$(wildcard $(SRCPATH)/*.c))
OBJS=$(addprefix $(OBJPATH)/,$(SRCS:.c=.o))
diff --git a/cleopatre/application/igmp_snoopd/inc/internal.h b/cleopatre/application/igmp_snoopd/inc/internal.h
index 8e2ade5bc0..5130343ce9 100644
--- a/cleopatre/application/igmp_snoopd/inc/internal.h
+++ b/cleopatre/application/igmp_snoopd/inc/internal.h
@@ -99,6 +99,9 @@ struct context
/** The last multicast info entries written to a file. */
libspid_multicast_info_t *multicast_info;
+
+ /** timer [Other Querier Present]. */
+ timer_t timer_other_querier_present;
};
/**
@@ -130,6 +133,13 @@ void
update_timers (struct group *grp, struct group_member *member, struct igmp_metrics *metrics);
/**
+ * Update the [Other Querier Present] timer.
+ * \param ctx the context.
+ */
+void
+update_timer_other_querier_present (struct context *ctx);
+
+/**
* Initialize the metrics.
* \param metrics The IGMP metrics.
*/
diff --git a/cleopatre/application/igmp_snoopd/src/igmp_common.c b/cleopatre/application/igmp_snoopd/src/igmp_common.c
index 0096d08c5b..6fe475efe7 100644
--- a/cleopatre/application/igmp_snoopd/src/igmp_common.c
+++ b/cleopatre/application/igmp_snoopd/src/igmp_common.c
@@ -19,9 +19,11 @@
#include "internal.h"
+#include <errno.h>
#include <linux/igmp.h>
#include <math.h>
#include <stdbool.h>
+#include <string.h>
#include "utils.h"
@@ -169,6 +171,31 @@ update_timers (struct group *grp, struct group_member *member, struct igmp_metri
member->last_report_time = now;
}
+void
+update_timer_other_querier_present (struct context *ctx)
+{
+ struct itimerspec timer_spec =
+ {
+ .it_interval =
+ {
+ .tv_sec = 0,
+ .tv_nsec = 0
+ },
+ .it_value =
+ {
+ .tv_sec = ctx->metrics.other_querier_present_interval,
+ .tv_nsec = 0
+ }
+ };
+
+ if (timer_settime (ctx->timer_other_querier_present,
+ 0, &timer_spec, NULL) == -1)
+ {
+ log_error ("timer_settime: %s", strerror (errno));
+ /* TODO: exit ? */
+ }
+}
+
/**
* Is a Querier present ?
* \param metrics The IGMP metrics to consider.
diff --git a/cleopatre/application/igmp_snoopd/src/igmp_v1_v2.c b/cleopatre/application/igmp_snoopd/src/igmp_v1_v2.c
index 554a002d17..d7ef0640ac 100644
--- a/cleopatre/application/igmp_snoopd/src/igmp_v1_v2.c
+++ b/cleopatre/application/igmp_snoopd/src/igmp_v1_v2.c
@@ -84,6 +84,8 @@ process_v2_query (struct context *ctx,
{
log_debug ("Group-Specific Query");
}
+
+ update_timer_other_querier_present (ctx);
}
void
diff --git a/cleopatre/application/igmp_snoopd/src/igmp_v3.c b/cleopatre/application/igmp_snoopd/src/igmp_v3.c
index 96234c40a1..174e76bcbc 100644
--- a/cleopatre/application/igmp_snoopd/src/igmp_v3.c
+++ b/cleopatre/application/igmp_snoopd/src/igmp_v3.c
@@ -228,6 +228,7 @@ process_v3_query (struct context *ctx,
}
update_computed_metrics (&ctx->metrics);
+ update_timer_other_querier_present (ctx);
}
/**
diff --git a/cleopatre/application/igmp_snoopd/src/main.c b/cleopatre/application/igmp_snoopd/src/main.c
index bfacb2b7ef..39f07d4782 100644
--- a/cleopatre/application/igmp_snoopd/src/main.c
+++ b/cleopatre/application/igmp_snoopd/src/main.c
@@ -41,6 +41,21 @@
/* Command line options */
#define OPTARG_VLAN "--vlan"
+#define TIMER_SIGNAL SIGALRM
+
+/** Flag used by the signal handler to inform that the timer expired. */
+static volatile sig_atomic_t timer_expired = 0;
+
+/**
+ * Handler for the signal used by the timer.
+ * \param sig The signal number.
+ */
+static void
+timer_signal_handler (int __attribute__((unused)) sig)
+{
+ timer_expired = 1;
+}
+
/**
* Process a packet.
* \param ctx The context.
@@ -108,6 +123,15 @@ process_packet (struct context *ctx, unsigned char *msg, size_t len)
return process_igmp_packet (ctx, eth_header->h_source, igmp_start, msg_end);
}
+/**
+ * Send a General Query.
+ */
+static void
+send_general_query (void)
+{
+ /* TODO: implement */
+}
+
/*
* Initialize.
* \param ctx The context.
@@ -120,6 +144,16 @@ init (struct context *ctx)
init_metrics (&ctx->metrics);
ctx->multicast_info = NULL;
+
+ /* Init timer */
+ struct sigevent evp;
+ evp.sigev_notify = SIGEV_SIGNAL;
+ evp.sigev_signo = TIMER_SIGNAL;
+ evp.sigev_value.sival_int = 0;
+ evp.sigev_notify_function = NULL;
+ evp.sigev_notify_attributes = NULL;
+
+ timer_create (CLOCK_MONOTONIC, &evp, &ctx->timer_other_querier_present);
}
/**
@@ -131,6 +165,11 @@ dump (const struct context *ctx)
{
dump_info (&ctx->metrics);
dump_groups (&ctx->groups_head);
+
+ struct itimerspec timer_curr_value;
+ timer_gettime (ctx->timer_other_querier_present, &timer_curr_value);
+ log_debug ("Other Querier Present Timer: %lu",
+ (unsigned long)timer_curr_value.it_value.tv_sec);
}
static void
@@ -224,13 +263,42 @@ igmp_snooping (const char *ifname,
exit (EXIT_FAILURE);
}
+ sigset_t sigmask;
+
+ /* Block the signal used for the timer */
+ sigemptyset (&sigmask);
+ sigaddset (&sigmask, TIMER_SIGNAL);
+ if (sigprocmask (SIG_BLOCK, &sigmask, NULL) == -1)
+ {
+ log_error ("sigprocmask: %s", strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Install a handler for the signal used by the timer */
+ struct sigaction sa;
+ sa.sa_handler = timer_signal_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (TIMER_SIGNAL, &sa, NULL) == -1)
+ {
+ log_error ("sigaction: %s", strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+
+ sigset_t empty_sigmask;
+ sigemptyset (&empty_sigmask);
+
+ /* Start timer */
+ update_timer_other_querier_present (ctx);
+
while (true)
{
fd_set read_fds;
FD_ZERO (&read_fds);
FD_SET (sockfd, &read_fds);
- int ret = pselect (sockfd + 1, &read_fds, NULL, NULL, NULL, NULL);
+ int ret = pselect (sockfd + 1, &read_fds, NULL, NULL, NULL,
+ &empty_sigmask);
if (ret == 1)
{
@@ -248,6 +316,21 @@ igmp_snooping (const char *ifname,
if (errno == EINTR)
{
/* Interrupted by a signal. */
+ if (timer_expired)
+ {
+ timer_expired = 0;
+
+ send_general_query ();
+
+ /* In case something bad happens to the query, we re-arm
+ * the timer.
+ * This will be canceled if the query is received. */
+ update_timer_other_querier_present (ctx);
+ }
+ else
+ {
+ log_debug ("interrupted by unexpected signal");
+ }
}
else
{