summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mercadie2011-05-05 16:55:47 +0200
committerDavid Mercadie2011-05-18 14:20:02 +0200
commitfdd874acacdf7dd167a8d228c13b01ea8a38711d (patch)
tree620a4cde5ef12d7afbe08722dc4582464d7227df
parent88ebb85bff702c4f5461e647256c7c29a7766f5a (diff)
cesar/{cl, cp/{sta/{action, mgr}, msg}}: support IGMP with mutiple members in a group, closes #2470
-rw-r--r--cesar/cl/cl.h16
-rw-r--r--cesar/cl/cl_mactotei.h33
-rw-r--r--cesar/cl/inc/context.h4
-rw-r--r--cesar/cl/inc/trace.h1
-rw-r--r--cesar/cl/src/cl.c124
-rw-r--r--cesar/cl/src/cl_mactotei.c61
-rw-r--r--cesar/cl/src/trace.c1
-rw-r--r--cesar/cl/stub/src/cl.c7
-rw-r--r--cesar/cl/stub/src/cl_mactotei.c28
-rw-r--r--cesar/cl/test/utest/src/misc.c150
-rw-r--r--cesar/cl/test/utest/src/send.c114
-rw-r--r--cesar/cl/test/utest/src/test.c5
-rw-r--r--cesar/cl/test/utest/test.h11
-rw-r--r--cesar/common/defs/igmp.h20
-rw-r--r--cesar/cp/msg/inc/msg_drv.h4
-rw-r--r--cesar/cp/msg/src/msg_drv.c8
-rw-r--r--cesar/cp/msg/test/src/msg_drv.c109
-rw-r--r--cesar/cp/sta/action/src/bridge.c5
-rw-r--r--cesar/cp/sta/action/src/drv.c30
-rw-r--r--cesar/cp/sta/action/test/utest/inc/scenario_defs.h7
-rw-r--r--cesar/cp/sta/action/test/utest/src/dataplane_stub.c37
-rw-r--r--cesar/cp/sta/action/test/utest/src/drv.c18
-rw-r--r--cesar/cp/sta/action/test/utest/src/msg_stub.c4
-rw-r--r--cesar/cp/sta/mgr/src/sta_mgr.c10
-rw-r--r--cesar/test_general/station/cco0/s2/py/sc16_igmp.py14
25 files changed, 688 insertions, 133 deletions
diff --git a/cesar/cl/cl.h b/cesar/cl/cl.h
index 1ef66e7c42..ce7831b78f 100644
--- a/cesar/cl/cl.h
+++ b/cesar/cl/cl.h
@@ -19,6 +19,7 @@
#include "mac/common/store.h"
#include "lib/utils.h"
#include "mac/sar/sar.h"
+#include "common/defs/igmp.h"
/** forward declaration. */
typedef struct cl_t cl_t;
@@ -319,6 +320,21 @@ cl_mme_buffer_add (cl_t *cl, u8 *buffer);
void
cl_data_buffer_add (cl_t *cl, u8 *buffer);
+/**
+ * Update the igmp groups based on the mactotei table.
+ * \param cl the CL context.
+ */
+void
+cl_update_igmp_groups (cl_t *ctx);
+
+/**
+ * Get the access to the igmp data in the cl context.
+ * \param cl the CL context.
+ * \return the pointer to the igmp data.
+ */
+igmp_groups_t *
+cl_get_igmp_groups (cl_t *cl);
+
END_DECLS
#endif /* CL_CL_H_ */
diff --git a/cesar/cl/cl_mactotei.h b/cesar/cl/cl_mactotei.h
index 4edd6cac90..dd103e1335 100644
--- a/cesar/cl/cl_mactotei.h
+++ b/cesar/cl/cl_mactotei.h
@@ -71,6 +71,18 @@ cl_mactotei_copy_tei_and_tag (cl_t *ctx, cl_mactotei_blk_t *table,
uint tei, uint tag);
/**
+ * Request the CL to copy all the entries from the actual MAC to TEI table
+ * corresponding to a TEI.
+ *
+ * \param ctx the CL context.
+ * \param table the new MAC to TEI table to fill.
+ * \param tei the corresponding TEI entries to copy.
+ */
+void
+cl_mactotei_copy_tei (cl_t *ctx, cl_mactotei_blk_t *table,
+ uint tei);
+
+/**
* Find a mac address in the table using a dichotomy search.
*
* \param ctx the CL context.
@@ -82,6 +94,17 @@ uint
cl_mactotei_table_find_tei_from_mac (cl_t *ctx, mac_t mac);
/**
+ * Find the tei and tag associated to a mac address in the table.
+ * \param ctx the CL context.
+ * \param mac the mac address to look for.
+ * \param tag the tag associated with the tei for this mac.
+ * \return the TEI corresponding to the mac address if the entry exists.
+ * Otherwise, it returns MAC_TEI_UNASSOCIATED.
+ */
+uint
+cl_mactotei_table_find_tei_and_tag_from_mac (cl_t *ctx, mac_t mac, uint *tag);
+
+/**
* Request the CL to use the new table and remove the old one.
*
* \param ctx the CL context.
@@ -112,6 +135,16 @@ void
cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag);
/**
+ * Copy all the entries from the current MAC to TEI table except the ones with
+ * a specific tei.
+ * \param ctx the CL context.
+ * \param table the table where to add copied entries.
+ * \param tei the matching tei.
+ */
+void
+cl_mactotei_copy_except_tei (cl_t *ctx, cl_mactotei_blk_t *table, uint tei);
+
+/**
* Cancel the creation of a table.
* \param table the table to cancel.
*
diff --git a/cesar/cl/inc/context.h b/cesar/cl/inc/context.h
index 79e48d5794..54314c5a0a 100644
--- a/cesar/cl/inc/context.h
+++ b/cesar/cl/inc/context.h
@@ -25,6 +25,7 @@
#include "cl/inc/bridge_table.h" // bridge_table_context_t
#include "cl/inc/trace.h"
+#include "common/defs/igmp.h"
/** Define the delay at the one the data inside the cl_data_send_link_t are
* considered expired. */
@@ -148,6 +149,9 @@ struct cl_t
/** Last link used on a Data send. */
cl_data_send_link_t data_send_link;
+ /** Groups for multi-unicast. */
+ igmp_groups_t groups;
+
/** Tracing system */
#if CONFIG_TRACE
/** cl Trace */
diff --git a/cesar/cl/inc/trace.h b/cesar/cl/inc/trace.h
index 484049d3c4..e312a292f6 100644
--- a/cesar/cl/inc/trace.h
+++ b/cesar/cl/inc/trace.h
@@ -43,6 +43,7 @@ enum
CL_TRACE_DATA_SEND,
CL_TRACE_DATA_SEND_DROP,
CL_TRACE_DATA_SEND_DONE,
+ CL_TRACE_DATA_SEND_MULTI_FAILED,
CL_TRACE_DATA_RECV,
CL_TRACE_DATA_BUFFER_ADD,
CL_TRACE_BRIDGE_ADD,
diff --git a/cesar/cl/src/cl.c b/cesar/cl/src/cl.c
index 9b0cc4cbcb..9d2e5200a4 100644
--- a/cesar/cl/src/cl.c
+++ b/cesar/cl/src/cl.c
@@ -464,33 +464,33 @@ cl_send_unicast (cl_t *ctx, u8 *buffer, uint length, uint tei,
* \param mme true if the message comes from the CP, false otherwise.
* \param tag the tag provided by the upper layer.
* \param arrival_time_ntb the arrival time NTB.
+ * \param group_id the group id for data multiunicast.
*/
static void
cl_send_multiunicast (cl_t *ctx, u8 *buffer, uint length, bool mme, uint tag,
- u32 arrival_time_ntb)
+ u32 arrival_time_ntb, uint group_id)
{
cl_send_t *cl_data;
uint i;
sta_t *sta;
+ mfs_tx_t *mfs;
+ bool added;
dbg_assert (ctx);
dbg_assert (buffer);
dbg_assert ((length >= ETH_PACKET_MIN_SIZE_ALLOWED)
&& (length <= ETH_PACKET_MAX_SIZE));
+ /* Allocate the buffer handler. */
+ cl_data = cl_send_init (ctx, buffer, mme);
+
if (mme)
{
- /* Allocate the buffer handler. */
- cl_data = cl_send_init (ctx, buffer, mme);
-
for ( i = MAC_TEI_STA_MIN; i < MAC_TEI_STA_NB; i++)
{
sta = mac_store_sta_get (ctx->mac_store, i);
if (sta && sta->multi_unicast_receiver)
{
- mfs_tx_t *mfs;
- bool added;
-
mfs = mac_store_mfs_add_tx (ctx->mac_store,
false /* MME */,
true /* MME */,
@@ -510,11 +510,66 @@ cl_send_multiunicast (cl_t *ctx, u8 *buffer, uint length, bool mme, uint tag,
blk_release (sta);
}
}
- slab_release (cl_data);
}
else
- /* FIXME Implement for DATA too. */
- dbg_assert_default ();
+ {
+ for (i = 0; i < ctx->groups.nb_actual_members[group_id]; i++)
+ {
+ uint lid;
+ bool bcast;
+ bool acs;
+ bool drop;
+ uint tei = ctx->groups.member_tei[group_id][i];
+ dbg_assert (MAC_TEI_IS_STA (tei));
+
+ /* Get some data from the classifier. */
+ lid = cl_classifer_get_lid (ctx, tei, tag, &bcast, &acs, &drop);
+
+ if (MAC_LID_IS_PLID (lid))
+ {
+ /* Create the MFS if it does not exits. */
+ mfs = mac_store_mfs_add_tx (ctx->mac_store, bcast, false, lid,
+ tei, &added);
+ if (added)
+ sar_mfs_add (ctx->sar, (mfs_t *)mfs);
+ }
+ else
+ {
+ /* try to get the mfs from the store. */
+ mfs = mac_store_mfs_get_tx (ctx->mac_store, bcast, false, lid,
+ tei);
+ }
+
+ if (!drop && !acs && mfs)
+ {
+ CL_TRACE (DATA_SEND, phy_date (), buffer, length,
+ mfs->common.tei, mfs->common.lid, mfs->common.bcast);
+ slab_addref (cl_data);
+ sar_msdu_add (ctx->sar, buffer, length, mfs, cl_data,
+ arrival_time_ntb);
+
+ /* update data rate informations associated to the TX
+ * from the local sta to the associated sta */
+ if (CONFIG_CL_DATA_RATE)
+ {
+ sta = mac_store_sta_get (ctx->mac_store, tei);
+ if (sta)
+ {
+ data_rate_update_info (&(sta->tx_data_rate), length);
+ blk_release (sta);
+ }
+ }
+ }
+ else
+ {
+ CL_TRACE (DATA_SEND_MULTI_FAILED, phy_date (), drop, acs,
+ mfs, tei, group_id);
+ }
+ if (mfs)
+ blk_release (mfs);
+ }
+ }
+ slab_release (cl_data);
}
/**
@@ -555,9 +610,22 @@ cl_data_send_prepare (cl_t *ctx, u8 *buffer, uint length, uint tag,
/* Get the TEI from the mactotei table. */
uint tei;
- tei = cl_mactotei_table_find_tei_from_mac (ctx, dmac);
+ uint group;
+ tei = cl_mactotei_table_find_tei_and_tag_from_mac (ctx, dmac, &group);
dbg_assert (tei != ctx->mac_config->tei);
+ if (tei == MAC_TEI_BCAST)
+ {
+ if (ctx->groups.nb_actual_members[group] > 1)
+ {
+ cl_send_multiunicast (ctx, buffer, length, 0, tag, arrival_time_ntb,
+ group);
+ return;
+ }
+ else
+ tei = ctx->groups.member_tei[group][0];
+ }
+
/* If the TEI is not found the packet is send as broadcast. */
cl_data_send_with_tei (ctx, buffer, length,
tei == MAC_TEI_UNASSOCIATED ? MAC_TEI_BCAST: tei,
@@ -663,7 +731,7 @@ cl_mme_send (cl_t *ctx, u8 *buffer, uint length, uint tei)
{
dbg_assert (ctx->mac_config->tei);
cl_send_multiunicast (ctx, buffer, length, true /* MME */, 1,
- mac_ntb());
+ mac_ntb(), 0);
}
/* the destination is not associated or associated and our station
* can or not be associated */
@@ -921,3 +989,35 @@ cl_data_send_link_clear (cl_t *ctx)
ctx->data_send_link.tag = 0;
arch_dsr_unlock ();
}
+
+igmp_groups_t*
+cl_get_igmp_groups (cl_t *ctx)
+{
+ dbg_assert (ctx);
+
+ return &ctx->groups;
+}
+
+void
+cl_update_igmp_groups (cl_t *ctx)
+{
+ dbg_assert (ctx);
+ uint g;
+ uint m;
+ for (g = 0; g < ctx->groups.nb; g++)
+ {
+ uint tei = MAC_TEI_UNASSOCIATED;
+ ctx->groups.nb_actual_members[g] = 0;
+
+ for (m = 0; m < ctx->groups.nb_total_members[g]; m++)
+ {
+ tei = cl_mactotei_table_find_tei_from_mac (
+ ctx, ctx->groups.member_mac[g][m]);
+ if (MAC_TEI_IS_STA(tei))
+ ctx->groups.member_tei[g][ctx->groups.nb_actual_members[g]++] =
+ tei;
+ }
+ if (ctx->groups.nb_actual_members[g] == 0)
+ ctx->groups.member_tei[g][0] = MAC_TEI_BCAST;
+ }
+}
diff --git a/cesar/cl/src/cl_mactotei.c b/cesar/cl/src/cl_mactotei.c
index f71a2b6465..e9043ae6b4 100644
--- a/cesar/cl/src/cl_mactotei.c
+++ b/cesar/cl/src/cl_mactotei.c
@@ -26,7 +26,7 @@ static inline u16
cl_mactotei_set_tei_tag (uint tei, uint tag)
{
/* Check parameters. */
- dbg_assert (MAC_TEI_IS_STA (tei));
+ dbg_assert (MAC_TEI_IS_STA (tei) || (tei == MAC_TEI_BCAST));
dbg_assert (tag <= 0xFF);
u16 extra_info = 0;
extra_info = tei;
@@ -81,6 +81,23 @@ cl_mactotei_copy_tei_and_tag (cl_t *ctx, cl_mactotei_blk_t *table,
}
void
+cl_mactotei_copy_tei (cl_t *ctx, cl_mactotei_blk_t *table,
+ uint tei)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+
+ cl_mactotei_table_t *table_old = ctx->mactotei;
+ /* Nothing to copy. */
+ if (table_old == NULL)
+ return;
+
+ /* Copy entries with matching TEI. */
+ mac_lookup_table_copy (table_old, table, 0xFF00,
+ cl_mactotei_set_tei_tag (tei, 0));
+}
+
+void
cl_mactotei_addr_add (cl_mactotei_blk_t *table, mac_t mac_addr,
uint tei, uint tag)
{
@@ -148,6 +165,32 @@ cl_mactotei_table_find_tei_from_mac (cl_t *ctx, mac_t mac)
return MAC_TEI_UNASSOCIATED;
}
+uint
+cl_mactotei_table_find_tei_and_tag_from_mac (cl_t *ctx, mac_t mac, uint *tag)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+
+ /* Empty MAC to TEI table? */
+ if (ctx->mactotei)
+ {
+ u16 extra_info;
+ /* Entry exist? */
+ if (mac_lookup_table_find_entry (ctx->mactotei, mac, &extra_info))
+ {
+ CL_TRACE (MACTOTEI_FIND_TEI, phy_date (), TRACE_U64 (mac), true,
+ extra_info >> 8);
+ *tag = extra_info & 0xFF;
+ return extra_info >> 8;
+ }
+ }
+
+ /* Entry does not exist. */
+ CL_TRACE (MACTOTEI_FIND_TEI, phy_date (), TRACE_U64 (mac), false,
+ MAC_TEI_UNASSOCIATED);
+ return MAC_TEI_UNASSOCIATED;
+}
+
void
cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag)
{
@@ -164,6 +207,22 @@ cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag)
}
void
+cl_mactotei_copy_except_tei (cl_t *ctx, cl_mactotei_blk_t *table, uint tei)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+
+ cl_mactotei_table_t *table_old = ctx->mactotei;
+ /* Nothing to copy. */
+ if (table_old == NULL)
+ return;
+
+ /* Copy entries with matching TEI and tag. */
+ mac_lookup_table_copy_except (
+ table_old, table, 0xFF00, cl_mactotei_set_tei_tag (tei, 0));
+}
+
+void
cl_mactotei_cancel (cl_mactotei_blk_t *table)
{
/* Release table from memory. */
diff --git a/cesar/cl/src/trace.c b/cesar/cl/src/trace.c
index d9ff1dee61..9ad0392a54 100644
--- a/cesar/cl/src/trace.c
+++ b/cesar/cl/src/trace.c
@@ -48,6 +48,7 @@ cl_trace_init (cl_t *ctx)
TRACE_EVENT (CL_TRACE_DATA_SEND, "CL_DATA_SEND buffer @ : %x, length : %d, tei : %x, lid : %x, bcast : %d", TIMESTAMP),
TRACE_EVENT (CL_TRACE_DATA_SEND_DROP, "CL_DATA_SEND_DROP authenticated : %d, buffer @ : %x, length : %d", TIMESTAMP),
TRACE_EVENT (CL_TRACE_DATA_SEND_DONE, "CL_DATA_SEND_DONE buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (CL_TRACE_DATA_SEND_MULTI_FAILED, "Multiunicast data send failed drop : %d, acs : %d, mfs : %x, dtei : %x, group : %d", TIMESTAMP),
TRACE_EVENT (CL_TRACE_DATA_RECV, "CL_DATA_RECV buffer @ : %x, destination : %m, source : %m, length : %d", TIMESTAMP),
TRACE_EVENT (CL_TRACE_DATA_BUFFER_ADD, "CL_DATA_BUFFER_ADD buffer @ : %x", TIMESTAMP),
TRACE_EVENT (CL_TRACE_BRIDGE_ADD, "Bridging MAC %m"),
diff --git a/cesar/cl/stub/src/cl.c b/cesar/cl/stub/src/cl.c
index 6ef20d4294..58b8b2fdad 100644
--- a/cesar/cl/stub/src/cl.c
+++ b/cesar/cl/stub/src/cl.c
@@ -14,6 +14,7 @@
*/
#include "common/std.h"
#include "cl/cl.h"
+#include "common/defs/igmp.h"
cl_t *
cl_init (mac_store_t *mac_store, sar_t *sar, mac_config_t *mac_config) __attribute__((weak));
@@ -126,3 +127,9 @@ cl_mme_buffer_add (cl_t *cl, u8 *buffer) {}
void
cl_data_buffer_add (cl_t *cl, u8 *buffer) {}
+
+void
+cl_update_igmp_groups (cl_t *cl)__attribute__((weak));
+void
+cl_update_igmp_groups (cl_t *cl) {}
+
diff --git a/cesar/cl/stub/src/cl_mactotei.c b/cesar/cl/stub/src/cl_mactotei.c
index 135d33430e..8b5934325a 100644
--- a/cesar/cl/stub/src/cl_mactotei.c
+++ b/cesar/cl/stub/src/cl_mactotei.c
@@ -45,6 +45,15 @@ cl_mactotei_copy_tei_and_tag (cl_t *ctx, cl_mactotei_blk_t *table,
{
}
+void
+cl_mactotei_copy_tei (cl_t *ctx, cl_mactotei_blk_t *table,
+ uint tei)
+__attribute__((weak));
+
+void
+cl_mactotei_copy_tei (cl_t *ctx, cl_mactotei_blk_t *table,
+ uint tei) {}
+
uint
cl_mactotei_table_find_tei_from_mac (cl_t *ctx, mac_t mac)
__attribute__((weak));
@@ -55,6 +64,16 @@ cl_mactotei_table_find_tei_from_mac (cl_t *ctx, mac_t mac)
return MAC_TEI_UNASSOCIATED;
}
+uint
+cl_mactotei_table_find_tei_and_tag_from_mac (cl_t *ctx, mac_t mac, uint *tag)
+ __attribute__((weak));
+
+uint
+cl_mactotei_table_find_tei_and_tag_from_mac (cl_t *ctx, mac_t mac, uint *tag)
+{
+ return MAC_TEI_UNASSOCIATED;
+}
+
void
cl_mactotei_use_table (cl_t *ctx, cl_mactotei_blk_t *table)
__attribute__((weak));
@@ -80,6 +99,15 @@ cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag)
}
void
+cl_mactotei_copy_except_tei (cl_t *ctx, cl_mactotei_blk_t *table, uint tei)
+__attribute__((weak));
+
+void
+cl_mactotei_copy_except_tei (cl_t *ctx, cl_mactotei_blk_t *table, uint tei)
+{
+}
+
+void
cl_mactotei_cancel (cl_mactotei_blk_t *table) __attribute__((weak));
void
diff --git a/cesar/cl/test/utest/src/misc.c b/cesar/cl/test/utest/src/misc.c
index f13a1af630..401d834445 100644
--- a/cesar/cl/test/utest/src/misc.c
+++ b/cesar/cl/test/utest/src/misc.c
@@ -15,6 +15,7 @@
#include "cl/test/utest/test.h"
#include "cl/cl_mactotei.h"
#include <stdio.h>
+#include "cl/inc/cl.h"
uint
cl_classifer_get_lid (cl_t *ctx, uint tei, uint tag,
@@ -108,6 +109,14 @@ cl_test_case__mactotei_test_api_copy_tag_and_tei (test_t test)
test_fail_if (tei == 0, "MAC %d not found", 1);
test_fail_if (tei != 1, "TEI %d does not correspond to MAC %d",
1, 1);
+ /* try with cl_mactotei_table_find_tei_and_tag_from_mac */
+ uint tag;
+ tei = cl_mactotei_table_find_tei_and_tag_from_mac (t.cl, 1, &tag);
+ test_fail_if (tei == 0, "MAC %d not found", 1);
+ test_fail_if (tei != 1, "TEI %d does not correspond to MAC %d",
+ 1, 1);
+ test_fail_if (tag != 1, "tag %d does not correspond to MAC %d",
+ 1, 1);
/* Entry should not exist. */
test_fail_if (cl_mactotei_table_find_tei_from_mac (t.cl, max_elements),
"Entry should not exist.");
@@ -146,10 +155,151 @@ cl_test_case__mactotei_test_api_copy_tag_and_tei (test_t test)
test_end;
}
+/**
+ * Test the function cl_update_igmp_groups.
+ * \param test Test structure.
+ */
+void
+cl_test_case__cl_update_igmp_groups (test_t test)
+{
+ uint i, j;
+ cl_mactotei_blk_t *table = cl_mactotei_new ();
+ cl_test_t t;
+ cl_test_init (&t, 0x9540);
+
+ /** Create the mactotei table with entries for members and groups. */
+ for (i = 0; i < 4 + MCAST_MEMBER_MAX_NB; i++)
+ {
+ cl_mactotei_addr_add (
+ table, MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, i),
+ i + 1, i +1);
+ }
+
+ /** Create the igmp groups. */
+ t.cl->groups.nb = 3;
+
+ t.cl->groups.group_mac[0] = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0, 0x01);
+ t.cl->groups.nb_total_members[0] = 2;
+ t.cl->groups.member_mac[0][0] = MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, 0);
+ t.cl->groups.member_mac[0][1] = MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, 1);
+
+ t.cl->groups.group_mac[1] = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 1, 0x01);
+ t.cl->groups.nb_total_members[1] = 2;
+ t.cl->groups.member_mac[1][0] = MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, 2);
+ t.cl->groups.member_mac[1][1] = MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, 3);
+
+ t.cl->groups.group_mac[2] = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 2, 0x01);
+ t.cl->groups.nb_total_members[2] = MCAST_MEMBER_MAX_NB;
+ for (i = 4; i < 4 + MCAST_MEMBER_MAX_NB; i++)
+ {
+ t.cl->groups.member_mac[2][i - 4] =
+ MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, i);
+ }
+
+ for (j = 0; j < t.cl->groups.nb; j++)
+ {
+ cl_mactotei_addr_add (
+ table, MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, j, 0x01),
+ MAC_TEI_BCAST, j);
+ }
+ cl_mactotei_use_table (t.cl, table);
+
+ test_case_begin (test, "cl_update_igmp_groups");
+ /** Create a valid tei list for each group based on the mactotei and
+ * the list of mac addresses of members of each group. */
+ test_begin (test, "create valid tei list")
+ {
+ cl_update_igmp_groups (t.cl);
+ uint tei = 1;
+
+ for (j = 0; j < t.cl->groups.nb; j++)
+ {
+ test_fail_if (t.cl->groups.nb_actual_members[j] !=
+ t.cl->groups.nb_total_members[j]);
+ for (i = 0; i < t.cl->groups.nb_actual_members[j]; i++)
+ {
+ test_fail_if (t.cl->groups.member_tei[j][i] != tei++);
+ }
+ }
+ }
+ test_end;
+ cl_mactotei_release_table (t.cl);
+
+ /** Update the tei list when the mactotei list is modified:
+ * we remove all sta excepted one for group 0, one for group 1, group 2 has
+ * no member left available. */
+ table = cl_mactotei_new ();
+ cl_mactotei_addr_add (table, MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, 1),
+ 2, 2);
+ cl_mactotei_addr_add (table, MAC_ADDRESS(0x12, 0x34, 0x56, 0x78, 0x9A, 2),
+ 3, 3);
+ cl_mactotei_use_table (t.cl, table);
+
+ test_begin (test, "update tei list")
+ {
+ cl_update_igmp_groups (t.cl);
+
+ test_fail_if (t.cl->groups.nb_actual_members[0] != 1);
+ test_fail_if (t.cl->groups.member_tei[0][0] != 2);
+
+ test_fail_if (t.cl->groups.nb_actual_members[1] != 1);
+ test_fail_if (t.cl->groups.member_tei[1][0] != 3);
+
+ test_fail_if (t.cl->groups.nb_actual_members[2] != 0);
+ test_fail_if (t.cl->groups.member_tei[2][0] != MAC_TEI_BCAST);
+ }
+ test_end;
+ cl_mactotei_release_table (t.cl);
+
+ /** Test with full groups */
+ table = cl_mactotei_new ();
+ uint tei = 1;
+ t.cl->groups.nb = MCAST_GROUP_MAX_NB;
+ for (j = 0; j < MCAST_GROUP_MAX_NB; j++)
+ {
+ t.cl->groups.group_mac[j] =
+ MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, j, 0x01);
+ t.cl->groups.nb_total_members[j] = MCAST_MEMBER_MAX_NB;
+
+ for (i = 0; i < t.cl->groups.nb_total_members[j]; i++)
+ {
+ t.cl->groups.member_mac[j][i] =
+ MAC_ADDRESS (0x12, 0x34, 0x56, 0x78, 0x9A, tei - 1);
+ cl_mactotei_addr_add (table, t.cl->groups.member_mac[j][i],
+ tei, tei);
+ tei++;
+ }
+ cl_mactotei_addr_add (table, t.cl->groups.group_mac[j], MAC_TEI_BCAST, j);
+ }
+
+ cl_mactotei_use_table (t.cl, table);
+
+ test_begin (test, "full groups")
+ {
+ cl_update_igmp_groups (t.cl);
+
+ uint tei = 1;
+ for (j = 0; j < t.cl->groups.nb; j++)
+ {
+ test_fail_if (t.cl->groups.nb_actual_members[j] !=
+ t.cl->groups.nb_total_members[j]);
+ for (i = 0; i < t.cl->groups.nb_actual_members[j]; i++)
+ {
+ test_fail_if (t.cl->groups.member_tei[j][i] != tei++);
+ }
+ }
+ }
+ test_end;
+
+ cl_mactotei_release_table (t.cl);
+ cl_test_uninit (&t);
+}
+
void
cl_test_suite_misc (test_t test)
{
test_suite_begin (test, "CL miscellaneous");
cl_test_case__classifier (test);
cl_test_case__mactotei_test_api_copy_tag_and_tei (test);
+ cl_test_case__cl_update_igmp_groups (test);
}
diff --git a/cesar/cl/test/utest/src/send.c b/cesar/cl/test/utest/src/send.c
index 30337b2cf2..48408675cf 100644
--- a/cesar/cl/test/utest/src/send.c
+++ b/cesar/cl/test/utest/src/send.c
@@ -29,9 +29,11 @@ sar_msdu_add (sar_t *ctx, u8 *buffer, u16 length,
{
sar_test_t *t = (sar_test_t*) ctx;
dbg_assert (ctx);
- t->buffer = buffer;
- t->length = length;
- t->mfs = mfs;
+ dbg_assert (t->nb <= TEST_BUFFER_MAX_NB);
+
+ t->buffer[t->nb] = buffer;
+ t->length[t->nb] = length;
+ t->mfs[t->nb] = mfs;
t->nb++;
if (user_data)
slab_release (user_data);
@@ -43,6 +45,7 @@ cl_test_cl_data_send_prepare (cl_test_t *ctx, test_t test, u8 *buffer,
cl_data_send_link_t *expected)
{
test_within(test);
+ ctx->sar.nb = 0;
cl_data_send (ctx->cl, buffer, length, tag, av_time_ntb);
test_fail_unless (ctx->cl->data_send_link.mfs == expected->mfs);
test_fail_unless (ctx->cl->data_send_link.last_update_date_ntb ==
@@ -168,6 +171,87 @@ cl_test_case__cl_data_send_prepare (test_t test)
dbg_check (mac_store_sta_remove (t.mac_store, 1));
}
test_end;
+ test_begin (test, "Multicast data.")
+ {
+ /** Prepare the groups and the mactotei table. */
+ cl_mactotei_blk_t *table = cl_mactotei_new ();
+ for (j = 0; j < MCAST_GROUP_MAX_NB; j++)
+ {
+ t.cl->groups.group_mac[j] =
+ MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, j, 0x01);
+ t.cl->groups.nb_actual_members[j] = j % (MCAST_MEMBER_MAX_NB + 1);
+ t.cl->groups.member_tei[j][0] = MAC_TEI_UNASSOCIATED;
+
+ for (i = 0; i < t.cl->groups.nb_actual_members[j]; i++)
+ {
+ t.cl->groups.member_tei[j][i] = 1 + j*MCAST_MEMBER_MAX_NB + i;
+ }
+
+ cl_mactotei_addr_add (table, t.cl->groups.group_mac[j],
+ MAC_TEI_BCAST, j);
+ }
+ cl_mactotei_use_table (t.cl, table);
+ t.cl->groups.nb = MCAST_GROUP_MAX_NB;
+
+ for (j = 0; j < MCAST_GROUP_MAX_NB; j++)
+ {
+ cl_test_prepare_buffer (
+ &t, buffer, length, MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, j, 0x01),
+ 0);
+
+ /** Send the multicast message */
+ t.sar.nb = 0;
+ cl_data_send (t.cl, buffer, length, 0, start_time_ntb);
+
+ /** Check mfs have been updated. */
+ bool bcast;
+ bool acs;
+ bool drop;
+ mfs_tx_t *mfs_ref;
+
+ if (t.cl->groups.nb_actual_members[j] == 0)
+ {
+ test_fail_unless (t.sar.nb == 1);
+
+ uint tei = MAC_TEI_BCAST;
+ uint lid = cl_classifer_get_lid (t.cl, tei, 0, &bcast, &acs, &drop);
+ mfs_ref = mac_store_mfs_get_tx (t.cl->mac_store, bcast, false, lid,
+ tei);
+
+ test_fail_unless (mfs_ref == t.sar.mfs[0]);
+ test_fail_unless (buffer == t.sar.buffer[0]);
+ test_fail_unless (mfs_ref->common.tei == tei);
+ test_fail_unless (mfs_ref->common.tei == tei);
+ test_fail_unless (bcast == true);
+
+ mac_store_mfs_remove (t.mac_store, PARENT_OF (mfs_t, tx, mfs_ref));
+ blk_release (mfs_ref);
+ }
+ else
+ {
+ test_fail_unless (t.sar.nb == t.cl->groups.nb_actual_members[j]);
+
+ for (i = 0; i < t.cl->groups.nb_actual_members[j]; i++)
+ {
+ uint tei = 1 + j*MCAST_MEMBER_MAX_NB + i;
+ uint lid = cl_classifer_get_lid (t.cl, tei, 0, &bcast, &acs, &drop);
+ mfs_ref = mac_store_mfs_get_tx (t.cl->mac_store, bcast, false, lid,
+ tei);
+
+ test_fail_unless (mfs_ref == t.sar.mfs[i]);
+ test_fail_unless (buffer == t.sar.buffer[i]);
+ test_fail_unless (mfs_ref->common.tei == tei);
+ test_fail_unless (bcast == false);
+
+ mac_store_mfs_remove (t.mac_store, PARENT_OF (mfs_t, tx, mfs_ref));
+ blk_release (mfs_ref);
+ dbg_check (mac_store_sta_remove (t.mac_store, tei));
+ }
+ }
+ }
+ cl_mactotei_release_table (t.cl);
+ }
+ test_end;
cl_test_uninit (&t);
}
@@ -245,9 +329,9 @@ cl_test_case__send_mme (test_t test)
cl_mme_send (t.cl, buffer, length, i + 1);
/* Check data. */
test_fail_unless (t.sar.nb == 1);
- test_fail_unless (t.sar.buffer == buffer);
+ test_fail_unless (t.sar.buffer[0] == buffer);
mac_store_mfs_remove (t.mac_store,
- PARENT_OF (mfs_t, tx, t.sar.mfs));
+ PARENT_OF (mfs_t, tx, t.sar.mfs[0]));
}
}
test_end;
@@ -270,11 +354,11 @@ cl_test_case__send_mme (test_t test)
cl_mme_send (t.cl, buffer, length, i + 1);
/* Check data. */
test_fail_unless (t.sar.nb == 1);
- test_fail_unless (t.sar.buffer == buffer);
- test_fail_unless (t.sar.mfs != NULL);
- test_fail_unless (t.sar.mfs->common.tei == i + 1);
- test_fail_unless (t.sar.mfs->common.mme);
- test_fail_unless (t.sar.mfs->common.bcast == false);
+ test_fail_unless (t.sar.buffer[0] == buffer);
+ test_fail_unless (t.sar.mfs[0] != NULL);
+ test_fail_unless (t.sar.mfs[0]->common.tei == i + 1);
+ test_fail_unless (t.sar.mfs[0]->common.mme);
+ test_fail_unless (t.sar.mfs[0]->common.bcast == false);
}
}
test_end;
@@ -285,7 +369,7 @@ cl_test_case__send_mme (test_t test)
cl_mme_send (t.cl, buffer, length, MAC_TEI_MULTI_UNICAST);
/* Check data. */
test_fail_unless (t.sar.nb == 2);
- test_fail_unless (t.sar.buffer == buffer);
+ test_fail_unless (t.sar.buffer[0] == buffer);
}
test_end;
test_begin (test, "Broadcast")
@@ -300,10 +384,10 @@ cl_test_case__send_mme (test_t test)
cl_mme_send (t.cl, buffer, length, MAC_TEI_BCAST);
/* Check data. */
test_fail_unless (t.sar.nb == 1);
- test_fail_unless (t.sar.buffer == buffer);
- test_fail_unless (t.sar.mfs->common.mme);
- test_fail_unless (t.sar.mfs->common.bcast);
- test_fail_unless (t.sar.mfs->common.tei == MAC_TEI_BCAST);
+ test_fail_unless (t.sar.buffer[0] == buffer);
+ test_fail_unless (t.sar.mfs[0]->common.mme);
+ test_fail_unless (t.sar.mfs[0]->common.bcast);
+ test_fail_unless (t.sar.mfs[0]->common.tei == MAC_TEI_BCAST);
/* Remove the MFS broadcast. */
mac_store_mfs_remove (t.mac_store, PARENT_OF (mfs_t, tx, bcast));
blk_release (bcast);
diff --git a/cesar/cl/test/utest/src/test.c b/cesar/cl/test/utest/src/test.c
index 81a41b02c2..57df690e01 100644
--- a/cesar/cl/test/utest/src/test.c
+++ b/cesar/cl/test/utest/src/test.c
@@ -57,6 +57,10 @@ cl_trace_buffer_dbg_dump_callback (void *user, const char *text,
return 0;
}
+static void
+cl_data_send_done_cb (void *user, u8 *buffer)
+{
+}
void
cl_test_init (cl_test_t *ctx, u32 seed)
@@ -72,6 +76,7 @@ cl_test_init (cl_test_t *ctx, u32 seed)
cl_mme_init_buffer_add_cb (ctx->cl, cl_test_buffer_ul_add, INVALID_PTR);
cl_mme_init_ul_as_data (ctx->cl, cl_test_mme_ul_send_done_cb,
INVALID_PTR);
+ cl_data_send_done_init (ctx->cl, cl_data_send_done_cb, ctx);
cl_mme_recv_init (ctx->cl, cl_test_init_mme_recv_cp, &ctx->pwl_recv);
cl_data_recv_init (ctx->cl, cl_test_init_data_recv, &ctx->pwl_recv);
lib_rnd_init (&ctx->rnd, seed);
diff --git a/cesar/cl/test/utest/test.h b/cesar/cl/test/utest/test.h
index ff4783053c..6e444d0faa 100644
--- a/cesar/cl/test/utest/test.h
+++ b/cesar/cl/test/utest/test.h
@@ -15,16 +15,19 @@
#include "cl/cl.h"
#include "lib/rnd.h"
+
+#define TEST_BUFFER_MAX_NB 4
+
struct sar_test_t
{
/** buffer received. */
- u8 *buffer;
+ u8 *buffer[TEST_BUFFER_MAX_NB];
/** MFS used for TX. */
- mfs_tx_t *mfs;
+ mfs_tx_t *mfs[TEST_BUFFER_MAX_NB];
/** Data length. */
- uint length;
+ uint length[TEST_BUFFER_MAX_NB];
/** User data. */
- void *ud;
+ void *ud[MCAST_MEMBER_MAX_NB];
/** Number of calls. */
uint nb;
};
diff --git a/cesar/common/defs/igmp.h b/cesar/common/defs/igmp.h
index fd81bc8132..c83d772d93 100644
--- a/cesar/common/defs/igmp.h
+++ b/cesar/common/defs/igmp.h
@@ -18,9 +18,27 @@
#define MCAST_GROUP_MAX_NB 12
/** Max number of members. */
-#define MCAST_MEMBER_MAX_NB 1
+#define MCAST_MEMBER_MAX_NB 4
/** Max number of sources. */
#define MCAST_SOURCE_MAX_NB 32
+/** Keeps all data about all igmp groups. */
+struct igmp_groups_t
+{
+ /** Number of igmp groups. */
+ uint nb;
+ /** number of actual member stations in the group. */
+ uint nb_actual_members[MCAST_GROUP_MAX_NB];
+ /** Total number of member stations in the group. */
+ uint nb_total_members[MCAST_GROUP_MAX_NB];
+ /** Mac address of the group. */
+ mac_t group_mac[MCAST_GROUP_MAX_NB];
+ /** mac of all the stations of the group. */
+ mac_t member_mac[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+ /** tei of the actual stations of the group. */
+ uint member_tei[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+};
+typedef struct igmp_groups_t igmp_groups_t;
+
#endif /* common_defs_igmp_h */
diff --git a/cesar/cp/msg/inc/msg_drv.h b/cesar/cp/msg/inc/msg_drv.h
index faffaaac08..a15a98c6e4 100644
--- a/cesar/cp/msg/inc/msg_drv.h
+++ b/cesar/cp/msg/inc/msg_drv.h
@@ -337,8 +337,8 @@ cp_msg_drv_sta_set_avln_hfid_ind_send (cp_t *ctx, cp_mme_peer_t *peer,
*/
bool
cp_msg_drv_mcast_set_list_req_receive (
- cp_t *ctx, cp_mme_rx_t *mme, int *nb_groups,
- mac_t groups[MCAST_GROUP_MAX_NB], int nb_members[MCAST_GROUP_MAX_NB],
+ cp_t *ctx, cp_mme_rx_t *mme, uint *nb_groups,
+ mac_t groups[MCAST_GROUP_MAX_NB], uint nb_members[MCAST_GROUP_MAX_NB],
mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB]);
END_DECLS
diff --git a/cesar/cp/msg/src/msg_drv.c b/cesar/cp/msg/src/msg_drv.c
index 8920772e37..98db473794 100644
--- a/cesar/cp/msg/src/msg_drv.c
+++ b/cesar/cp/msg/src/msg_drv.c
@@ -663,8 +663,8 @@ cp_msg_drv_sta_set_avln_hfid_ind_send (cp_t *ctx, cp_mme_peer_t *peer,
bool
cp_msg_drv_mcast_set_list_req_receive (
- cp_t *ctx, cp_mme_rx_t *mme, int *nb_groups,
- mac_t groups[MCAST_GROUP_MAX_NB], int nb_members[MCAST_GROUP_MAX_NB],
+ cp_t *ctx, cp_mme_rx_t *mme, uint *nb_groups,
+ mac_t groups[MCAST_GROUP_MAX_NB], uint nb_members[MCAST_GROUP_MAX_NB],
mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB])
{
/* Check parameters. */
@@ -681,7 +681,7 @@ cp_msg_drv_mcast_set_list_req_receive (
if (*nb_groups > MCAST_GROUP_MAX_NB)
return false;
- int group;
+ uint group;
for (group = 0; group < *nb_groups; group++)
{
groups[group] = bitstream_read_large (&mme->bitstream, 48);
@@ -694,7 +694,7 @@ cp_msg_drv_mcast_set_list_req_receive (
(nb_members[group] == 0))
return false;
- int member;
+ uint member;
for (member = 0; member < nb_members[group]; member++)
{
members[group][member] =
diff --git a/cesar/cp/msg/test/src/msg_drv.c b/cesar/cp/msg/test/src/msg_drv.c
index 1340c7c6af..41920140ba 100644
--- a/cesar/cp/msg/test/src/msg_drv.c
+++ b/cesar/cp/msg/test/src/msg_drv.c
@@ -878,23 +878,19 @@ test_case_drv_mcast_set_list (test_t test)
cp_mme_rx_t mme;
cp_t cp;
- int nb_groups;
- mac_t groups[MCAST_GROUP_MAX_NB];
- int nb_members[MCAST_GROUP_MAX_NB];
- mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+ igmp_groups_t groups;
+ igmp_groups_t groups_ref;
/* Create the groups and members. */
- mac_t groups_ref[MCAST_GROUP_MAX_NB];
- mac_t members_ref[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
- u8 group;
- u8 member;
- for (group = 0; group < MCAST_GROUP_MAX_NB; group++)
+ uint g;
+ uint m;
+ for (g = 0; g < MCAST_GROUP_MAX_NB; g++)
{
- groups_ref[group] = MAC_ADDRESS(0x01, 0x00, 0x5E, group, 0x00, 0x00);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ groups_ref.group_mac[g] = MAC_ADDRESS(0x01, 0x00, 0x5E, g, 0x00, 0x00);
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
- members_ref[group][member] =
- MAC_ADDRESS(0x10, 0x22, 0x33, 0x44, group, member);
+ groups_ref.member_mac[g][m] =
+ MAC_ADDRESS(0x10, 0x22, 0x33, 0x44, g, m);
}
}
@@ -906,35 +902,35 @@ test_case_drv_mcast_set_list (test_t test)
/* Fill the message */
bitstream_write (&mme.bitstream, MCAST_GROUP_MAX_NB, 8);
- for (group = 0; group < MCAST_GROUP_MAX_NB; group++)
+ for (g = 0; g < MCAST_GROUP_MAX_NB; g++)
{
- bitstream_write_large (&mme.bitstream, groups_ref[group], 48);
+ bitstream_write_large (&mme.bitstream, groups_ref.group_mac[g], 48);
bitstream_write (&mme.bitstream, MCAST_MEMBER_MAX_NB, 8);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
bitstream_write_large (&mme.bitstream,
- members_ref[group][member], 48);
+ groups_ref.member_mac[g][m], 48);
}
}
uint bits = bitstream_write_finalise (&mme.bitstream);
bitstream_init (&mme.bitstream, buffer, bits / 8, BITSTREAM_READ);
- test_fail_unless (cp_msg_drv_mcast_set_list_req_receive(&cp, &mme,
- &nb_groups, groups, nb_members, members));
+ test_fail_unless (cp_msg_drv_mcast_set_list_req_receive (
+ &cp, &mme, &groups.nb, groups.group_mac,
+ groups.nb_total_members, groups.member_mac));
- test_fail_unless (nb_groups == MCAST_GROUP_MAX_NB);
- for (group = 0; group < nb_groups; group++)
+ test_fail_unless (groups.nb == MCAST_GROUP_MAX_NB);
+ for (g = 0; g < groups.nb; g++)
{
- test_fail_unless (groups[group] == groups_ref[group]);
- test_fail_unless (nb_members[group] == MCAST_MEMBER_MAX_NB);
+ test_fail_unless (groups.group_mac[g] == groups_ref.group_mac[g]);
+ test_fail_unless (groups.nb_total_members[g] == MCAST_MEMBER_MAX_NB);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
- test_fail_unless (members[group][member] ==
- members_ref[group][member]);
+ test_fail_unless (groups.member_mac[g][m] ==
+ groups_ref.member_mac[g][m]);
}
}
-
} test_end;
test_begin (test, "REQ, zero groups and members")
@@ -948,10 +944,11 @@ test_case_drv_mcast_set_list (test_t test)
uint bits = bitstream_write_finalise (&mme.bitstream);
bitstream_init (&mme.bitstream, buffer, bits / 8, BITSTREAM_READ);
- test_fail_unless (cp_msg_drv_mcast_set_list_req_receive(&cp, &mme,
- &nb_groups, groups, nb_members, members));
+ test_fail_unless (cp_msg_drv_mcast_set_list_req_receive (
+ &cp, &mme, &groups.nb, groups.group_mac,
+ groups.nb_total_members, groups.member_mac));
- test_fail_unless (nb_groups == 0);
+ test_fail_unless (groups.nb == 0);
} test_end;
test_begin (test, "REQ, invalid group")
@@ -962,23 +959,24 @@ test_case_drv_mcast_set_list (test_t test)
/* Fill the message */
bitstream_write (&mme.bitstream, MCAST_GROUP_MAX_NB, 8);
- for (group = 0; group < MCAST_GROUP_MAX_NB; group++)
+ for (g = 0; g < MCAST_GROUP_MAX_NB; g++)
{
bitstream_write_large (
&mme.bitstream,
- MAC_ADDRESS(0x01, 0x00, 0x5F, group, 0x00, 0x00), 48);
+ MAC_ADDRESS(0x01, 0x00, 0x5F, g, 0x00, 0x00), 48);
bitstream_write (&mme.bitstream, MCAST_MEMBER_MAX_NB, 8);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
bitstream_write_large (&mme.bitstream,
- members_ref[group][member], 48);
+ groups_ref.member_mac[g][m], 48);
}
}
uint bits = bitstream_write_finalise (&mme.bitstream);
bitstream_init (&mme.bitstream, buffer, bits / 8, BITSTREAM_READ);
- test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive(&cp, &mme,
- &nb_groups, groups, nb_members, members));
+ test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive (
+ &cp, &mme, &groups.nb, groups.group_mac,
+ groups.nb_total_members, groups.member_mac));
} test_end;
test_begin (test, "REQ, invalid groups number")
@@ -989,21 +987,22 @@ test_case_drv_mcast_set_list (test_t test)
/* Fill the message */
bitstream_write (&mme.bitstream, MCAST_GROUP_MAX_NB+1, 8);
- for (group = 0; group < MCAST_GROUP_MAX_NB; group++)
+ for (g = 0; g < MCAST_GROUP_MAX_NB; g++)
{
- bitstream_write_large (&mme.bitstream, groups_ref[group], 48);
+ bitstream_write_large (&mme.bitstream, groups_ref.group_mac[g], 48);
bitstream_write (&mme.bitstream, MCAST_MEMBER_MAX_NB, 8);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
bitstream_write_large (&mme.bitstream,
- members_ref[group][member], 48);
+ groups_ref.member_mac[g][m], 48);
}
}
uint bits = bitstream_write_finalise (&mme.bitstream);
bitstream_init (&mme.bitstream, buffer, bits / 8, BITSTREAM_READ);
- test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive(&cp, &mme,
- &nb_groups, groups, nb_members, members));
+ test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive (
+ &cp, &mme, &groups.nb, groups.group_mac,
+ groups.nb_total_members, groups.member_mac));
} test_end;
test_begin (test, "REQ, invalid members number")
@@ -1014,21 +1013,22 @@ test_case_drv_mcast_set_list (test_t test)
/* Fill the message */
bitstream_write (&mme.bitstream, MCAST_GROUP_MAX_NB, 8);
- for (group = 0; group < MCAST_GROUP_MAX_NB; group++)
+ for (g = 0; g < MCAST_GROUP_MAX_NB; g++)
{
- bitstream_write_large (&mme.bitstream, groups_ref[group], 48);
+ bitstream_write_large (&mme.bitstream, groups_ref.group_mac[g], 48);
bitstream_write (&mme.bitstream, MCAST_MEMBER_MAX_NB+1, 8);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
bitstream_write_large (&mme.bitstream,
- members_ref[group][member], 48);
+ groups_ref.member_mac[g][m], 48);
}
}
uint bits = bitstream_write_finalise (&mme.bitstream);
bitstream_init (&mme.bitstream, buffer, bits / 8, BITSTREAM_READ);
- test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive(&cp, &mme,
- &nb_groups, groups, nb_members, members));
+ test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive (
+ &cp, &mme, &groups.nb, groups.group_mac,
+ groups.nb_total_members, groups.member_mac));
} test_end;
test_begin (test, "REQ, null members number")
@@ -1039,21 +1039,22 @@ test_case_drv_mcast_set_list (test_t test)
/* Fill the message */
bitstream_write (&mme.bitstream, MCAST_GROUP_MAX_NB, 8);
- for (group = 0; group < MCAST_GROUP_MAX_NB; group++)
+ for (g = 0; g < MCAST_GROUP_MAX_NB; g++)
{
- bitstream_write_large (&mme.bitstream, groups_ref[group], 48);
+ bitstream_write_large (&mme.bitstream, groups_ref.group_mac[g], 48);
bitstream_write (&mme.bitstream, 0, 8);
- for (member = 0; member < MCAST_MEMBER_MAX_NB; member++)
+ for (m = 0; m < MCAST_MEMBER_MAX_NB; m++)
{
bitstream_write_large (&mme.bitstream,
- members_ref[group][member], 48);
+ groups_ref.member_mac[g][m], 48);
}
}
uint bits = bitstream_write_finalise (&mme.bitstream);
bitstream_init (&mme.bitstream, buffer, bits / 8, BITSTREAM_READ);
- test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive(&cp, &mme,
- &nb_groups, groups, nb_members, members));
+ test_fail_unless (!cp_msg_drv_mcast_set_list_req_receive (
+ &cp, &mme, &groups.nb, groups.group_mac,
+ groups.nb_total_members, groups.member_mac));
} test_end;
}
diff --git a/cesar/cp/sta/action/src/bridge.c b/cesar/cp/sta/action/src/bridge.c
index cef13c4d29..2d27454ee3 100644
--- a/cesar/cp/sta/action/src/bridge.c
+++ b/cesar/cp/sta/action/src/bridge.c
@@ -99,6 +99,10 @@ cp_sta_action_process_cm_brg_info_cnf (cp_t *ctx, cp_mme_rx_t *mme)
cl_mactotei_blk_t *new_table = cl_mactotei_new ();
/* Copy entries except the old ones. */
cl_mactotei_copy_except_tag (ctx->cl, new_table, mme->peer.tei);
+ /* Copy also the multicast group if exist */
+ cl_mactotei_copy_tei_and_tag (ctx->cl, new_table, MAC_TEI_BCAST,
+ mme->peer.tei);
+
/* Add new entries. */
uint count;
mac_t bda;
@@ -127,6 +131,7 @@ cp_sta_action_process_cm_brg_info_cnf (cp_t *ctx, cp_mme_rx_t *mme)
{
/* Use new MAC to TEI table. */
cl_mactotei_use_table (ctx->cl, new_table);
+ cl_update_igmp_groups (ctx->cl);
}
}
/* End MME decoding if there are no error. */
diff --git a/cesar/cp/sta/action/src/drv.c b/cesar/cp/sta/action/src/drv.c
index 837399018d..58a0984931 100644
--- a/cesar/cp/sta/action/src/drv.c
+++ b/cesar/cp/sta/action/src/drv.c
@@ -550,35 +550,29 @@ cp_sta_action_drv__drv_mcast_set_list_req (cp_t *ctx, cp_mme_rx_t *mme)
dbg_assert (mme);
cp_msg_drv_result_t result = CP_MSG_DRV_RESULT_SUCCESS;
+ igmp_groups_t *igmp_groups = NULL;
- mac_t groups[MCAST_GROUP_MAX_NB];
- int nb_groups;
- int nb_members[MCAST_GROUP_MAX_NB];
- mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+ igmp_groups = cl_get_igmp_groups (ctx->cl);
- if (cp_msg_drv_mcast_set_list_req_receive (ctx, mme, &nb_groups, groups,
- nb_members, members))
+ if (cp_msg_drv_mcast_set_list_req_receive (ctx, mme, &igmp_groups->nb,
+ igmp_groups->group_mac,
+ igmp_groups->nb_total_members,
+ igmp_groups->member_mac))
{
/* Create a new table. */
cl_mactotei_blk_t *new_table = cl_mactotei_new ();
/* Copy entries except the groups entries. */
- cl_mactotei_copy_except_tag (ctx->cl, new_table, MAC_TEI_BCAST);
+ cl_mactotei_copy_except_tei (ctx->cl, new_table, MAC_TEI_BCAST);
/* Add new entries. */
- int group;
- for (group = 0; group < nb_groups; group++)
+ uint g;
+ for (g = 0; g < igmp_groups->nb; g++)
{
- dbg_assert (nb_members[group] == 1);
- /* Get the tei from the mactotei table. */
- cp_tei_t tei = cl_mactotei_table_find_tei_from_mac (
- ctx->cl, members[group][0]);
-
- /* Add bridged destination address. */
- if (MAC_TEI_IS_STA(tei))
- cl_mactotei_addr_add (new_table, groups[group], tei,
- MAC_TEI_BCAST);
+ cl_mactotei_addr_add (new_table, igmp_groups->group_mac[g],
+ MAC_TEI_BCAST, g);
}
/* Use new MAC to TEI table. */
cl_mactotei_use_table (ctx->cl, new_table);
+ cl_update_igmp_groups (ctx->cl);
}
else
result = CP_MSG_DRV_RESULT_FAILURE;
diff --git a/cesar/cp/sta/action/test/utest/inc/scenario_defs.h b/cesar/cp/sta/action/test/utest/inc/scenario_defs.h
index ce48e91e05..26e11b62e2 100644
--- a/cesar/cp/sta/action/test/utest/inc/scenario_defs.h
+++ b/cesar/cp/sta/action/test/utest/inc/scenario_defs.h
@@ -449,9 +449,12 @@ __0 (whoru_timeout_process)
\
cl_mactotei_new, \
cl_mactotei_copy_except_tag, \
+ cl_mactotei_copy_except_tei, \
cl_mactotei_addr_add, \
cl_mactotei_use_table, \
cl_mactotei_cancel, \
+ cl_get_igmp_groups, \
+ cl_update_igmp_groups, \
\
cp_msg_cm_brg_info_cnf_receive_begin, \
cp_msg_cm_brg_info_cnf_receive, \
@@ -854,8 +857,10 @@ __e (cl_mactotei_use_table)
__e (cl_mactotei_cancel)
__e (cl_mactotei_new)
__e (cl_mactotei_copy_except_tag)
+__e (cl_mactotei_copy_except_tei)
__e (cp_sta_own_data_set_nid, cp_nid_t nid)
-
+__e (cl_get_igmp_groups, igmp_groups_t *groups)
+__e (cl_update_igmp_groups)
#undef __e
#undef __er
diff --git a/cesar/cp/sta/action/test/utest/src/dataplane_stub.c b/cesar/cp/sta/action/test/utest/src/dataplane_stub.c
index 237827bc54..7ae91e0334 100644
--- a/cesar/cp/sta/action/test/utest/src/dataplane_stub.c
+++ b/cesar/cp/sta/action/test/utest/src/dataplane_stub.c
@@ -27,14 +27,7 @@ cl_mactotei_new (void)
scenario_event (cl_mactotei_new);
return INVALID_PTR;
}
-/*
-void
-cl_mactotei_addr_add (cl_mactotei_blk_t *table, mac_t mac_addr,
- uint tei, uint tag)
-{
- scenario_event (cl_mactotei_addr_add);
-}
-*/
+
void
cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag)
{
@@ -45,6 +38,16 @@ cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag)
scenario_event (cl_mactotei_copy_except_tag);
}
+void
+cl_mactotei_copy_except_tei (cl_t *ctx, cl_mactotei_blk_t *table, uint tei)
+{
+ if (!scenario.current
+ || (scenario.current->event_id !=
+ SCENARIO_EVENT_cl_mactotei_copy_except_tei))
+ return; /* Be less strict. */
+ scenario_event (cl_mactotei_copy_except_tei);
+}
+
uint
cl_mactotei_table_find_tei_from_mac (cl_t *ctx, mac_t mac)
{
@@ -87,6 +90,24 @@ cl_mactotei_cancel (cl_mactotei_blk_t *table)
scenario_event (cl_mactotei_cancel);
}
+igmp_groups_t *
+cl_get_igmp_groups (cl_t *ctx)
+{
+ scenario_event (cl_get_igmp_groups, param);
+
+ return param->groups;
+}
+
+void
+cl_update_igmp_groups (cl_t *ctx)
+{
+ if (!scenario.current
+ || (scenario.current->event_id != SCENARIO_EVENT_cl_update_igmp_groups))
+ return; /* Be less strict. */
+
+ scenario_event (cl_update_igmp_groups);
+}
+
void
sar_activate (sar_t *ctx, bool flag)
{
diff --git a/cesar/cp/sta/action/test/utest/src/drv.c b/cesar/cp/sta/action/test/utest/src/drv.c
index e126f58fb2..8bcbc31a9f 100644
--- a/cesar/cp/sta/action/test/utest/src/drv.c
+++ b/cesar/cp/sta/action/test/utest/src/drv.c
@@ -731,6 +731,8 @@ drv_mcast_test_case (test_t t)
.cp = &ctx.cp,
};
+ igmp_groups_t igmp_groups;
+
test_case_begin (t, "igmp");
test_begin (t, "set")
{
@@ -750,6 +752,8 @@ drv_mcast_test_case (test_t t)
/* Set multicast set list. */
scenario_entry_t entries[] = {
SCENARIO_ACTION (drv__drv_mcast_set_list_req, .peer = peer),
+ SCENARIO_EVENT (cl_get_igmp_groups,
+ .groups = &igmp_groups),
SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
.ok = true,
.nb_groups = nb_groups,
@@ -757,12 +761,13 @@ drv_mcast_test_case (test_t t)
.nb_members = nb_members,
.members = (mac_t*)members),
SCENARIO_EVENT (cl_mactotei_new),
- SCENARIO_EVENT (cl_mactotei_copy_except_tag),
+ SCENARIO_EVENT (cl_mactotei_copy_except_tei),
SCENARIO_EVENT (cl_mactotei_addr_add, .mac = groups[0],
- .tag = MAC_TEI_BCAST),
+ .tag = 0),
SCENARIO_EVENT (cl_mactotei_addr_add, .mac = groups[1],
- .tag = MAC_TEI_BCAST),
+ .tag = 1),
SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_EVENT (cl_update_igmp_groups),
SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
.peer = peer,
.mmtype = DRV_MCAST_SET_LIST_CNF,
@@ -785,13 +790,16 @@ drv_mcast_test_case (test_t t)
/* Set multicast set list. */
scenario_entry_t entries[] = {
SCENARIO_ACTION (drv__drv_mcast_set_list_req, .peer = peer),
+ SCENARIO_EVENT (cl_get_igmp_groups,
+ .groups = &igmp_groups),
SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
.ok = true, .nb_groups = nb_groups,
.groups = groups, .nb_members = nb_members,
.members = (mac_t*)members),
SCENARIO_EVENT (cl_mactotei_new),
- SCENARIO_EVENT (cl_mactotei_copy_except_tag),
+ SCENARIO_EVENT (cl_mactotei_copy_except_tei),
SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_EVENT (cl_update_igmp_groups),
SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
.peer = peer,
.mmtype = DRV_MCAST_SET_LIST_CNF,
@@ -812,6 +820,8 @@ drv_mcast_test_case (test_t t)
/* Set multicast set list. */
scenario_entry_t entries[] = {
SCENARIO_ACTION (drv__drv_mcast_set_list_req, .peer = peer),
+ SCENARIO_EVENT (cl_get_igmp_groups,
+ .groups = &igmp_groups),
SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
.ok = false, .nb_groups = nb_groups,
.groups = groups, .nb_members = nb_members,
diff --git a/cesar/cp/sta/action/test/utest/src/msg_stub.c b/cesar/cp/sta/action/test/utest/src/msg_stub.c
index 41593791f7..38b1c6381b 100644
--- a/cesar/cp/sta/action/test/utest/src/msg_stub.c
+++ b/cesar/cp/sta/action/test/utest/src/msg_stub.c
@@ -503,9 +503,9 @@ __msd (cp_msg_drv_sta_status_ind_send, cp_msg_drv_sta_status_t,
__mr (cp_msg_drv_sta_set_config_req_receive,
(char *, config, string))
__mr (cp_msg_drv_mcast_set_list_req_receive,
- (int, nb_groups, assign),
+ (uint, nb_groups, assign),
(mac_t, groups, array, [MCAST_GROUP_MAX_NB]),
- (int, nb_members, array, [MCAST_GROUP_MAX_NB]),
+ (uint, nb_members, array, [MCAST_GROUP_MAX_NB]),
(mac_t, members, array, [MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB]))
__mr (cp_msg_cm_brg_info_cnf_receive_begin,
diff --git a/cesar/cp/sta/mgr/src/sta_mgr.c b/cesar/cp/sta/mgr/src/sta_mgr.c
index 241eaea5a2..d25d781a9e 100644
--- a/cesar/cp/sta/mgr/src/sta_mgr.c
+++ b/cesar/cp/sta/mgr/src/sta_mgr.c
@@ -734,7 +734,9 @@ cp_sta_mgr_sta_remove (cp_t *ctx, cp_sta_t * station)
if ((sta->net == ctx->sta_mgr.our_avln)
&& (MAC_TEI_IS_STA (sta->tei)))
+ {
sar_sta_remove (ctx->sar, sta->tei);
+ }
cp_sta_mgr_sta_remove_common (ctx, station);
@@ -866,17 +868,17 @@ cp_sta_mgr_commit_to_dataplane (cp_t *ctx)
// Copy all the bridge table from the previous list.
cl_mactotei_copy_tei_and_tag (ctx->cl, mactotei, sta_private->tei,
sta_private->tei);
- // Copy all the groups list table from the previous list.
- cl_mactotei_copy_tei_and_tag (ctx->cl, mactotei, sta_private->tei,
- MAC_TEI_BCAST);
// Add the current station.
cl_mactotei_addr_add (mactotei, sta_private->mac_address,
sta_private->tei, MAC_TEI_UNASSOCIATED);
-
}
+ // Copy all the groups list table from the previous list.
+ cl_mactotei_copy_tei (ctx->cl, mactotei, MAC_TEI_BCAST);
+
// Request the CL to use the table.
cl_mactotei_use_table (ctx->cl, mactotei);
+ cl_update_igmp_groups (ctx->cl);
}
}
diff --git a/cesar/test_general/station/cco0/s2/py/sc16_igmp.py b/cesar/test_general/station/cco0/s2/py/sc16_igmp.py
index 6e54e06374..6f030535c9 100644
--- a/cesar/test_general/station/cco0/s2/py/sc16_igmp.py
+++ b/cesar/test_general/station/cco0/s2/py/sc16_igmp.py
@@ -21,6 +21,7 @@ from sta_mgr import Sta_mgr
from maximus import *
csi = csiCore (1234)
+MAC_TEI_BCAST = 0xff
# Create the AVLN.
avln_sta_nb = 5
@@ -76,13 +77,20 @@ def test_mactotei_no_group(self):
tei = sta_data.get_tei_from_mac(maximus, ref_sta_cesar, mac_group)
self.failUnless (tei == 0)
-def data_msdu_filter (msdu):
+def mme_msdu_filter (msdu):
if msdu.get_type () is 'ETHERNET_TYPE_MME':
# The received object is an MSDU
return True
else:
return False
+def data_msdu_filter (msdu):
+ if msdu.get_type () is 'ETHERNET_TYPE_DATA':
+ # The received object is an MSDU
+ return True
+ else:
+ return False
+
def send_mme_DRV_MCAST_SET_LIST (self, payload):
""" send DRV_MCAST_SET_REQ to ref_sta_cesar """
# Create and send mme message
@@ -99,7 +107,7 @@ def send_mme_DRV_MCAST_SET_LIST (self, payload):
mme.send (maximus, ref_sta_cesar)
# Wait for response
- rsp = recv (maximus, count=1, filter=data_msdu_filter,
+ rsp = recv (maximus, count=1, filter=mme_msdu_filter,
timeout=50000000)
# Fail in case of no response
self.failUnless (rsp != None)
@@ -181,7 +189,7 @@ class TestIGMP(unittest.TestCase):
mac_group = (0x01, 0x00, 0x5E, i, i , i)
mac_member = (0x00, 0x13, 0xd7, 0x00, 0x01, i)
tei = sta_data.get_tei_from_mac(maximus, ref_sta_cesar, mac_group)
- self.failUnless (tei == mac2tei[mac_member])
+ self.failUnless (tei == MAC_TEI_BCAST)
# Send an empty list to remove the multicast entries
data = pack ('B', 0)