summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYacine Belkadi2011-03-14 18:37:36 +0100
committerYacine Belkadi2011-03-25 12:01:15 +0100
commit81296fa875f32e8a1a8f4360b2a3659cf66fc212 (patch)
tree90a265887eac7b7dba6e16095c9a198d165c4488
parent55932d12e74886e8c7079a5b2cf658a4eff0fb2a (diff)
cleo/devkit/plcd: no need to detect changes in multicast info anymore, closes #2368
Up to now, plcd needed to compare the new content of the multicast info file with the previous content to detect changes and determine if it should send the info. Now, igmp_snoopd only warns plcd if the multicast file really changed. So plcd can just read the file and send the info.
-rw-r--r--cleopatre/devkit/plcd/inc/plcd.h57
-rw-r--r--cleopatre/devkit/plcd/src/plcd_mcast.c255
-rw-r--r--cleopatre/devkit/plcd/src/plcd_process.c2
3 files changed, 117 insertions, 197 deletions
diff --git a/cleopatre/devkit/plcd/inc/plcd.h b/cleopatre/devkit/plcd/inc/plcd.h
index 7b999b1088..75f7404a52 100644
--- a/cleopatre/devkit/plcd/inc/plcd.h
+++ b/cleopatre/devkit/plcd/inc/plcd.h
@@ -62,12 +62,6 @@
#define PLCD_EVENT_REFRESH_TIMEOUT_MS 1000
#define PLCD_INIT_RETRIES 10
-/* Maximum number of multicast groups */
-#define MCAST_GROUP_MAX_NB ((uint8_t)12)
-
-/* Maxium number of members in a multicast group */
-#define MCAST_MEMBER_MAX_NB ((uint8_t)1)
-
typedef enum
{
MME_DRV_STATUS_ASSOC_UNASSOCIATED = 0,
@@ -128,40 +122,7 @@ static char *mme_drv_key_sl_table[] =
NULL
};
-/** Multicast group member */
-typedef struct
-{
- /** The MAC address of the member */
- unsigned char mac_address[ETHER_ADDR_LEN];
-} mcast_member_t;
-
-/** Multicast group */
-typedef struct
-{
- /** The MAC address of the group */
- unsigned char mac_address[ETHER_ADDR_LEN];
-
- /** The list of members of the group */
- mcast_member_t members[MCAST_MEMBER_MAX_NB];
-
- /** The number of members of the group */
- uint8_t member_count;
-
-} mcast_group_t;
-
-/** Multicast info */
-typedef struct
-{
- /** The list of multicast groups */
- mcast_group_t groups[MCAST_GROUP_MAX_NB];
-
- /** The number of groups */
- uint8_t group_count;
-
- /** The last time the file containing the multicast info was checked */
- time_t last_file_check;
-} mcast_info_t;
/** main context of plc daemon */
typedef struct
@@ -215,8 +176,8 @@ typedef struct
libspid_boolean_t is_sc_button;
} hpav_info;
- /** Info about multicast groups and their members */
- mcast_info_t mcast_info;
+ /** Last time the multicast info file was checked. */
+ time_t mcast_last_check;
} plcd_ctx_t;
@@ -229,17 +190,17 @@ int plcd_send_recv_drv_mme (const plcd_ctx_t *ctx, const mme_ctx_t *request_ctx,
mme_ctx_t *confirm_ctx, mme_ctx_t *indication_ctx);
/**
- * Check if the mcast_info needs to be updated and update it if needed.
- * \param ctx the plcd context (which contains the mcast_info to check/update).
- * \return LIBSPID_TRUE if the mcast_info was updated,
- * LIBSPID_FALSE if the mcast_info was not updated.
+ * Tell whether the multicast info file was updated since last check.
+ * \param ctx The context;
+ * \return LIBSPID_TRUE, if the multicast info has been updated.
+ * LIBSPID_FALSE, if no update since last check.
*/
libspid_boolean_t plcd_mcast_info_updated (plcd_ctx_t *ctx);
/**
- * Send the mcast_info via an MME.
- * \param ctx the plcd context(which contains the mcast_info).
+ * Process the multicast info.
+ * \param ctx the plcd context.
*/
-void plcd_mcast_send_info (const plcd_ctx_t *ctx);
+void plcd_mcast_process (plcd_ctx_t *ctx);
#endif /* PLCD_H */
diff --git a/cleopatre/devkit/plcd/src/plcd_mcast.c b/cleopatre/devkit/plcd/src/plcd_mcast.c
index a612fd1868..5306dad4e4 100644
--- a/cleopatre/devkit/plcd/src/plcd_mcast.c
+++ b/cleopatre/devkit/plcd/src/plcd_mcast.c
@@ -24,6 +24,12 @@
#include "libspid.h"
#include "plcd.h"
+/* Maximum number of multicast groups */
+#define MCAST_GROUP_MAX_NB ((uint8_t)12)
+
+/* Maxium number of members in a multicast group */
+#define MCAST_MEMBER_MAX_NB ((uint8_t)1)
+
/* The mcast.info file has the following format:
* group1_mac_addr<delimiter>member1_mac_addr<delimiter>member2_mac_addr<delimiter>membern_mac_addr<delimiter>
* group2_mac_addr<delimiter>member1_mac_addr<delimiter>member2_mac_addr<delimiter>membern_mac_addr<delimiter>
@@ -55,6 +61,27 @@ typedef enum
MCAST_READ_PARSE_ERROR
} mcast_read_status_t;
+/** Multicast group member */
+typedef struct
+{
+ /** The MAC address of the member */
+ unsigned char mac_address[ETHER_ADDR_LEN];
+} mcast_member_t;
+
+/** Multicast group */
+typedef struct
+{
+ /** The MAC address of the group */
+ unsigned char mac_address[ETHER_ADDR_LEN];
+
+ /** The list of members of the group */
+ mcast_member_t members[MCAST_MEMBER_MAX_NB];
+
+ /** The number of members of the group */
+ uint8_t member_count;
+
+} mcast_group_t;
+
/**
* Tell whether the provided MAC address is a multicast address or not.
* \param mac_addr the multicast address to test.
@@ -178,149 +205,10 @@ plcd_mcast_read_groups (mcast_group_t *groups, uint8_t *group_count)
return MCAST_READ_SUCCESS;
}
-/**
- * Compare two groups and see if they are the same.
- * \param group1 first group
- * \param group2 second group
- * \return LIBSPID_TRUE if the two groups are the same,
- * LIBSPID_FALSE otherwise.
- *
- * Two groups are the same if they have the same MAC address
- * and the same members.
- */
-static libspid_boolean_t
-plcd_mcast_same_group (const mcast_group_t *group1, const mcast_group_t *group2)
-{
- if ((memcmp (group1->mac_address, group2->mac_address, ETHER_ADDR_LEN) != 0)
- || (group1->member_count != group2->member_count))
- {
- return LIBSPID_FALSE;
- }
-
- /* ASSERT: no duplicates in members of group1 or in members of group2
- * ie: group1->members is a set and group2->members is a set */
-
- unsigned int member_idx1;
- for (member_idx1 = 0; member_idx1 < group1->member_count; member_idx1++)
- {
- unsigned int member_idx2 ;
- for (member_idx2 = 0; member_idx2 < group2->member_count; member_idx2++)
- {
- if (memcmp (group1->members[member_idx1].mac_address,
- group2->members[member_idx2].mac_address,
- ETHER_ADDR_LEN) == 0)
- {
- break;
- }
- }
-
- if (member_idx2 >= group2->member_count)
- {
- /* A member from groups1 is not in groups2 */
- return LIBSPID_FALSE;
- }
- }
-
- return LIBSPID_TRUE;
-}
-
-/**
- * Compares two lists of groups to see if they are the same.
- * \param groups1 the first list of groups.
- * \param groups2 the second list of groups.
- * \param group_count the number of groups in both lists.
- * \return LIBSPID_TRUE if the lists are the same,
- * LIBSPID_FALSE otherwise.
- */
-static libspid_boolean_t
-plcd_mcast_same_groups (const mcast_group_t *groups1, const mcast_group_t *groups2, uint8_t group_count)
-{
- /* ASSERT: no duplicates in groups1 list or in groups2 list
- * ie: groups1 is a set and groups2 is a set */
-
- unsigned int grp_idx1;
- for (grp_idx1 = 0; grp_idx1 < group_count; grp_idx1++)
- {
- unsigned int grp_idx2;
- for (grp_idx2 = 0; grp_idx2 < group_count; grp_idx2++)
- {
- if (plcd_mcast_same_group (&groups1[grp_idx1], &groups2[grp_idx2]) == LIBSPID_TRUE)
- {
- break;
- }
- }
-
- if (grp_idx2 >= group_count)
- {
- /* we didn't find group1 in groups2 */
- return LIBSPID_FALSE;
- }
- }
-
- return LIBSPID_TRUE;
-}
-
-libspid_boolean_t
-plcd_mcast_info_updated (plcd_ctx_t *ctx)
-{
- struct stat file_stat;
- memset (&file_stat, 0, sizeof (struct stat));
-
- if (stat (LIBSPID_MCAST_INFO_PATH, &file_stat) == 0)
- {
- if (file_stat.st_mtime < ctx->mcast_info.last_file_check)
- {
- /* if the modification time is older than the last update
- * to the mcast info, no need to read the file */
- return LIBSPID_FALSE;
- }
- }
- else
- {
- syslog (LOG_ERR, "stat: %s", strerror (errno));
- }
-
- mcast_group_t fgroups[MCAST_GROUP_MAX_NB];
- uint8_t fgroup_count = 0;
-
- /* Record the time just _before_ reading from the file.
- * If we record the time after reading from the file, we could miss
- * an update of the file that happened during the read. */
- time_t last_file_check = time (NULL);
-
- mcast_read_status_t status = plcd_mcast_read_groups (fgroups, &fgroup_count);
-
- if ((status == MCAST_READ_SUCCESS)
- || (status == MCAST_READ_PARSE_ERROR))
- {
- /* We timestamp only if we were able to read the file.
- * We don't update ctx->mcast_info.last_file_check on MCAST_READ_ERROR,
- * because if we do, that will prevent us from reading the file again later.
- * We do want to try again later, in case the error was a one time anomaly. */
- ctx->mcast_info.last_file_check = last_file_check;
- }
-
- /* If an error occured, fgroup_count is still 0. So as a precaution,
- * the mcast_info will be cleared. This will make Cesar stop its filtering. */
-
- if ((ctx->mcast_info.group_count != fgroup_count)
- || (plcd_mcast_same_groups (ctx->mcast_info.groups, fgroups, fgroup_count) == LIBSPID_FALSE))
- {
- /* update mcast_info */
- memcpy (&ctx->mcast_info.groups, &fgroups, fgroup_count * sizeof (mcast_group_t));
- ctx->mcast_info.group_count = fgroup_count;
-
- syslog (LOG_INFO, "mcast_info updated");
- return LIBSPID_TRUE;
- }
- else
- {
- return LIBSPID_FALSE;
- }
-}
-
-void
-plcd_mcast_send_info (const plcd_ctx_t *ctx)
+static void
+plcd_mcast_send_info (plcd_ctx_t *ctx,
+ const mcast_group_t *groups,
+ unsigned int group_count)
{
syslog (LOG_INFO, __func__);
@@ -330,14 +218,20 @@ plcd_mcast_send_info (const plcd_ctx_t *ctx)
mme_error_t status;
- status = mme_init (&request_ctx, MME_TYPE_DRV_STA_SET_MCAST_LIST | MME_TYPE_REQ, mme_buffer, sizeof (mme_buffer));
+ status = mme_init (&request_ctx,
+ MME_TYPE_DRV_STA_SET_MCAST_LIST | MME_TYPE_REQ,
+ mme_buffer, sizeof (mme_buffer));
+
if (status != MME_SUCCESS)
{
syslog (LOG_ERR, "mme_init failed (%d)", status);
return;
}
- status = mme_init (&confirm_ctx, MME_TYPE_DRV_STA_SET_MCAST_LIST | MME_TYPE_CNF, mme_buffer, sizeof (mme_buffer));
+ status = mme_init (&confirm_ctx,
+ MME_TYPE_DRV_STA_SET_MCAST_LIST | MME_TYPE_CNF,
+ mme_buffer, sizeof (mme_buffer));
+
if (status != MME_SUCCESS)
{
syslog (LOG_ERR, "mme_init failed (%d)", status);
@@ -346,7 +240,7 @@ plcd_mcast_send_info (const plcd_ctx_t *ctx)
unsigned int result_length;
if (mme_put (&request_ctx,
- (void *)&ctx->mcast_info.group_count,
+ (void *)&group_count,
sizeof (uint8_t),
&result_length) != MME_SUCCESS)
{
@@ -355,9 +249,9 @@ plcd_mcast_send_info (const plcd_ctx_t *ctx)
}
uint8_t group_idx;
- for (group_idx = 0; group_idx < ctx->mcast_info.group_count; group_idx++)
+ for (group_idx = 0; group_idx < group_count; group_idx++)
{
- const mcast_group_t *group = &ctx->mcast_info.groups[group_idx];
+ const mcast_group_t *group = &groups[group_idx];
result_length = 0;
if (mme_put (&request_ctx,
@@ -414,3 +308,68 @@ plcd_mcast_send_info (const plcd_ctx_t *ctx)
syslog (LOG_INFO, "sent successfully");
}
+
+libspid_boolean_t
+plcd_mcast_info_updated (plcd_ctx_t *ctx)
+{
+ struct stat file_stat;
+ memset (&file_stat, 0, sizeof (struct stat));
+
+ if (stat (LIBSPID_MCAST_INFO_PATH, &file_stat) == 0)
+ {
+ /* >= instead of > because the precision is up to the second.
+ * If we use >, we may miss an update that happened in the same second
+ * as the last check but a few millisecondes later.
+ * e.g: last_check at 345.00 secondes and update at 345.9999 seconds.
+ * The downside is that we may process many times the same file if
+ * multiple signals arrive in the same second as the last_check.*/
+ if (file_stat.st_mtime >= ctx->mcast_last_check)
+ {
+ return LIBSPID_TRUE;
+ }
+ }
+ else
+ {
+ syslog (LOG_ERR, "stat: %s", strerror (errno));
+ }
+
+ return LIBSPID_FALSE;
+}
+
+void
+plcd_mcast_process (plcd_ctx_t *ctx)
+{
+ uint8_t group_count = 0;
+ mcast_group_t *groups = malloc (sizeof (mcast_group_t ) * MCAST_GROUP_MAX_NB);
+ if (groups != NULL)
+ {
+ /* Record the time just _before_ reading from the file.
+ * If we record the time after reading from the file, we could miss
+ * an update of the file that happened during the read. */
+ time_t last_file_check = time (NULL);
+
+ mcast_read_status_t status =
+ plcd_mcast_read_groups (groups, &group_count);
+
+ if ((status == MCAST_READ_SUCCESS)
+ || (status == MCAST_READ_PARSE_ERROR))
+ {
+ /* We timestamp only if we were able to read the file.
+ * We don't update ctx->mcast_last_check on MCAST_READ_ERROR,
+ * because if we do, that will prevent us from reading the file
+ * again later.
+ * We do want to try again later, in case the error was a one
+ * time anomaly. */
+ ctx->mcast_last_check = last_file_check;
+ }
+ }
+
+ /* If an error occured, group_count is still 0. So as a precaution,
+ * the multicast info will be cleared. This will make Cesar stop its
+ * filtering. */
+
+ /* Send the info to Cesar */
+ plcd_mcast_send_info (ctx, groups, group_count);
+
+ free (groups);
+}
diff --git a/cleopatre/devkit/plcd/src/plcd_process.c b/cleopatre/devkit/plcd/src/plcd_process.c
index e2688e76de..13a36208a7 100644
--- a/cleopatre/devkit/plcd/src/plcd_process.c
+++ b/cleopatre/devkit/plcd/src/plcd_process.c
@@ -657,6 +657,6 @@ plcd_process_signal (plcd_ctx_t *ctx)
/* mcast.info */
if (plcd_mcast_info_updated (ctx) == LIBSPID_TRUE)
{
- plcd_mcast_send_info (ctx);
+ plcd_mcast_process (ctx);
}
}