From 744504a9d68a36c43209d4e1c76bfaa5a9ad7f69 Mon Sep 17 00:00:00 2001 From: Yacine Belkadi Date: Thu, 21 Apr 2011 18:41:16 +0200 Subject: 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. --- cleopatre/application/igmp_snoopd/Makefile | 2 +- cleopatre/application/igmp_snoopd/inc/internal.h | 10 +++ .../application/igmp_snoopd/src/igmp_common.c | 27 +++++++ cleopatre/application/igmp_snoopd/src/igmp_v1_v2.c | 2 + cleopatre/application/igmp_snoopd/src/igmp_v3.c | 1 + cleopatre/application/igmp_snoopd/src/main.c | 85 +++++++++++++++++++++- 6 files changed, 125 insertions(+), 2 deletions(-) (limited to 'cleopatre/application/igmp_snoopd') 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; }; /** @@ -129,6 +132,13 @@ void update_computed_metrics (struct igmp_metrics *metrics); 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 #include #include #include +#include #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 { -- cgit v1.2.3