summaryrefslogtreecommitdiff
path: root/cesar/cl
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cl')
-rw-r--r--cesar/cl/inc/context.h22
-rw-r--r--cesar/cl/src/cl.c107
-rw-r--r--cesar/cl/test/Makefile2
-rw-r--r--cesar/cl/test/src/cl_send_data.c258
-rw-r--r--cesar/cl/test/src/test.c69
-rw-r--r--cesar/cl/test/test.h71
6 files changed, 320 insertions, 209 deletions
diff --git a/cesar/cl/inc/context.h b/cesar/cl/inc/context.h
index 58e2b80038..78f379052f 100644
--- a/cesar/cl/inc/context.h
+++ b/cesar/cl/inc/context.h
@@ -26,6 +26,10 @@
#include "cl/inc/trace.h"
+/** Define the delay at the one the data inside the cl_data_send_link_t are
+ * considered expired. */
+#define CL_DATA_SEND_EXCEED_TIME_MS 100
+
/** data tx structure. */
struct cl_data_tx_t
{
@@ -86,6 +90,21 @@ struct cl_mme_t
};
typedef struct cl_mme_t cl_mme_t;
+/** Keep DATA about last data SEND. This should help the CL to use
+ * previous MFS to send the new Frame if it is for the same destination Mac
+ * Address. The date inside it is only set if it the current time is exceed
+ * see CL_DATA_SEND_EXCEED_TIME_MS. */
+struct cl_data_send_link_t
+{
+ /** Last update time, Set with the arrival time stamp in the NTB clock. */
+ u32 last_update_date_ntb;
+ /** Destination Mac address. */
+ mac_t dmac;
+ /** Link associated. */
+ mfs_tx_t *mfs;
+};
+typedef struct cl_data_send_link_t cl_data_send_link_t;
+
struct cl_t
{
/** The sar context use to send the MME or data. */
@@ -122,6 +141,9 @@ struct cl_t
/** The bridge table module context. */
bridge_table_context_t bridge_table;
+ /** Last link used on a Data send. */
+ cl_data_send_link_t data_send_link;
+
/** Tracing system */
#if CONFIG_TRACE
/** cl Trace */
diff --git a/cesar/cl/src/cl.c b/cesar/cl/src/cl.c
index 78c55aa74c..d9416f876e 100644
--- a/cesar/cl/src/cl.c
+++ b/cesar/cl/src/cl.c
@@ -21,6 +21,7 @@
#include "cl/data_rate.h"
#include "mac/sar/sar.h"
#include "mac/pbproc/pbproc.h"
+#include "mac/common/timings.h"
#include "cl/inc/context.h"
#include "cl/inc/cl.h"
@@ -96,10 +97,12 @@ cl_classifer_get_lid (cl_t *ctx, uint tei, uint tag,
* \param tag the tag provided by the upper layer.
* \param cl_data opaque type.
* \param arrival_time_ntb the arrival time in NTB.
+ * \param dmac the final destination mac address.
*/
static void
cl_data_send_with_tei (cl_t *ctx, u8 *buffer, uint length, uint tei,
- uint tag, cl_send_t *cl_data, u32 arrival_time_ntb)
+ uint tag, cl_send_t *cl_data, u32 arrival_time_ntb,
+ mac_t dmac)
{
uint lid;
bool bcast;
@@ -138,6 +141,9 @@ cl_data_send_with_tei (cl_t *ctx, u8 *buffer, uint length, uint tei,
{
CL_TRACE (DATA_SEND, mac_ntb(), buffer, length, mfs->common.tei,
mfs->common.lid, mfs->common.bcast);
+ ctx->data_send_link.mfs = mfs;
+ ctx->data_send_link.last_update_date_ntb = arrival_time_ntb;
+ ctx->data_send_link.dmac = dmac;
sar_msdu_add (ctx->sar, buffer, length, mfs, cl_data,
arrival_time_ntb);
@@ -159,11 +165,10 @@ cl_data_send_with_tei (cl_t *ctx, u8 *buffer, uint length, uint tei,
buffer, length);
dbg_assert (ctx->data_tx.cb);
(*ctx->data_tx.cb) (ctx->data_tx.user, buffer);
+ /* Release the MFS */
+ if (mfs)
+ blk_release (mfs);
}
-
- /* release the mfs */
- if (mfs)
- blk_release (mfs);
}
/** Initialise the cl_send object.
@@ -285,6 +290,9 @@ cl_init (mac_store_t *mac_store, sar_t *sar, mac_config_t *mac_config)
/* Initialize the local bridge table module. */
bridge_table_init (ctx);
+ /* Initialise the data link. */
+ ctx->data_send_link.mfs = NULL;
+
CL_TRACE (INIT, mac_ntb());
/* Debug leds. */
@@ -331,6 +339,9 @@ void cl_uninit (cl_t *ctx)
/* De-initialize the local bridge table module. */
bridge_table_deinit (ctx);
+ /* Release the MFS of the data_send_link context. */
+ if (ctx->data_send_link.mfs)
+ blk_release (ctx->data_send_link.mfs);
cl_trace_uninit(ctx);
}
@@ -518,51 +529,91 @@ cl_send_multiunicast (cl_t *ctx, u8 *buffer, uint length, bool mme, uint tag,
dbg_assert_default ();
}
-void
-cl_data_send (cl_t *ctx, u8 *buffer, uint length, uint tag,
- u32 arrival_time_ntb)
+/**
+ * Prepare the CL to send a Frame.
+ * \param ctx the cl context.
+ * \param buffer the Ethernet frame to send.
+ * \param length the Ethernet frame length.
+ * \param tag the tag for the classifier.
+ * \param arrrival_time_ntb arrival time in the High layers.
+ * \param dmac the destination mac address.
+ * \param smac the source mac address.
+ */
+static void
+cl_data_send_prepare (cl_t *ctx, u8 *buffer, uint length, uint tag,
+ u32 arrival_time_ntb, mac_t dmac, mac_t smac)
{
- dbg_assert (ctx);
- dbg_assert (buffer);
- dbg_assert ((length >= ETH_PACKET_MIN_SIZE_ALLOWED)
- && (length <= ETH_PACKET_MAX_SIZE));
-
- /* Get MAC addresses. */
- mac_t src_mac, dst_mac;
- bitstream_direct_read_macs (buffer, &dst_mac, &src_mac);
/* The source MAC address should not be not be a multicast, a zero address
* nor a broadcast one (note that checking multicast address also checks
* for broadcast). Linux, in bridging mode, handle this problem and reject
* any of those packets (see net/bridge/br_input.c:127 (in
* br_handle_frame). */
- dbg_assert (src_mac != MAC_ZERO);
- dbg_assert (!mac_is_multicast (src_mac));
+ dbg_assert (smac != MAC_ZERO);
+ dbg_assert (!mac_is_multicast (smac));
/* Add the source MAC address to the local bridge table if not our MAC
* address. */
dbg_assert (ctx->mac_config);
- if (ctx->mac_config->sta_mac_address != src_mac)
- bridge_table_add (ctx, src_mac);
+ if (ctx->mac_config->sta_mac_address != smac)
+ bridge_table_add (ctx, smac);
/* Data are forbidden if not authenticated. */
if (!ctx->mac_config->authenticated)
{
- (*ctx->data_tx.cb) (ctx->data_tx.user, buffer);
- CL_TRACE (DATA_SEND_DROP, mac_ntb (), ctx->mac_config->authenticated,
- buffer, length);
- return;
+ (*ctx->data_tx.cb) (ctx->data_tx.user, buffer);
+ CL_TRACE (DATA_SEND_DROP, mac_ntb (), ctx->mac_config->authenticated,
+ buffer, length);
+ return;
}
/* Get the TEI from the mactotei table. */
uint tei;
- tei = cl_mactotei_table_find_tei_from_mac (ctx, dst_mac);
+ tei = cl_mactotei_table_find_tei_from_mac (ctx, dmac);
dbg_assert (tei != ctx->mac_config->tei);
/* 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,
- tag, NULL, arrival_time_ntb);
+ tag, NULL, arrival_time_ntb, dmac);
}
+void
+cl_data_send (cl_t *ctx, u8 *buffer, uint length, uint tag,
+ u32 arrival_time_ntb)
+{
+ mac_t smac, dmac;
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert ((length >= ETH_PACKET_MIN_SIZE_ALLOWED)
+ && (length <= ETH_PACKET_MAX_SIZE));
+ bitstream_direct_read_macs (buffer, &dmac, &smac);
+ if (ctx->data_send_link.mfs
+ && ctx->data_send_link.mfs->fsm_state != MFS_FSM_CMD_RELEASE
+ && dmac == ctx->data_send_link.dmac
+ && ctx->mac_config->authenticated
+ && less_mod2p32 (arrival_time_ntb,
+ ctx->data_send_link.last_update_date_ntb
+ + MAC_MS_TO_TCK (CL_DATA_SEND_EXCEED_TIME_MS)))
+ {
+ CL_TRACE (DATA_SEND, mac_ntb(), buffer, length,
+ ctx->data_send_link.mfs->common.tei,
+ ctx->data_send_link.mfs->common.lid,
+ ctx->data_send_link.mfs->common.bcast);
+ sar_msdu_add (ctx->sar, buffer, length,
+ ctx->data_send_link.mfs, NULL,
+ arrival_time_ntb);
+ }
+ else
+ {
+ /* Release the MFS's reference. */
+ if (ctx->data_send_link.mfs)
+ {
+ blk_release (ctx->data_send_link.mfs);
+ ctx->data_send_link.mfs = NULL;
+ }
+ cl_data_send_prepare (ctx, buffer, length, tag,
+ arrival_time_ntb, dmac, smac);
+ }
+}
/**
* Send an MME from the CP to the PLC via the SAR MME way.
@@ -676,6 +727,7 @@ cl_mme_send (cl_t *ctx, u8 *buffer, uint length, uint tei)
}
else if (ctx->mac_config->authenticated)
{
+ mac_t dmac = bitstream_direct_read_large (buffer, 0, 48);
dbg_assert (tei != ctx->mac_config->tei);
// if the TEI is not found the packet is send as broadcast.
@@ -683,8 +735,7 @@ cl_mme_send (cl_t *ctx, u8 *buffer, uint length, uint tei)
cl_data_send_with_tei (ctx, buffer, length,
table_tei,
1 /* Priority 0 in HPAV.*/, cl_data,
- mac_ntb());
-
+ mac_ntb(), dmac);
CL_TRACE (MME_SEND_AS_DATA, mac_ntb(), length, buffer, tei);
}
}
diff --git a/cesar/cl/test/Makefile b/cesar/cl/test/Makefile
index e3892b2909..20b8426021 100644
--- a/cesar/cl/test/Makefile
+++ b/cesar/cl/test/Makefile
@@ -19,7 +19,7 @@ cl_recv_data_SOURCES = cl_recv_data.c phy_stub.c
cl_recv_data_MODULES = lib cl mac/common \
mac/sar/stub
-cl_send_data_SOURCES = cl_send_data.c phy_stub.c
+cl_send_data_SOURCES = test.c cl_send_data.c phy_stub.c
cl_send_data_MODULES = lib cl mac/common \
mac/sar/stub
diff --git a/cesar/cl/test/src/cl_send_data.c b/cesar/cl/test/src/cl_send_data.c
index 8b410520c3..7045b8b3cb 100644
--- a/cesar/cl/test/src/cl_send_data.c
+++ b/cesar/cl/test/src/cl_send_data.c
@@ -13,218 +13,119 @@
*/
#include "common/std.h"
+#include "mac/common/timings.h"
#include "lib/test.h"
-#include "lib/trace.h"
-#include "lib/slab.h"
#include "lib/bitstream.h"
-
-#include "mac/pbproc/pbproc.h"
-#include "mac/common/ntb.h"
-
#include "cl/cl.h"
-#include "cl/cl_mactotei.h"
-#include "cl/inc/trace.h"
-
-#include "hal/phy/phy.h"
-
-#include <stdio.h>
+#include "cl/test/test.h"
+#include "cl/inc/context.h"
uint
cl_classifer_get_lid (cl_t *ctx, uint tei, uint tag,
bool *bcast, bool *acs,
bool *drop);
-
-static mfs_tx_t *mfs_test;
-
-unsigned int packet[]__attribute__((aligned(2048))) =
-{ 0x001111B6, 0x1E520002, 0x00000000, 0x00000000,
- 0x0000ffff, 0x00000001, 0x46973299, 0x0007c33e,
- 0x00000042, 0x00000042, 0x12005452, 0x00080235,
- 0x4c205227, 0x00450008, 0x4e043400, 0x06400040,
- 0x000a1917, 0x79cb0f02, 0x1b04d547, 0x6b285000,
- 0x0000babc, 0x02800000, 0x396bf0fa, 0x04020000,
- 0x0301b405, 0x01010003, 0x00000204};
-unsigned int packet_len = 106;
-
void
-sar_mfs_add (sar_t *ctx, mfs_t *mfs)
-{
-}
-
-void
-sar_msdu_add (sar_t *ctx, u8 *buffer, u16 length,
- mfs_tx_t *mfs, void *user_data, u32 arrival_time_ntb)
+test_data_send_done_cb (void *user, u8 *buffer)
{
- dbg_assert (mfs);
-
- mfs_test = mfs;
-
- dbg_assert (!user_data);
}
void
-test_data_send_done_cb (void *user, u8 *buffer)
+test_cl_data_send_prepare (cl_test_t *ctx, test_t test, u8 *buffer,
+ uint length, u32 av_time_ntb,
+ cl_data_send_link_t *expected)
{
+ test_within(test);
+ cl_data_send (ctx->cl, buffer, length, 0, 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 ==
+ expected->last_update_date_ntb);
+ test_fail_unless (ctx->cl->data_send_link.dmac ==
+ bitstream_direct_read_large (buffer, 0, 48));
}
void
-test_case__cl_data_send (test_t test)
+test_case__cl_data_send_prepare (test_t test)
{
- mac_t sta1_mac = 0x123456789ABCull;
- uint sta1_tei = 10;
- uint sta1_tag = 0;
-
- mac_t sta2_mac = 0x23456789ABCDull;
- uint sta2_tei = 11;
- uint sta2_tag = 0;
-
- test_case_begin (test, "Send a packet to the PWL");
-
- test_begin (test, "Send on PLID 0, station 1")
+ test_case_begin (test, "Data send");
+
+ u8 buffer [1024];
+ cl_data_send_link_t expected;
+ mac_t sta_mac [] = {0x123456789abcull, 0x23456789abceull};
+ uint length = 123;
+ bool added;
+ cl_test_t t;
+ uint i, j, start_time_ntb = 0;
+ mfs_tx_t *mfs[COUNT(sta_mac)];
+ cl_test_init (&t, 0x95490d);
+ cl_test_prepare_mactotei (&t, sta_mac, COUNT (sta_mac));
+ for (j = 0; j < COUNT (sta_mac); j++)
{
- cl_t *cl;
- cl_mactotei_blk_t *table;
- mac_store_t *mac_store;
- uint sar;
- mac_config_t mac_config;
- uint phy;
-
- /* Initialise. */
- mac_store = mac_store_init ();
- cl = cl_init (mac_store, (sar_t *) &sar, &mac_config);
- cl_data_send_done_init (cl, test_data_send_done_cb, NULL);
- mac_config.authenticated = true;
-
- mac_ntb_init ((phy_t *) &phy, &mac_config);
-
- /* Create the mac to TEI table. */
- table = cl_mactotei_new ();
- cl_mactotei_addr_add (table, sta1_mac, sta1_tei, sta1_tag);
- cl_mactotei_addr_add (table, sta2_mac, sta2_tei, sta2_tag);
- cl_mactotei_use_table (cl, table);
- table = NULL;
-
- bitstream_direct_write_large ((u8*) packet, 0, sta1_mac, 48);
-
- /* Send the packet. */
- cl_data_send (cl, (u8*) packet, packet_len, 0, 123);
-
- /* check the MFS created. */
- test_fail_unless (mfs_test->common.tei == sta1_tei);
-
- /* Uninitialise. */
- mac_store_mfs_remove (mac_store, (mfs_t *) mfs_test);
- dbg_check (mac_store_sta_remove (mac_store, mfs_test->common.tei));
- cl_uninit (cl);
- mac_store_uninit (mac_store);
+ mfs[j] = mac_store_mfs_add_tx (t.mac_store, false, false, 1, j + 1,
+ &added);
+ dbg_assert (added);
}
- test_end;
-
- test_begin (test, "Send on PLID 0, station 2")
+ test_begin (test, "Verify cache expiration.")
{
- cl_t *cl;
- cl_mactotei_blk_t *table;
- mac_store_t *mac_store;
- uint sar;
- mac_config_t mac_config;
- uint phy;
-
- /* Initialise. */
- mac_store = mac_store_init ();
- cl = cl_init (mac_store, (sar_t *) &sar, &mac_config);
- cl_data_send_done_init (cl, test_data_send_done_cb, NULL);
- mac_config.authenticated = true;
-
- mac_ntb_init ((phy_t *) &phy, &mac_config);
-
- /* Create the mac to TEI table. */
- table = cl_mactotei_new ();
- cl_mactotei_addr_add (table, sta1_mac, sta1_tei, sta1_tag);
- cl_mactotei_addr_add (table, sta2_mac, sta2_tei, sta2_tag);
- cl_mactotei_use_table (cl, table);
- table = NULL;
-
- bitstream_direct_write_large ((u8*) packet, 0, sta2_mac, 48);
-
- /* Send the packet. */
- cl_data_send (cl, (u8*) packet, packet_len, 0, 123);
-
- /* check the MFS created. */
- test_fail_unless (mfs_test->common.tei == sta2_tei);
-
- /* Uninitialise. */
- mac_store_mfs_remove (mac_store, (mfs_t *) mfs_test);
- dbg_check (mac_store_sta_remove (mac_store, mfs_test->common.tei));
- cl_uninit (cl);
- mac_store_uninit (mac_store);
+ for (j = 0; j < COUNT (sta_mac); j++)
+ {
+ cl_test_prepare_buffer (&t, buffer, length, sta_mac[j]);
+ expected.mfs = mfs[j];
+ expected.last_update_date_ntb = start_time_ntb;
+ expected.dmac = sta_mac[j];
+ for (i = start_time_ntb;
+ i < 2*MAC_MS_TO_TCK (CL_DATA_SEND_EXCEED_TIME_MS);
+ i+= 100000)
+ {
+ if (i == MAC_MS_TO_TCK (CL_DATA_SEND_EXCEED_TIME_MS))
+ expected.last_update_date_ntb = i;
+ test_cl_data_send_prepare (&t, test, buffer, length, i,
+ &expected);
+ }
+ }
}
test_end;
-
- test_begin (test, "Send on PLID 0, station not found")
+ test_begin (test, "Verify cache update on destination mac change.")
{
- cl_t *cl;
- cl_mactotei_blk_t *table;
- mac_store_t *mac_store;
- uint sar;
- mac_config_t mac_config;
- uint phy;
-
- /* Initialise. */
- mac_store = mac_store_init ();
- cl = cl_init (mac_store, (sar_t *) &sar, &mac_config);
- cl_data_send_done_init (cl, test_data_send_done_cb, NULL);
- mac_config.authenticated = true;
- mac_config.tei = 0x1;
-
- mac_ntb_init ((phy_t *) &phy, &mac_config);
-
- /* Create the mac to TEI table. */
- table = cl_mactotei_new ();
- cl_mactotei_addr_add (table, sta1_mac, sta1_tei, sta1_tag);
- cl_mactotei_addr_add (table, sta2_mac, sta2_tei, sta2_tag);
- cl_mactotei_use_table (cl, table);
- table = NULL;
-
- bitstream_direct_write_large ((u8*) packet, 0, 0x99999999ull, 48);
-
- /* Send the packet. */
- cl_data_send (cl, (u8*) packet, packet_len, 0, 124);
-
- /* check the MFS created. */
- test_fail_unless (mfs_test->common.tei == MAC_TEI_BCAST);
-
- /* Uninitialise. */
- mac_store_mfs_remove (mac_store, (mfs_t *) mfs_test);
- cl_uninit (cl);
- mac_store_uninit (mac_store);
+ for (i = start_time_ntb;
+ i < 2*MAC_MS_TO_TCK (CL_DATA_SEND_EXCEED_TIME_MS);
+ i+= 100000)
+ {
+ uint index;
+ for (j = 0; j < 2 * COUNT (sta_mac); j++)
+ {
+ index = j % COUNT (sta_mac);
+ cl_test_prepare_buffer (&t, buffer, length, sta_mac[index]);
+ expected.mfs = mfs[index];
+ expected.last_update_date_ntb = i;
+ expected.dmac = sta_mac[index];
+ test_cl_data_send_prepare (&t, test, buffer, length, i,
+ &expected);
+ }
+ }
}
test_end;
+ for (j = 0; j < COUNT (sta_mac); j++)
+ {
+ mac_store_mfs_remove (t.mac_store, PARENT_OF (mfs_t, tx, mfs[j]));
+ blk_release (mfs [j]);
+ dbg_check (mac_store_sta_remove (t.mac_store, j + 1));
+ }
+ cl_test_uninit (&t);
}
void
test_case__data_too_short (test_t test)
{
+ u8 buffer [1024];
test_begin (test, "Data too short")
{
- cl_t *cl;
- mac_store_t *mac_store;
- uint sar;
- mac_config_t mac_config;
- uint phy;
-
+ cl_test_t t;
/* Initialise. */
- mac_store = mac_store_init ();
- cl = cl_init (mac_store, (sar_t *) &sar, &mac_config);
- cl_data_send_done_init (cl, test_data_send_done_cb, NULL);
- mac_config.authenticated = true;
- mac_config.tei = 0x1;
-
- mac_ntb_init ((phy_t *) &phy, &mac_config);
-
+ cl_test_init (&t, 0x92843);
dbg_fatal_try_begin
{
- cl_data_send (cl, (u8*) packet, ETH_PACKET_MIN_SIZE_ALLOWED - 1,
+ cl_data_send (t.cl, buffer, ETH_PACKET_MIN_SIZE_ALLOWED - 1,
0, 11);
test_fail_unless (false);
}
@@ -234,11 +135,8 @@ test_case__data_too_short (test_t test)
test_fail_unless (true);
}
dbg_fatal_try_end;
-
/* Uninitialise. */
- mac_store_mfs_remove (mac_store, (mfs_t *) mfs_test);
- cl_uninit (cl);
- mac_store_uninit (mac_store);
+ cl_test_uninit (&t);
}
test_end;
}
@@ -290,7 +188,7 @@ int main (void)
trace_init ();
test_init (test, 0, NULL);
- test_case__cl_data_send (test);
+ test_case__cl_data_send_prepare (test);
test_case__data_too_short (test);
test_case__qos (test);
diff --git a/cesar/cl/test/src/test.c b/cesar/cl/test/src/test.c
new file mode 100644
index 0000000000..ea0a6f71ea
--- /dev/null
+++ b/cesar/cl/test/src/test.c
@@ -0,0 +1,69 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cl/test/src/test.c
+ * \brief CL environment test.
+ * \ingroup cl
+ */
+#include "common/std.h"
+#include "lib/bitstream.h"
+#include "cl/test/test.h"
+#include "cl/cl_mactotei.h"
+
+void
+cl_test_init (cl_test_t *ctx, u32 seed)
+{
+ dbg_assert (ctx);
+ ctx->mac_store = mac_store_init ();
+ mac_config_init (&ctx->mac_config);
+ ctx->mac_config.authenticated = true;
+ ctx->mac_config.tei = 0xfe;
+ ctx->mac_config.sta_mac_address = 0xfeffffd71300ull;
+ ctx->cl = cl_init (ctx->mac_store, INVALID_PTR, &ctx->mac_config);
+ lib_rnd_init (&ctx->rnd, seed);
+}
+
+void
+cl_test_uninit (cl_test_t *ctx)
+{
+ dbg_assert (ctx);
+ cl_uninit (ctx->cl);
+ mac_store_uninit (ctx->mac_store);
+}
+
+void
+cl_test_prepare_mactotei (cl_test_t *ctx, mac_t *dmacs, uint nb)
+{
+ uint i;
+ cl_mactotei_blk_t *table;
+ dbg_assert (ctx);
+ cl_mactotei_release_table (ctx->cl);
+ table = cl_mactotei_new ();
+ for (i = 0; i < nb; i++)
+ {
+ dbg_assert (!mac_is_multicast (dmacs[i]));
+ cl_mactotei_addr_add (table, dmacs[i], i + 1, MAC_TEI_UNASSOCIATED);
+ }
+ cl_mactotei_use_table (ctx->cl, table);
+}
+
+void
+cl_test_prepare_buffer (cl_test_t *ctx, u8 *buffer, u16 length, mac_t dmac)
+{
+ u8 data;
+ u16 i;
+ bitstream_t stream;
+ dbg_assert (ctx);
+ data = lib_rnd32 (&ctx->rnd) & 0xff;
+ bitstream_write_init (&stream, buffer, length);
+ bitstream_write_large (&stream, dmac, 48);
+ bitstream_write_large (&stream, ctx->mac_config.sta_mac_address, 48);
+ for (i = 0; i < length - 12; i++)
+ bitstream_write (&stream, data, 8);
+ bitstream_finalise (&stream);
+}
diff --git a/cesar/cl/test/test.h b/cesar/cl/test/test.h
new file mode 100644
index 0000000000..e4aa3c5f9a
--- /dev/null
+++ b/cesar/cl/test/test.h
@@ -0,0 +1,71 @@
+#ifndef cl_test_test_h
+#define cl_test_test_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cl/test/test.h
+ * \brief CL environment test.
+ * \ingroup cl
+ */
+#include "cl/cl.h"
+#include "lib/rnd.h"
+
+struct cl_test_t
+{
+ /** CL context. */
+ cl_t *cl;
+ /** Mac config context. */
+ mac_config_t mac_config;
+ /** Mac store context. */
+ mac_store_t *mac_store;
+ /** Random context. */
+ lib_rnd_t rnd;
+};
+typedef struct cl_test_t cl_test_t;
+
+BEGIN_DECLS
+
+/**
+ * Initialise test context.
+ * \param ctx the test context.
+ * \param seed the seed to initialise the random generator.
+ */
+void
+cl_test_init (cl_test_t *ctx, u32 seed);
+
+/**
+ * Uninitialise the CL context.
+ * \param ctx the test context.
+ */
+void
+cl_test_uninit (cl_test_t *ctx);
+
+/**
+ * Prepare the mac to tei table of the CL.
+ * \param ctx the CL context.
+ * \param dmacs destination mac tables.
+ * \param nb the number of entries.
+ *
+ * First entry corresponds to TEI 1 and so on.
+ */
+void
+cl_test_prepare_mactotei (cl_test_t *ctx, mac_t *dmacs, uint nb);
+
+/**
+ * Prepare a buffer to be sent by the Cl.
+ * \param ctx the test context.
+ * \param buffer the buffer to use.
+ * \param length the MF length.
+ * \param dmac the destination mac address.
+ */
+void
+cl_test_prepare_buffer (cl_test_t *ctx, u8 *buffer, u16 length, mac_t dmac);
+
+END_DECLS
+
+#endif /* cl_test_test_h */