summaryrefslogtreecommitdiff
path: root/cesar/mac/sar
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/mac/sar')
-rw-r--r--cesar/mac/sar/Module4
-rw-r--r--cesar/mac/sar/bridgedma/Module1
-rw-r--r--cesar/mac/sar/bridgedma/inc/bridge.h58
-rw-r--r--cesar/mac/sar/bridgedma/src/bridge.c233
-rw-r--r--cesar/mac/sar/doc/sar.odtbin0 -> 359727 bytes
-rw-r--r--cesar/mac/sar/inc/bridge_dma.h75
-rw-r--r--cesar/mac/sar/inc/sar.h199
-rw-r--r--cesar/mac/sar/inc/sar_context.h187
-rw-r--r--cesar/mac/sar/inc/sar_expiration.h162
-rw-r--r--cesar/mac/sar/inc/sar_job_mfs.h49
-rw-r--r--cesar/mac/sar/inc/sar_mf.h75
-rw-r--r--cesar/mac/sar/inc/sar_mfs.h63
-rw-r--r--cesar/mac/sar/inc/sar_pb.h36
-rw-r--r--cesar/mac/sar/inc/trace.h77
-rw-r--r--cesar/mac/sar/sar.h351
-rw-r--r--cesar/mac/sar/sar_mfs_expiration_cb.h24
-rw-r--r--cesar/mac/sar/src/bridge_dma.c155
-rw-r--r--cesar/mac/sar/src/sar.c1751
-rw-r--r--cesar/mac/sar/src/sar_expiration.c459
-rw-r--r--cesar/mac/sar/src/sar_mf.c180
-rw-r--r--cesar/mac/sar/src/sar_mfs.c105
-rw-r--r--cesar/mac/sar/src/sar_pb.c48
-rw-r--r--cesar/mac/sar/src/trace.c73
-rw-r--r--cesar/mac/sar/test/Module2
-rw-r--r--cesar/mac/sar/test/inc/ce.h76
-rw-r--r--cesar/mac/sar/test/inc/eth_packets.h141
-rw-r--r--cesar/mac/sar/test/inc/reassembly_unit_test_functions.h52
-rw-r--r--cesar/mac/sar/test/inc/sar_unit_test_functions.h112
-rw-r--r--cesar/mac/sar/test/maximus_test/Makefile14
-rw-r--r--cesar/mac/sar/test/maximus_test/ecos.ecc.sh104
-rw-r--r--cesar/mac/sar/test/maximus_test/inc/blk_t.h27
-rw-r--r--cesar/mac/sar/test/maximus_test/inc/max_job.h30
-rw-r--r--cesar/mac/sar/test/maximus_test/src/Maximus_sar.cpp431
-rw-r--r--cesar/mac/sar/test/maximus_test/src/Sta_sar.c1187
-rw-r--r--cesar/mac/sar/test/src/ce.c140
-rw-r--r--cesar/mac/sar/test/src/reassembly_unit_test_functions.c304
-rw-r--r--cesar/mac/sar/test/src/sar_unit_test_functions.c100
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/Makefile75
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/ecos.ecc.sh5
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/beacon.c78
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/crc_error.c148
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/lib_sar_expiration.c644
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/lib_sar_mfs.c123
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/msdu-timeout.c108
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/reassembly_complete.c430
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/reassembly_create_mfs.c149
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/reassembly_measurement.c126
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/reassembly_mfs_update_expiration_date.c100
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/reassembly_two_jobs.c236
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/sar_call_back_ul.c179
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/sar_manage_expiration.c808
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/sar_mf_function_test.c148
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/sar_mfs_resising.c268
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/segmentation_complete.c486
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/test-segmentation-provide-pb.c129
-rw-r--r--cesar/mac/sar/test/unit_test/ecos/src/test_store_memory.c46
-rw-r--r--cesar/mac/sar/test/unit_test/host/Makefile17
-rw-r--r--cesar/mac/sar/test/unit_test/host/src/bridgedma_list.c87
-rw-r--r--cesar/mac/sar/test/unit_test/host/src/lib_buffer_address_list.c123
-rw-r--r--cesar/mac/sar/test/unit_test/host/src/lib_sar_mf.c198
-rw-r--r--cesar/mac/sar/test/unit_test/host/src/phy_stub.c24
-rw-r--r--cesar/mac/sar/test/unit_test/host/src/test_store_memory.c44
62 files changed, 11864 insertions, 0 deletions
diff --git a/cesar/mac/sar/Module b/cesar/mac/sar/Module
new file mode 100644
index 0000000000..aa46e13333
--- /dev/null
+++ b/cesar/mac/sar/Module
@@ -0,0 +1,4 @@
+SOURCES := sar.c sar_expiration.c sar_mf.c sar_pb.c sar_mfs.c bridge_dma.c
+ifeq ($(CONFIG_TRACE),y)
+SOURCES += trace.c
+endif
diff --git a/cesar/mac/sar/bridgedma/Module b/cesar/mac/sar/bridgedma/Module
new file mode 100644
index 0000000000..dc07b476c1
--- /dev/null
+++ b/cesar/mac/sar/bridgedma/Module
@@ -0,0 +1 @@
+SOURCES := bridge.c \ No newline at end of file
diff --git a/cesar/mac/sar/bridgedma/inc/bridge.h b/cesar/mac/sar/bridgedma/inc/bridge.h
new file mode 100644
index 0000000000..14804a9a27
--- /dev/null
+++ b/cesar/mac/sar/bridgedma/inc/bridge.h
@@ -0,0 +1,58 @@
+#ifndef BRIDGE_H_
+#define BRIDGE_H_
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lib/rnd.h"
+
+#include "mac/pbproc/pbproc.h"
+
+#include "hal/phy/bridgedma.h"
+#include "mac/sar/inc/sar_mf.h"
+
+struct bridge_dma_test_t
+{
+ phy_bridgedma_job_t *head;
+ phy_bridgedma_job_t *tail;
+
+ phy_bridgedma_cb_t bridge_cb;
+ void *user_data;
+
+ phy_bridgedma_job_t *curr;
+};
+typedef struct bridge_dma_test_t bridge_dma_test_t;
+
+
+struct pb_bridged_list_t
+{
+ pb_t *first;
+ pb_t *last;
+};
+typedef struct pb_bridged_list_t pb_bridged_list_t;
+
+phy_bridgedma_t *
+phy_bridgedma_init (void *user_data, phy_bridgedma_cb_t bridgedma_cb,
+ phy_deferred_cb_t deferred_cb);
+
+void phy_bridgedma_start (phy_bridgedma_t *ctx,
+ phy_bridgedma_job_t *job_first, phy_bridgedma_job_t *job_last);
+
+/**
+ * Reset and uninitialise the Bridge DMA.
+ * \param ctx Bridge DMA context
+ */
+void
+phy_bridgedma_uninit (phy_bridgedma_t *ctx);
+
+void bridge_run (void);
+
+u16 mix_up_pbs (pb_t **first, pb_t **last);
+
+bridge_dma_test_t bridge;
+pb_bridged_list_t pb_list;
+
+#endif /*BRIDGE_H_*/
diff --git a/cesar/mac/sar/bridgedma/src/bridge.c b/cesar/mac/sar/bridgedma/src/bridge.c
new file mode 100644
index 0000000000..8b602aad76
--- /dev/null
+++ b/cesar/mac/sar/bridgedma/src/bridge.c
@@ -0,0 +1,233 @@
+#include "common/std.h"
+#include "mac/sar/bridgedma/inc/bridge.h"
+#include "lib/read_word.h"
+
+phy_bridgedma_t *phy_bridgedma_init (void *user_data,
+ phy_bridgedma_cb_t bridgedma_cb, phy_deferred_cb_t deferred_cb)
+{
+ bridge.bridge_cb = bridgedma_cb;
+ bridge.user_data = user_data;
+
+ bridge.head = NULL;
+ bridge.tail = NULL;
+ bridge.curr = NULL;
+
+ pb_list.first = NULL;
+ pb_list.last = NULL;
+
+ return NULL;
+}
+
+void phy_bridgedma_start (phy_bridgedma_t *ctx,
+ phy_bridgedma_job_t *job_first, phy_bridgedma_job_t *job_last)
+{
+ if (bridge.head == NULL)
+ {
+ bridge.head = job_first;
+ bridge.tail = job_last;
+
+ bridge.curr = job_first;
+ }
+ else
+ {
+ bridge.tail->next = job_first;
+ bridge.tail = job_last;
+ }
+
+ job_last->next = NULL;
+ bridge_run ();
+}
+
+void bridge_run (void)
+{
+ phy_bridgedma_job_t *bridge_job;
+
+ u8 *data_addr;
+ u8 header_len;
+ u32 header1;
+ u32 header2;
+ s16 data_len;
+ pb_t *first;
+ u16 offset;
+ bool direction;
+ u16 data_offset;
+ u8 *buffer;
+ bool debug = false;
+
+ while (bridge.curr)
+ {
+ bridge_job = bridge.curr;
+ data_addr = bridge_job->data_addr;
+ header_len = bridge_job->header_len;
+
+ header1 = bridge_job->mf_header1;
+ header2 = bridge_job->mf_header2;
+
+ bridge_job->crc_error = false;
+ data_len = bridge_job->data_len + header_len;
+ first = (pb_t *) bridge_job->first_pb_desc;
+ offset = bridge_job->first_pb_offset;
+ direction = bridge_job->direction;
+
+ if (debug)
+ {
+ printf ("/*************** BRIDGE **************/\n");
+ printf ("header len : %d\n", header_len);
+ printf ("header 1 : %x\n", header1);
+ printf ("header 2 : %x\n", header2);
+ printf ("data_len : %d\n", data_len);
+ printf ("offset : %d\n", offset);
+ printf ("Direction : %d\n", direction);
+ printf ("/************* BRIDGE END ************/\n");
+ }
+
+ if (offset > BLK_SIZE)
+ {
+ return;
+ }
+
+ if (direction)
+ {
+ //RX
+ u8 *addr;
+
+ addr = first->data + offset;
+ buffer = malloc (2048 * sizeof(u8));
+ header_len = read_u16_from_word (addr) & 0x3;
+
+ memcpy (buffer, (first->data + offset), BLK_SIZE- offset);
+ data_len -= BLK_SIZE - offset;
+ data_offset = BLK_SIZE - offset;
+
+ while (data_len > BLK_SIZE)
+ {
+ first = first->next;
+ memcpy (buffer + data_offset, first->data, BLK_SIZE);
+ data_len -= BLK_SIZE;
+ data_offset += BLK_SIZE;
+ }
+
+ if (data_len > 0)
+ {
+ first = first->next;
+ memcpy (buffer + data_offset, first->data, data_len);
+ }
+
+ if (header_len > 1)
+ {
+ header_len = 6;
+ }
+ else
+ {
+ header_len = 2;
+ }
+ memcpy (data_addr, buffer + header_len, 2048 - header_len);
+ free (buffer);
+
+ }
+ else
+ {
+ //list the pb in the pb list
+ if (pb_list.first == NULL)
+ {
+ pb_list.first = first;
+ }
+ else if (pb_list.last != first)
+ {
+ pb_list.last->next = first;
+ pb_list.last = first;
+ }
+
+ *((u32*)(first->data + offset)) = header1;
+
+ if (header_len > 2)
+ {
+ *((u16 *)(first->data + offset + sizeof(u32))) = header2;
+ }
+
+ offset += sizeof(u32) + sizeof(u16);
+
+ memcpy ((char *) (first->data + offset), (char *) data_addr,
+ BLK_SIZE - offset);
+ data_len -= BLK_SIZE - offset;
+ data_offset = BLK_SIZE - offset;
+
+ while (data_len > BLK_SIZE)
+ {
+ first = first->next;
+ memcpy ((char *) (first->data), (char *) data_addr
+ + data_offset, BLK_SIZE);
+ data_len -= BLK_SIZE;
+ data_offset += BLK_SIZE;
+ }
+
+ //list the pb in the pb list
+ pb_list.last = first;
+ }
+
+ bridge.curr = bridge.head->next;
+ if (bridge.head)
+ {
+ bridge.head = bridge.head->next;
+ }
+
+ (*bridge.bridge_cb) (bridge.user_data, 0);
+ }
+}
+
+u16 mix_up_pbs (pb_t **first, pb_t **last)
+{
+ pb_t *list[100];
+ u16 size;
+ pb_t *head;
+ pb_t *tmp;
+ lib_rnd_t rnd_ctx1;
+ lib_rnd_t rnd_ctx2;
+ int i;
+ u16 slot1;
+ u16 slot2;
+
+ lib_rnd_init (&rnd_ctx1, 123456);
+ lib_rnd_init (&rnd_ctx2, 234567);
+
+ //count the quantity of PBs.
+ for (size = 0, head = pb_list.first; head != NULL; head = head->next,
+ size++)
+ {
+ list[size] = head;
+ }
+ list[size] = NULL;
+
+ // randomize the list
+ for (i = 0; i < size; i++)
+ {
+ slot1 = lib_rnd32 (&rnd_ctx1) % size;
+ slot2 = lib_rnd32 (&rnd_ctx2) % size;
+
+ tmp = list[slot1];
+ list[slot1] = list[slot2];
+ list[slot2] = tmp;
+ }
+
+ //Chain the PB list
+ for (i = 0; i < size - 1; i++)
+ {
+ list[i]->next = list[i+1];
+ }
+
+ *first = list[0];
+ *last = list[size - 1];
+ list[size - 1]->next = NULL;
+
+ return size;
+}
+
+/**
+ * Reset and uninitialise the Bridge DMA.
+ * \param ctx Bridge DMA context
+ */
+void
+phy_bridgedma_uninit (phy_bridgedma_t *ctx)
+{
+}
+
diff --git a/cesar/mac/sar/doc/sar.odt b/cesar/mac/sar/doc/sar.odt
new file mode 100644
index 0000000000..c8f7385f80
--- /dev/null
+++ b/cesar/mac/sar/doc/sar.odt
Binary files differ
diff --git a/cesar/mac/sar/inc/bridge_dma.h b/cesar/mac/sar/inc/bridge_dma.h
new file mode 100644
index 0000000000..baccfc5d9b
--- /dev/null
+++ b/cesar/mac/sar/inc/bridge_dma.h
@@ -0,0 +1,75 @@
+#ifndef BRIDGE_DMA_H_
+#define BRIDGE_DMA_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/inc/bridge_dma.h
+ * \brief header for the bridge dma launch.
+ * \ingroup mac_sar
+ */
+
+#include "mac/sar/inc/sar_job_mfs.h"
+
+/**
+ * Bridge DMA list of jobs to process
+ */
+struct sar_bridge_dma_list_t
+{
+ sar_job_mfs_t *head;
+ sar_job_mfs_t *tail;
+};
+typedef struct sar_bridge_dma_list_t sar_bridge_dma_list_t;
+
+/**
+ * Initialize the list of jobs for the bridge DMA.
+ */
+void bridge_dma_list_init (sar_bridge_dma_list_t *list);
+
+/**
+ * Return the head of the list and remove it from the list
+ *
+ * \param list the list to get the head
+ * \return the head of the lsit
+ */
+sar_job_mfs_t * bridge_dma_get_head (sar_bridge_dma_list_t *list);
+
+/**
+ * Add a job to the tx/rx pending job list
+ *
+ * \param list the bridge dma list to add the job
+ * \param head the job mfs to add to the list
+ */
+void bridge_dma_add_pending_job (sar_bridge_dma_list_t *list,
+ sar_job_mfs_t *head);
+
+/**
+ * Add a job to the bridge dma list
+ *
+ * \param bridge_list the list in which the job must be added
+ * \param head the head chain list
+ * \param last the tail of the chain list.
+ */
+void bridge_dma_add_jobs (sar_bridge_dma_list_t *bridge_list,
+ sar_job_mfs_t *head, sar_job_mfs_t *last);
+
+/**
+ * Verify the if a list is empty.
+ *
+ * \return boolean indicating is the state of the list
+ */
+bool bridge_dma_list_is_empty (sar_bridge_dma_list_t *list);
+
+/**
+ * Remove all the jobs in the list and release the mfs and PBs in it.
+ *
+ * \param list the list to uninit.
+ */
+void bridge_dma_uninit_list (sar_bridge_dma_list_t *list);
+
+#endif /*BRIDGE_DMA_H_*/
diff --git a/cesar/mac/sar/inc/sar.h b/cesar/mac/sar/inc/sar.h
new file mode 100644
index 0000000000..cb7f4d3ce4
--- /dev/null
+++ b/cesar/mac/sar/inc/sar.h
@@ -0,0 +1,199 @@
+#ifndef MAC_SAR_INC_SAR_H_
+#define MAC_SAR_INC_SAR_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/inc/sar.h
+ * \brief private declaration functions of the SAR.
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#define SAR_GET_WORK_DELAY_RTC 5
+
+/**
+ * Initialize the reassembly context
+ *
+ * \param ctx the sar reassembly context
+ * \param buffer the buffer to stock the addresses.
+ * \param nb_slots the quantity of slots.
+ */
+void sar_reassembly_init (sar_reassembly_ctx_t *ctx, u8 **buffer, uint nb_slots);
+
+/**
+ * Allocate a new list of chained PB of the size of pb_nb to give it to the
+ * pbproc.
+ *
+ * \param ctx the sar context
+ * \param pb_nb the quantity of PBs to allocate.
+ */
+void pb_pool_refill (sar_t *ctx, uint pb_nb);
+
+/**
+ * Get the first work to do by the SAR
+ *
+ * \param ctx the sar context.
+ * \return the work message
+ */
+sar_work_message_t* sar_work_get (sar_t *ctx);
+
+/**
+ * Parse the chain of PBs recevived from the pb proc.
+ * - Verifies if the PB is valid
+ * - Transmit the data to the CE.
+ * - Update the mfs window according with the HomePlug AV specification.
+ * - Verifies if the PB is in the window
+ * - Insert it in the right place in the corresponding MFS.
+ *
+ * \param ctx the sar context
+ * \param rx the mpdu_rx containing the PB to add to the MFS
+ */
+void rx_mpdu_process (sar_t *ctx, sar_mpdu_t * rx);
+
+/**
+ * Verify if one or various buffers are available for the CP. If they are the
+ * a list of jobs are chained to the bridge DMA job list to be processed.
+ *
+ * This function never loop cause of the implementation, When a buffer is
+ * haded this function is called as the same is done at each reconstitution of
+ * a MF.
+ *
+ * \param sar_ctx the sar context.
+ * \param ctx the reassembly context to transmit the data.
+ */
+void rx_upper_layer_transmit_data (sar_t *sar_ctx, sar_reassembly_ctx_t *ctx);
+
+/**
+ * Create a job with all the minimum configuration for the bridge dma
+ *
+ * \param tx if it is a TX way
+ * \return sar job mfs for the bridge dma.
+ */
+sar_job_mfs_t *sar_job_mfs_create (bool tx);
+
+/**
+ * Get the mfs from mac store or create it using the rx_params lid and dtei.
+ *
+ * \param sar the sar context.
+ * \param rx the rx_mpdu
+ * \param pb the PB from which it is possible to know if it needs the mme mfs
+ * or the data mfs
+ *
+ * \return the mfs corresponding, or the new one.
+ */
+mfs_rx_t *rx_get_associated_mfs (sar_t *sar, sar_mpdu_t * rx, pb_t *pb);
+
+/**
+ * Create a job_desc_t from the md_data and allocate the PBs neccessary to stock
+ * the MF contained in the md_data
+ *
+ * Create the list of PBs necessary to contain the MF and put it via the
+ * PB proc in the MFS.
+ *
+ * \param md_data the data to segment
+ * \param mfs the corresponding mfs
+ * \param job_mfs the job to fill
+ *
+ * \return the last pb of the chain
+ */
+pb_t * tx_job_desc_create (sar_msdu_t *md_data, mfs_tx_t * mfs,
+ sar_job_mfs_t *job_mfs);
+
+/**
+ * Create a complete or a partial list of PBs for the mac framing
+ * \param length the length of the complete MF or the end of the MF
+ * \param ssn the next ssn to put on the header
+ * \param mme if the segments will contain messages.
+ * \param begin the first pb of the chain
+ * \param last the last pb of the chain.
+ * \return the number of PBs allocated
+ */
+u8 tx_job_desc_create_complete_list (u16 length, u8 ssn, bool mme,
+ pb_t **begin, pb_t **last);
+
+/** create mac frame to transmit in preparing next job of bridge dma for
+ * segmentation
+ *
+ * \param ctx the sar context.
+ * \param md_data the Mac Frame to fill the job descriptor
+ */
+sar_job_mfs_t * tx_mac_framing (sar_t *ctx, sar_msdu_t *md_data);
+
+/**
+ * Msdu expiration
+ * cf the specification HomePlug AV on page 260 (5.4.1.6.1 Transmit buffer
+ * management).
+ *
+ * \param ctx the sar context
+ * \param msdu the msdu to verify
+ * \return true if it had expired, false otherwise.
+ */
+bool tx_msdu_expiration (sar_t *ctx, sar_msdu_t * msdu);
+
+/**
+ * Segmentation process for the SAR module.
+ *
+ * \param ctx the sar context
+ * \param msdu the msdu to process
+ */
+void segmentation_run (sar_t *ctx, sar_msdu_t *msdu);
+
+/**
+ * Launch the reassembly process to realize reassembly a new mpdu.
+ *
+ * \param ctx the sar context
+ * \param rx the rx data to process
+ */
+void reassembly_run (sar_t *ctx, sar_mpdu_t *rx);
+
+/**
+ * Search where the PB with the ssn given can be inserted in the chain.
+ *
+ * \param mfs the mfs to search
+ * \param ssn the ssn of the current pb
+ * \return - the last after the one the PB can be inserted in the list.
+ * - null if the chain is empty
+ * - null if it can not be inserted (the value already already
+ * exists in the chain).
+ */
+pb_t *rx_mfs_search_where_to_insert_pb (mfs_rx_t *mfs, u16 ssn);
+
+/**
+ * Function called by the phy hal when the bridge return an IT
+ *
+ * \param user user data
+ * \param status_word l'etat du bridge
+ */
+bool bridge_dma_interruption (void *user, u32 status_word);
+
+/**
+ * Function called by the phy hal when the bridge return an IT
+ *
+ * \param user user data
+ */
+void bridge_dma_deffered_interruption (void *user);
+
+/**
+ * Free the head of the bridge dma and call the rigth function.
+ *
+ * \param ctx the sar context.
+ */
+void
+bridge_dma_free_head (sar_t *ctx);
+
+/**
+ * Process the MFS to reconstitute MF until the MFS contains PBs or the MF
+ * can not be reconsitute because of missing PBs.
+ *
+ * \param ctx the sar context
+ * \param mfs the mfs to proccess.
+ */
+void rx_mfs_process (sar_t *ctx, mfs_rx_t * mfs);
+
+#endif /* MAC_SAR_INC_SAR_H_ */
diff --git a/cesar/mac/sar/inc/sar_context.h b/cesar/mac/sar/inc/sar_context.h
new file mode 100644
index 0000000000..551427db72
--- /dev/null
+++ b/cesar/mac/sar/inc/sar_context.h
@@ -0,0 +1,187 @@
+#ifndef SAR_CONTEXT_H_
+#define SAR_CONTEXT_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_context.h
+ * \brief Sar context declarations.
+ * \ingroup mac/sar/inc
+ */
+
+#include "mac/pbproc/pbproc.h"
+#include "lib/circular_buffer.h"
+
+#ifdef STATION_H_
+#include "hal/phy/bridgedma.h"
+#include "hal/phy/forward.h"
+#include "hal/phy/maximus/inc/maximus_interrupts.h"
+#include "hal/phy/maximus/inc/maximus_phy_ctx.h"
+#include "hal/phy/maximus/inc/maximus_bridgedma_ctx.h"
+#else
+#include "mac/sar/bridgedma/inc/bridge.h"
+#endif
+
+#include "mac/sar/inc/sar_expiration.h"
+#include "mac/sar/inc/sar_mf.h"
+#include "mac/sar/inc/sar_pb.h"
+#include "mac/sar/inc/bridge_dma.h"
+#include "mac/sar/inc/trace.h"
+
+
+#define SAR_NUMBER_OF_SLOTS_DATA 128
+#define SAR_NUMBER_OF_SLOTS_MSG 1
+
+/** mpdu_rx_t */
+struct sar_mpdu_t
+{
+ pbproc_rx_params_t *rx_params;
+ pb_t *chandata;
+ uint nb_chandata;
+ mfs_rx_t *mfs;
+ mfs_rx_t *mme;
+ pb_t *head;
+ pb_t *tail;
+ uint number;
+ u32 expiration_ntb;
+};
+typedef struct sar_mpdu_t sar_mpdu_t;
+
+struct sar_msdu_t
+{
+ /** Ats confounder field*/
+ u32 ats_confounder;
+ /** type and length of the data to segment */
+ u16 length;
+ /** The buffer address to use */
+ u8 *buffer_address;
+ /** the associated MFS */
+ mfs_tx_t *mfs;
+};
+typedef struct sar_msdu_t sar_msdu_t;
+
+struct sar_reassembly_ctx_t
+{
+ sar_reassembly_done_cb_t sar_rea_done;
+ sar_bridge_dma_list_t jobs_pending_list;
+
+ circular_buffer_t buffer_address_list;
+};
+typedef struct sar_reassembly_ctx_t sar_reassembly_ctx_t;
+
+enum message_type_t
+{
+ SEG,
+ REA,
+ ADD_BUFFER,
+ BRIDGE
+};
+typedef enum message_type_t message_type_t;
+
+union sar_work_message_union_t
+{
+ /** Mpdu data for the reassembly */
+ sar_msdu_t msdu;
+ /** Msdu data for the segmentation */
+ sar_mpdu_t mpdu;
+ /** buffer address */
+ u8 *buffer_addr;
+ /** Bridge direction */
+ bool bridge_direction;
+};
+typedef union sar_work_message_union_t sar_work_message_union_t;
+
+struct sar_work_message_t
+{
+ /**TODO To be removed if the use of the ecos mailbox is kept*/
+ //struct work_message_t *next;
+ message_type_t type;
+ /** reassembly ctx */
+ sar_reassembly_ctx_t *ctx;
+ sar_work_message_union_t msg;
+};
+typedef struct sar_work_message_t sar_work_message_t;
+
+/** Sar context */
+struct sar_t
+{
+ /** Data initialized in the sar_init */
+
+ /** The list of job for the bridge DMA
+ * Data initialized in the sar_init */
+ sar_bridge_dma_list_t bridge_dma_jobs;
+
+ /**
+ * Sar expiration context
+ */
+ sar_expiration_t expiration;
+
+ /** work mailbox for the segmentation process
+ * Data initialized in the sar_init */
+ cyg_mbox mailbox;
+ /** msdu mailbox handle to use the mailbox
+ * Data initialized in the sar_init */
+ cyg_handle_t mailbox_handle;
+
+ /** inform the upper layer when a job hab been bridged
+ * Initiliazed in sar_segmentation_init_mme_cb */
+ sar_segmentation_done_cb_t sar_seg_data_done_cb;
+
+ /** inform the upper layer when a job hab been bridged
+ * Initiliazed in sar_segmentation_init_data_cb*/
+ sar_segmentation_done_cb_t sar_seg_msg_done_cb;
+
+ /** Call back pointer for measurement data
+ * Data initialized in the sar_init_measurement_cb */
+ sar_measurement_cb_t sar_measurement;
+
+ /** sar context for the data reassembly
+ * sar_init_reassembly_data_cb */
+ sar_reassembly_ctx_t data_ctx;
+ u8 *data_slots[SAR_NUMBER_OF_SLOTS_DATA];
+
+ /** sar context for the mme reassembly
+ * sar_init_reassembly_mme_cb */
+ sar_reassembly_ctx_t mme_ctx;
+ u8 *mme_slots[SAR_NUMBER_OF_SLOTS_MSG];
+
+ /** beacon function call back */
+ void *beacon_user_data;
+ sar_beacon_cb_t beacon_function_cb;
+
+ /** ****************** Layers context ***************/
+
+ /** Bridge dma context
+ * Data initialized in the sar_init */
+ phy_bridgedma_t *bridgedma_ctx;
+
+ /** Pb proc call back to provide pbs */
+ pbproc_t *pbproc_ctx;
+
+ /** Channel estimation ctx */
+ void *ul_ce_ctx;
+
+ /** data context */
+ void *ul_data_ctx;
+
+ /** message context */
+ void *ul_msg_ctx;
+
+ /** Thread context. */
+ u8 thread_stack [SAR_THREAD_STACK_SIZE];
+ cyg_handle_t thread_handle;
+ cyg_thread thread;
+
+ /** Tracing system */
+#if CONFIG_TRACE
+ /** sar Trace */
+ trace_buffer_t trace;
+#endif /* !CONFIG_TRACE */
+};
+
+#endif /*SAR_CONTEXT_H_*/
diff --git a/cesar/mac/sar/inc/sar_expiration.h b/cesar/mac/sar/inc/sar_expiration.h
new file mode 100644
index 0000000000..4c72d2503b
--- /dev/null
+++ b/cesar/mac/sar/inc/sar_expiration.h
@@ -0,0 +1,162 @@
+#ifndef SAR_EXPIRATION_H_
+#define SAR_EXPIRATION_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_expiration.h
+ * \brief the function for the sar expiration process.
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "mac/sar/sar_mfs_expiration_cb.h"
+#include "mac/sar/inc/sar_mf.h"
+#include "mac/sar/inc/sar_mfs.h"
+#include "mac/sar/inc/sar_pb.h"
+
+#define RELEASE_TIMER_VALUE 25000000
+#define CA_DELAY_RELEASE 25000000
+
+#define SAR_MAX_REASSEMBLY_TIMER_NTB 25000000
+#define SAR_MAX_SEGMENTATION_TIMER_NTB 25000000
+
+struct sar_expiration_t
+{
+ /** Heap expiration for the mfs_tx
+ * Data initialized in the sar_init */
+ heap_t mfs_expiration_heap;
+ /** mutex to access the expiration heap
+ * Data initialized in the sar_init */
+ cyg_mutex_t expiration_heap_mutex;
+
+ /** The MFS Store to create MFS in the reassembly process
+ * Data initialized in the sar_init
+ * (given in parameter) */
+ mac_store_t *mfs_store;
+
+ /**
+ * Callback to inform the upper layer that a MFS will go to the release
+ * state.
+ */
+ sar_mfs_expired_cb_t mfs_expiration_cb;
+
+ /**
+ * Channel access context to add and remove MFSs.
+ */
+ ca_t *ca;
+};
+typedef struct sar_expiration_t sar_expiration_t;
+
+/**
+ * initialize the sar expiration and returns a context.
+ *
+ * \param ctx the context.
+ * \param ca the Channel Access context.
+ */
+void sar_expiration_init (sar_expiration_t *ctx, ca_t *ca);
+
+/**
+ * initialize the sar expiration and returns a context.
+ *
+ * \param ctx the context.
+ */
+void sar_expiration_uninit (sar_expiration_t *ctx);
+
+/** Add a MFS to the SAR.
+ *
+ * \param ctx the expiration context
+ * \param mfs the mfs to add to the SAR.
+ */
+void sar_expiration_mfs_add (sar_expiration_t *ctx, mfs_t *mfs);
+
+/** Remove a MFS from the SAR
+ *
+ * \param ctx the expiration context
+ * \param mfs the mfs to remove from the SAR.
+ */
+void sar_expiration_mfs_remove (sar_expiration_t *ctx, mfs_t *mfs);
+
+/** Destroy a MFS from the SAR
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to remove from the SAR.
+ *
+ * \return true if successed, false otherwise.
+ */
+bool sar_expiration_mfs_destroy (sar_expiration_t *ctx, mfs_t *mfs);
+
+/**
+ * get the next mfs to expire.
+ *
+ * \param ctx the sar expiration context
+ *
+ * \return the mfs on the root element of the heap.
+ */
+mfs_t* sar_expiration_get_mfs (sar_expiration_t *ctx);
+
+/**
+ * ajust the expiration heap
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to adjust in the expiration machanism
+ */
+void sar_expiration_ajust (sar_expiration_t *ctx, mfs_t *mfs);
+
+/**
+ * remove the mfs from the sar expiration mechanism.
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to remove
+ */
+void sar_expiration_mfs_remove_element (sar_expiration_t *ctx, mfs_t *mfs);
+
+/**
+ * Update the expiration date of the RX MFS
+ *
+ * \param ctx the sar expiration ctx to update the expiration machanism
+ * \param mfs the mfs to update
+ * \param date the current date
+ */
+void sar_expiration_mfs_update_date (sar_expiration_t *ctx, mfs_t *mfs,
+ u32 date);
+
+/**
+ * Launch the expiration mechanism and verify if the mfs had expired or not.
+ *
+ * \param ctx the sar expiration context
+ * \param phy_curr_date current date.
+ */
+void sar_expiration_mfs (sar_expiration_t *ctx, u32 phy_curr_date);
+
+/**
+ * Compare the two nodes of the tree, if the left side is lesser than the right
+ * it returns true otherwise it returns false.
+ *
+ * \param left the left heap node
+ * \param right the right heap node
+ * \return true if left expires before right, wrong otherwise.
+ */
+bool sar_expiration_mfs_less (heap_node_t *left, heap_node_t *right);
+
+/**
+ * Called by the mfs_manage_expiration to expire the pbs in the MFS.
+ *
+ * \param head the first pb to check.
+ * \param expiration_delay expiration delay
+ * \param phy_curr_date the current phy date.
+ * \return the new head of the chain.
+ */
+pb_t
+ * sar_expiration_pb (pb_t *head, uint expiration_delay,
+ u32 phy_curr_date);
+
+#endif /*SAR_EXPIRATION_H_*/
diff --git a/cesar/mac/sar/inc/sar_job_mfs.h b/cesar/mac/sar/inc/sar_job_mfs.h
new file mode 100644
index 0000000000..8cede7c19d
--- /dev/null
+++ b/cesar/mac/sar/inc/sar_job_mfs.h
@@ -0,0 +1,49 @@
+#ifndef SAR_JOB_MFS_H_
+#define SAR_JOB_MFS_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_job_mfs.h
+ * \brief job_mfs_t structure.
+ * \ingroup mac/sar/inc
+ */
+
+#include "mac/pbproc/pbproc.h"
+#include "mac/common/mfs.h"
+
+#ifndef STATION_H_
+#include "hal/phy/bridgedma.h"
+#else
+#include "mac/sar/bridgedma/inc/bridge.h"
+#endif
+
+/**
+ * Allows to remove the Job processed by the PBDMA from the memory
+ * And update the data of the mfs the counter of futur pbs available and
+ * the currents available.
+ */
+struct sar_job_mfs_t
+{
+ phy_bridgedma_job_t job;
+ mfs_t *mfs;
+ /** the last pb of the chain */
+ pb_t *tail;
+ /** usefull to update the mfs data for the tx */
+ u32 pb_quantity;
+ /** Job mfs next use to travel */
+ struct sar_job_mfs_t *next;
+ /** Last pb taken. */
+ bool pb_last_taken;
+ /** The offset of the next data which can be present in the last PB of the
+ * job. */
+ uint last_pb_offset;
+};
+typedef struct sar_job_mfs_t sar_job_mfs_t;
+
+#endif /*SAR_JOB_MFS_H_*/
diff --git a/cesar/mac/sar/inc/sar_mf.h b/cesar/mac/sar/inc/sar_mf.h
new file mode 100644
index 0000000000..4101f15150
--- /dev/null
+++ b/cesar/mac/sar/inc/sar_mf.h
@@ -0,0 +1,75 @@
+#ifndef SAR_MF_H_
+#define SAR_MF_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mf.h
+ * \brief header for the Mac Frame use.
+ * \ingroup mac/sar/inc
+ */
+
+#include "mac/pbproc/pbproc.h"
+#include "common/defs/ethernet.h"
+
+#define SAR_MF_MFH_SIZE 2
+#define SAR_MF_ATS_SIZE 4
+#define SAR_MF_ICV_SIZE 4
+
+
+#define SAR_MF_MAX_SIZE (SAR_MF_MFH_SIZE + SAR_MF_ATS_SIZE + ETH_PACKET_MAX_SIZE + SAR_MF_ICV_SIZE)
+#define SAR_MF_MIN_SIZE (SAR_MF_MFH_SIZE + SAR_MF_ATS_SIZE + ETH_PACKET_MIN_SIZE + SAR_MF_ICV_SIZE)
+
+#define SAR_DIV_BY_BLK_SIZE 9
+
+/**
+ * Get the type of the MF from the PB at the data adress plus the offset
+ *
+ * \param pb The first pb containing the MF.
+ * \param offset the offset to start reading
+ * \return MF type.
+ */
+uint mf_get_type (pb_t * pb, uint offset);
+
+/**
+ * Test the existance of a MF at the address given by mf and return its length.
+ * Will be used to determine if a complete MF is avaliable in the MFS.
+ * Test if the MF start in the end of the PB by verifying the offset, if the MFH
+ * is in two PBs.
+ *
+ * \param pb The first pb containing the MF.
+ * \param offset the offset to start reading
+ * \param payload_only request to return only the payload length if true.
+ *
+ * \return length of the paylod with the header and icv
+ */
+uint mf_get_length (pb_t *pb, uint offset, bool payload_length_only);
+
+/**
+ * Calculate the number of PB used for the MF
+ *
+ * Depends of the mf_get_length function
+ *
+ * \param pb the first PB where the MF starts
+ * \param offset the offset of the PB where the MF starts
+ * \return the quantity of PBs
+ */
+uint mf_get_quantity_of_pb (pb_t *pb, uint offset);
+
+/**
+ * gets the ATS of a MF in the address pointed by the PB plus the offset
+ *
+ * Depends of mf_get_type
+ *
+ * \param pb the first PB where the MF starts
+ * \param offset the offset of the PB where the MF starts
+ * \return the ATS of the MF.
+ */
+u32 mf_get_ats (pb_t *, uint offset);
+
+#endif /*SAR_MF_H_*/
diff --git a/cesar/mac/sar/inc/sar_mfs.h b/cesar/mac/sar/inc/sar_mfs.h
new file mode 100644
index 0000000000..ab4a90514d
--- /dev/null
+++ b/cesar/mac/sar/inc/sar_mfs.h
@@ -0,0 +1,63 @@
+#ifndef SAR_MFS_H_
+#define SAR_MFS_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mfs.h
+ * \brief the function for the sar mfs.
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#include "mac/pbproc/pbproc.h"
+#include "mac/sar/inc/sar_pb.h"
+
+/**
+ * Update last pb continuous on the mfs
+ *
+ * Verify the continuity of the chain from the first PB of the MFS to the last
+ * contiguous.
+ *
+ * If the counter of ssn had been reseted it verify the coninuity search the ssn
+ * 0 after the ssn 655535.
+ *
+ * \param mfs the MFS to update
+ * \param pb of the MFS from wich one it is needed to update
+ */
+void rx_mfs_update_last_contiguous_and_tail (mfs_rx_t *mfs, pb_t *pb);
+
+/**
+ * Verify if it is necessary to modify the ssn of the MFS according with the
+ * Homeplug AV norm.
+ *
+ * \param pb the pb to make the test.
+ * \param mfs the mfs to verify.
+ * \param pb_nb number of PBs in the mpdu given by the pbproc.
+ */
+void rx_mfs_resize_ssn (pb_t *pb, mfs_rx_t *mfs, uint pb_nb);
+
+/**
+ * Return the max ssn of the MFS
+ *
+ * \param mfs the mfs.
+ */
+u16
+rx_mfs_get_ssn_max (mfs_rx_t *mfs);
+
+/**
+ * Insert a PB after the PB this in the PBs chain
+ *
+ * \param this the pb which the new is the next
+ * \param new the Pb to insert
+ * \return the pb after new
+ */
+pb_t *
+rx_mfs_add_pb_after (pb_t *this, pb_t *new);
+
+#endif /*SAR_MFS_H_*/
diff --git a/cesar/mac/sar/inc/sar_pb.h b/cesar/mac/sar/inc/sar_pb.h
new file mode 100644
index 0000000000..226ec90bae
--- /dev/null
+++ b/cesar/mac/sar/inc/sar_pb.h
@@ -0,0 +1,36 @@
+#ifndef SAR_PB_H_
+#define SAR_PB_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_pb.h
+ * \brief common function to process pbs
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#include "mac/pbproc/pbproc.h"
+
+/**
+ * Free a pb of a chain and return the next PB of the PB given in parameter
+ *
+ * \param pb The PB to free
+ * \return The next PB of the freed PB.
+ */
+pb_t *pb_free (pb_t *);
+
+/**
+ * Free a range of pb
+ *
+ * \param pb The PB to free
+ * \return The next PB of the freed PB.
+ */
+void pb_free_range (pb_t *pb);
+
+#endif /*SAR_PB_H_*/
diff --git a/cesar/mac/sar/inc/trace.h b/cesar/mac/sar/inc/trace.h
new file mode 100644
index 0000000000..4fc8b8e5e2
--- /dev/null
+++ b/cesar/mac/sar/inc/trace.h
@@ -0,0 +1,77 @@
+#ifndef mac_sar_inc_trace_h
+#define mac_sar_inc_trace_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/inc/trace.h
+ * \brief Trace system
+ * \ingroup mac_sar
+ *
+ */
+
+#include "lib/trace.h"
+
+/** Shortcut for tracing inside SAR. */
+#define SAR_TRACE(id, args...) \
+ TRACE_FAST_SHORT (SAR_TRACE_, &ctx->trace, id, ## args)
+
+#if CONFIG_TRACE
+
+enum
+{
+ SAR_TRACE_INIT,
+ SAR_TRACE_UNINIT,
+ SAR_TRACE_DATA_BUFFER_ADD,
+ SAR_TRACE_MME_BUFFER_ADD,
+ SAR_TRACE_MPDU_ADD,
+ SAR_TRACE_MSDU_ADD,
+ SAR_TRACE_MFS_ADD,
+ SAR_TRACE_MFS_REMOVE,
+ SAR_TRACE_BRIDGE,
+ SAR_TRACE_PB_ERROR,
+ SAR_TRACE_MPDU_EXP,
+ SAR_TRACE_PB_SSN_NOT_IN_WIN,
+ SAR_TRACE_MSDU_EXP,
+ SAR_TRACE_BEACON,
+ SAR_TRACE_MBOX,
+};
+
+BEGIN_DECLS
+
+/**
+ * Initialize the trace system
+ * \param ctx the sar context.
+ */
+void
+sar_trace_init (sar_t *ctx);
+
+/**
+ * Uninitialize the trace system
+ * \param ctx the sar context
+ */
+void
+sar_trace_uninit (sar_t *ctx);
+
+/**
+ * Print the traces
+ * \param ctx the sar context.
+ */
+void
+sar_trace_print (sar_t *sar);
+
+END_DECLS
+
+#else /* !CONFIG_TRACE */
+
+#define sar_trace_init(ctx) ((void) 0)
+#define sar_trace_uninit(ctx) ((void) 0)
+#define sar_trace_print(ctx) ((void) 0)
+
+#endif /* !CONFIG_TRACE */
+
+#endif /* mac_sar_inc_trace_h */
diff --git a/cesar/mac/sar/sar.h b/cesar/mac/sar/sar.h
new file mode 100644
index 0000000000..f078b9adf8
--- /dev/null
+++ b/cesar/mac/sar/sar.h
@@ -0,0 +1,351 @@
+#ifndef MAC_SAR_SAR_H_
+#define MAC_SAR_SAR_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/sar.h
+ * \brief Public intefaces of the SAR.
+ * \ingroup mac/sar/
+ *
+ */
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/kernel/kapi.h>
+
+#include "mac/common/store.h"
+#include "mac/pbproc/pbproc.h"
+#include "mac/sar/sar_mfs_expiration_cb.h"
+
+#define SAR_THREAD_PRIORITY 9
+#define SAR_THREAD_STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
+
+/* forward declaration */
+typedef struct sar_t sar_t;
+
+/**
+ * Pb measurement RX callback for Channel estimation.
+ * This call back will return one or two block in order to insert all the
+ * measurements contained in each PB of the mpdu received.
+ * Two cases can happen, the first the pb_nb is lesser than the blk capacity,
+ * this callback will return only a blk pointed by the first and the last
+ * pointer.
+ * In the second case the quantity of PB are greater than one blk capacity, this
+ * callback will return two blk (chained) the first pointed by the first pointer
+ * and the last one by the last pointer.
+ *
+ * It provides the chandata to the CE provided by the pbproc.
+ *
+ * \param user User data
+ * \param rx_params Frame control information to know date and tonemap used
+ * \param number of pbs
+ * \param first blk to insert the measurements.
+ * \param last blk to insert the measurements.
+ * \param chan_data_first the first chandata PB.
+ * \param nb_chandata the quantitity of chandata PBs.
+ * \param blk_offset the first offset to write the measure in the blk.
+ *
+ * \return boolean to indicate if a block had been returned or not.
+ */
+typedef bool (*sar_measurement_cb_t) (void *user,
+ pbproc_rx_params_t *rx_params, uint pb_nb, blk_t **first,
+ blk_t **last, pb_t *chan_data_first, uint nb_chandata, uint
+ *blk_offset);
+
+/**
+ * Segmentation job done for the segmentation module, it send a data to inform
+ * the upper layer that a job had been processed.
+ *
+ * \param user upper layer context
+ * \param buffer the buffer which is no more used.
+ *
+ * The MFS reference is given to the CL it do not make a addref on it.
+ */
+typedef void (*sar_segmentation_done_cb_t) (void *user, u8* buffer);
+
+/**
+ * Inform the upper layer that the buffer given in parameter is not used anymore.
+ *
+ * \param user upper layer context pointer
+ * \param buffer the buffer which is no more used.
+ * \param length the length of the buffer.
+ * \param mfs the mfs correponding to the payload in the buffer.
+ * \param encrypted true if the MF has been encrypted, false otherwise. This
+ * is only valable for the MME, the DATA are dropped if it is not encrypted.
+ *
+ * The MFS reference is given to the CL it do not make a addref on it.
+ */
+typedef void (*sar_reassembly_done_cb_t) (void *user, u8* buffer,
+ uint length, mfs_rx_t *mfs, bool encrypted);
+
+/**
+ * Provides the beacon to the Control Plane
+ *
+ * \param user user data
+ * \param beacon the beacon data
+ * \param params the rx params at the pb reception
+ */
+typedef void (*sar_beacon_cb_t) (void *user, pb_beacon_t *pb,
+ pbproc_rx_beacon_params_t *params);
+
+/**
+ * Initialize the sar context.
+ *
+ * \param mac_store the mac store
+ * \param pbproc the pbproc context.
+ * \param ca the Channel Access context.
+ * \return the sar context.
+ */
+sar_t *sar_init (mac_store_t *mac_store, pbproc_t *pbproc, ca_t *ca);
+
+/**
+ * Release all the data used in the sar.
+ *
+ * \param ctx the sar context.
+ */
+void sar_uninit (sar_t *ctx);
+
+/**
+ * Add the upper data layer context to the SAR. It allows the sar to use
+ * the context in the callbacks to this layer.
+ *
+ * \param ctx the sar context
+ * \param user the upper layer data context.
+ */
+void sar_init_data_context (sar_t *ctx, void *user);
+
+/**
+ * Add the upper data layer context to the SAR. It allows the sar to use
+ * the context in the callbacks to this layer.
+ *
+ * \param ctx the sar context
+ * \param user the upper layer msg context.
+ */
+void sar_init_mme_context (sar_t *ctx, void *user);
+
+/**
+ * Add the upper data layer context to the SAR. It allows the sar to use
+ * the context in the callbacks to this layer.
+ *
+ * \param ctx the sar context
+ * \param user the upper layer msg context.
+ */
+void sar_init_measure_context (sar_t *ctx, void *user);
+
+/**
+ * Used by the upper layers to send or received messages.
+ *
+ * \param ctx the sar context
+ * \param sar_seg_done used by the segmentation to inform the upper layer the
+ * buffer is not used anymore.
+ */
+void sar_init_segmentation_mme_cb (sar_t *ctx,
+ sar_segmentation_done_cb_t sar_mme_seg_done);
+
+/**
+ * Used to inform the upper layer when a Data has been provided to the CA.
+ *
+ * \param ctx the sar context
+ * \param sar_seg_done used by the segmentation to inform the upper layer the
+ * buffer is not used anymore.
+ */
+void sar_init_segmentation_data_cb (sar_t *ctx,
+ sar_segmentation_done_cb_t sar_data_seg_done);
+
+/**
+ * Initialize the callback to send the measurement contained in the PBs.
+ *
+ * \param ctx the sar context
+ * \param sar_measurement the function to call to get the buffers to stock
+ * the measurements.
+ */
+void sar_init_measurement_cb (sar_t *ctx,
+ sar_measurement_cb_t sar_measurement);
+
+/**
+ * Add a buffer address to the sar to bridge pending jobs.
+ *
+ * \param ctx the sar context to add a buffer
+ * \param buffer_addr the buffer address to add to the sar in order to bridge
+ * the pending jobs.
+ * \param data if it is a data buffer.
+ * \return true if the buffer had been added, false, otherwise.
+ */
+bool sar_buffer_add (sar_t *ctx, u8* buffer_addr, bool data);
+
+/**
+ * Add a buffer address to the sar to bridge pending jobs.
+ *
+ * \param ctx the sar context to add a buffer
+ * \param buffer_addr the buffer address to add to the sar in order to bridge
+ * the pending jobs.
+ * \return true if the buffer had been added, false, otherwise.
+ */
+extern inline bool sar_data_buffer_add (sar_t *ctx, u8* buffer_addr)
+{
+ return sar_buffer_add (ctx, buffer_addr, true);
+}
+
+/**
+ * Add a buffer address to the sar to bridge pending jobs.
+ *
+ * \param ctx the sar context to add a buffer
+ * \param buffer_addr the buffer address to add to the sar in order to bridge
+ * the pending jobs.
+ * \return true if the buffer had been added, false, otherwise.
+ */
+extern inline bool sar_mme_buffer_add (sar_t *ctx, u8* buffer_addr)
+{
+ return sar_buffer_add (ctx, buffer_addr, false);
+}
+
+/**
+ * Initialise the callback pointer and return the contexte to the Upper layers
+ *
+ * \param ctx the sar context
+ * \param sar_rea_done inform the upper layers that the buffer is filled.
+ * \param data a boolean to indicate if it is a data stream or not.
+ */
+void sar_init_reassembly_ul (sar_t *ctx,
+ sar_reassembly_done_cb_t sar_rea_done, bool data);
+
+/**
+ * Initialize the callback pointer and return the contexte to the Control Plane
+ * to manage MME data
+ *
+ * \param ctx the sar context
+ * \param sar_mme_reassembly_done the function to call when the bridge DMA ends a job.
+ */
+extern inline void sar_init_reassembly_mme_cb (sar_t *ctx,
+ sar_reassembly_done_cb_t sar_mme_reassembly_done)
+{
+ sar_init_reassembly_ul (ctx, sar_mme_reassembly_done, false);
+}
+
+/**
+ * Initialize the callback pointer and return the contexte to the Convergence
+ * layer to manage data
+ *
+ * \param ctx the sar context
+ * \param sar_data_reassembly_done the function to call when the bridge DMA ends a job.
+ */
+extern inline void sar_init_reassembly_data_cb (sar_t *ctx,
+ sar_reassembly_done_cb_t sar_data_reassembly_done)
+{
+ sar_init_reassembly_ul (ctx, sar_data_reassembly_done, true);
+}
+
+/**
+ * MPDU RX callback.
+ * \param user user data
+ * \param mfs mfs for this RX or NULL
+ * \param mme mfs mme for this RX or NULL
+ * \param rx_params more parameters from this MPDU
+ * \param pb_first first PB descriptor
+ * \param pb_last last PB descriptor
+ * \param pb_nb number of PB
+ * \param chandata_first first channel data descriptor
+ * \param nb_chandata the quantity of PBs provided.
+ *
+ * When the mfs does not exist, \a mfs is NULL and the upper layer may create
+ * it.
+ *
+ */
+void sar_mpdu_add (void *user, mfs_t *mfs, mfs_t *mme,
+ const pbproc_rx_params_t *rx_params, pb_t *pb_first, pb_t *pb_last,
+ uint pb_nb, pb_t *chandata_first, uint nb_chandata);
+
+/** Call by convergence layer or control plane to add data in transmit data
+ * path
+ * Add new data in the to_tx_list defined in segmentation.h
+ *
+ * \param ctx sar context
+ * \param buffer the buffer address containing the data to segment
+ * \param length the type and length of the data
+ * \param ats_confounder
+ * \param mfs the mfs to stock the PB generated
+ *
+ * \return bool true if correctly inserted
+ */
+bool sar_msdu_add (sar_t *ctx, u8 *buffer, u16 length, u32 ats_confounder,
+ mfs_tx_t *mfs);
+
+/** Add a MFS to the SAR.
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to add to the SAR.
+ */
+void sar_mfs_add (sar_t *ctx, mfs_t *mfs);
+
+/** Remove a MFS from the SAR
+ *
+ * \param ctx the sar context
+ * \param mfs the mfs to remove from the SAR.
+ */
+void sar_mfs_remove (sar_t *ctx, mfs_t *mfs);
+
+/**
+ * Provides the beacon to the Control plane
+ *
+ * \param sar the sar context
+ * \param user_data
+ * \param uf upper layer function call
+ */
+void sar_init_beacon_cb (sar_t *sar, void *user_data, sar_beacon_cb_t uf);
+
+/**
+ * add a beacon to the SAR.
+ * It will provide it to the CP to process the beacon.
+ *
+ * \param sar the sar context
+ * \param pb pb containing the beacon
+ * \param params the rx params.
+ */
+void sar_beacon_add (void *sar, pb_beacon_t *pb,
+ pbproc_rx_beacon_params_t *params);
+
+/**
+ * Request the SAR to send a beacon.
+ *
+ * \param ctx the sar context.
+ * \param beacon the beacon to send.
+ * \param beacon_mfs the mfs use to send the beacon
+ * \param bto_bpsto the address to provide to the pbproc.
+ */
+void
+sar_beacon_send (sar_t *sar, pb_beacon_t *beacon, mfs_tx_t *beacon_mfs, void
+ *bto_bpsto);
+
+/**
+ * Sar procedure
+ * Launch the SAR.
+ *
+ * \param sar the sar context.
+ */
+void sar_launch (sar_t *sar);
+
+/**
+ * Return the quantoty of message still available in the sar mailbox.
+ *
+ * \param ctx the sar context
+ */
+uint sar_mailbox_state (sar_t *ctx);
+
+/**
+ * Get the sar expiration context to add or remove MFS from the sar expiration
+ * mechanism.
+ *
+ * \param ctx the sar context
+ * \param cb the callback function to inform the upper layer when a MFS will
+ * expire, not used if the MFS is a plid kind.
+ */
+void sar_init_expiration (sar_t *ctx, sar_mfs_expired_cb_t cb);
+
+void sar_process (cyg_addrword_t data);
+
+#endif /*MAC_SAR_SAR_H_*/
diff --git a/cesar/mac/sar/sar_mfs_expiration_cb.h b/cesar/mac/sar/sar_mfs_expiration_cb.h
new file mode 100644
index 0000000000..d1516ba90a
--- /dev/null
+++ b/cesar/mac/sar/sar_mfs_expiration_cb.h
@@ -0,0 +1,24 @@
+#ifndef MAC_SAR_SAR_MFS_EXPIRATION_CB_H_
+#define MAC_SAR_SAR_MFS_EXPIRATION_CB_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mfs_expiration_cb.h
+ * \brief sar expiration callback
+ * \ingroup mac/sar/
+ *
+ */
+
+#include "mac/common/mfs.h"
+
+/** Call back to prevent the upper layers when a MFS had expired
+ * Only used when it is a not PLID MFS */
+typedef void (*sar_mfs_expired_cb_t) (void *user, mfs_t *mfs);
+
+#endif /*MAC_SAR_SAR_MFS_EXPIRATION_CB_H_*/
diff --git a/cesar/mac/sar/src/bridge_dma.c b/cesar/mac/sar/src/bridge_dma.c
new file mode 100644
index 0000000000..5ceee75be9
--- /dev/null
+++ b/cesar/mac/sar/src/bridge_dma.c
@@ -0,0 +1,155 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/src/bridge_dma.c
+ * \brief header for the bridge dma launch.
+ * \ingroup mac_sar
+ */
+
+#include "common/std.h"
+#include "mac/sar/inc/bridge_dma.h"
+
+/**
+ * Initialize the list of jobs for the bridge DMA.
+ */
+void bridge_dma_list_init (sar_bridge_dma_list_t *list)
+{
+ list->head = NULL;
+ list->tail = NULL;
+}
+
+/**
+ * Return the head of the list and remove it from the list
+ *
+ * \param list the list to get the head
+ * \return the head of the lsit
+ */
+sar_job_mfs_t * bridge_dma_get_head (sar_bridge_dma_list_t *list)
+{
+ dbg_assert (list);
+ sar_job_mfs_t *job = NULL;
+
+ dbg_assert (list);
+
+ if (list->head == list->tail)
+ {
+ job = list->head;
+ list->head = NULL;
+ list->tail = NULL;
+ }
+ else if (list->head != NULL)
+ {
+ job = list->head;
+ list->head = list->head->next;
+ }
+
+ return job;
+}
+
+/**
+ * Add a job to the bridge dma list
+ *
+ * \param bridge_list the list in which the job must be added
+ * \param head the head chain list
+ * \param last the tail of the chain list.
+ */
+void bridge_dma_add_jobs (sar_bridge_dma_list_t *bridge_list,
+ sar_job_mfs_t *head, sar_job_mfs_t *last)
+{
+ dbg_assert (bridge_list);
+ dbg_assert (head);
+ dbg_assert (last);
+
+ if (bridge_list->tail == NULL)
+ {
+ bridge_list->head = head;
+ bridge_list->tail = last;
+ last->job.last = true;
+ }
+ else
+ {
+ bridge_list->tail->job.last = false;
+ bridge_list->tail->next = head;
+ bridge_list->tail = last;
+ last->job.last = true;
+ }
+}
+
+/**
+ * Add a job to the tx/rx pending job list
+ *
+ * \param list the bridge dma list to add the job
+ * \param head the job mfs to add to the list
+ */
+void bridge_dma_add_pending_job (sar_bridge_dma_list_t *list,
+ sar_job_mfs_t *head)
+{
+ dbg_assert (list);
+ dbg_assert (head);
+
+ if (list->head == NULL)
+ {
+ list->head = head;
+ list->tail = head;
+ }
+ else
+ {
+ list->tail->next = head;
+ list->tail = head;
+ }
+
+ head->next = NULL;
+}
+
+/**
+ * Verify the if a list is empty.
+ *
+ * \return boolean indicating is the state of the list
+ */
+bool bridge_dma_list_is_empty (sar_bridge_dma_list_t *list)
+{
+ dbg_assert (list);
+
+ if (list->head == NULL)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Remove all the jobs in the list and release the mfs and PBs in it.
+ *
+ * \param list the list to uninit.
+ */
+void bridge_dma_uninit_list (sar_bridge_dma_list_t *list)
+{
+ dbg_assert (list);
+
+ sar_job_mfs_t *job_mfs;
+ pb_t *pb_curr;
+
+ //release all pending jobs.
+ while ( (job_mfs = bridge_dma_get_head (list))!= NULL)
+ {
+ // release the PB in the job
+ while (job_mfs->job.first_pb_desc)
+ {
+ pb_curr = (pb_t *) job_mfs->job.first_pb_desc;
+ job_mfs->job.first_pb_desc = job_mfs->job.first_pb_desc->next;
+ blk_release_desc ((blk_t *) pb_curr);
+ }
+
+ blk_release ((blk_t *) job_mfs->mfs);
+ blk_release ((blk_t *) job_mfs);
+ }
+
+ list->head = NULL;
+ list->tail = NULL;
+}
diff --git a/cesar/mac/sar/src/sar.c b/cesar/mac/sar/src/sar.c
new file mode 100644
index 0000000000..6379897321
--- /dev/null
+++ b/cesar/mac/sar/src/sar.c
@@ -0,0 +1,1751 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar.c
+ * \brief sar source functions.
+ * \ingroup mac/sar/src/
+ *
+ * All the necessary functions to for the SAR.
+ *
+ */
+#include "common/std.h"
+#include "mac/sar/sar.h"
+#include "lib/read_word.h"
+#include "mac/common/timings.h"
+#include "mac/common/ntb.h"
+
+#include "mac/pbproc/pbproc.h"
+
+#include "mac/sar/inc/sar_context.h"
+#include "mac/sar/inc/sar_mfs.h"
+#include "mac/sar/inc/sar.h"
+
+#define SAR_PBPOOL_SIZE 250
+
+static struct sar_t sar_global;
+
+/**
+ * Initialize the sar context.
+ *
+ * \param mac_store the mac store
+ * \param pbproc the pbproc context.
+ * \param ca the channel access context
+ * \return the sar context.
+ */
+sar_t *sar_init (mac_store_t *mac_store, pbproc_t *pbproc, ca_t *ca)
+{
+ sar_t *ctx;
+ dbg_assert (mac_store);
+ dbg_assert (pbproc);
+
+ // Initialize the bridge dma job pending list.
+ bridge_dma_list_init (&sar_global.bridge_dma_jobs);
+
+ // Init the expiration
+ sar_expiration_init (&sar_global.expiration, ca);
+
+ // Creates the mailbox to stock the message work
+ cyg_mbox_create (&sar_global.mailbox_handle, &sar_global.mailbox);
+
+ //callbacks
+ sar_global.sar_seg_data_done_cb = NULL;
+ sar_global.sar_seg_msg_done_cb = NULL;
+ sar_global.sar_measurement = NULL;
+ sar_global.beacon_function_cb = NULL;
+
+ //reassembly
+ sar_reassembly_init (&sar_global.data_ctx, sar_global.data_slots, SAR_NUMBER_OF_SLOTS_DATA);
+ sar_reassembly_init (&sar_global.mme_ctx, sar_global.mme_slots, SAR_NUMBER_OF_SLOTS_MSG);
+
+ // Init the expiration process
+ sar_expiration_init (&sar_global.expiration, ca);
+ // init the mac store ctx in the sar.
+ sar_global.expiration.mfs_store = mac_store;
+
+ //pbproc
+ sar_global.pbproc_ctx = pbproc;
+ pbproc_init_cb (pbproc, &sar_global, sar_mpdu_add, sar_beacon_add);
+
+ // Init the bridgedma context by giving the functions to call back when a
+ // job had been bridge.
+ sar_global.bridgedma_ctx = phy_bridgedma_init (&sar_global,
+ bridge_dma_interruption, bridge_dma_deffered_interruption);
+
+ /** Upper layers init. */
+ sar_global.beacon_user_data = NULL;
+ sar_global.ul_ce_ctx = NULL;
+ sar_global.ul_data_ctx = NULL;
+ sar_global.ul_msg_ctx = NULL;
+
+ /* Fill the PBPOOL */
+ pb_pool_refill (&sar_global, SAR_PBPOOL_SIZE);
+
+ /** Trace system. */
+ ctx = &sar_global;
+ sar_trace_init(ctx);
+
+ SAR_TRACE (INIT, mac_ntb());
+
+ // Create the Thread for the SAR.
+ cyg_thread_create (SAR_THREAD_PRIORITY, &sar_process, (cyg_addrword_t) ctx,
+ "SAR", ctx->thread_stack, SAR_THREAD_STACK_SIZE,
+ &ctx->thread_handle, &ctx->thread);
+
+ /* Resume the thread only if the SAR is not in unit test. */
+#ifndef SAR_UNIT_TEST
+ cyg_thread_resume (ctx->thread_handle);
+#endif
+
+ return &sar_global;
+}
+
+/**
+ * Initialize the reassembly context
+ *
+ * \param ctx the sar reassembly context
+ * \param buffer the buffer to stock the addresses.
+ * \param nb_slots the quantity of slots.
+ */
+void sar_reassembly_init (sar_reassembly_ctx_t *ctx, u8 **buffer, uint nb_slots)
+{
+ dbg_assert (ctx);
+
+ ctx->sar_rea_done = NULL;
+ bridge_dma_list_init (&ctx->jobs_pending_list);
+ circular_buffer_init (&ctx->buffer_address_list, buffer, nb_slots);
+}
+
+/**
+ * Add the upper data layer context to the SAR. It allows the sar to use
+ * the context in the callbacks to this layer.
+ *
+ * \param ctx the sar context
+ * \param user the upper layer data context.
+ */
+void sar_init_data_context (sar_t *ctx, void *user)
+{
+ dbg_assert (ctx);
+
+ ctx->ul_data_ctx = user;
+}
+
+/**
+ * Add the upper data layer context to the SAR. It allows the sar to use
+ * the context in the callbacks to this layer.
+ *
+ * \param ctx the sar context
+ * \param user the upper layer msg context.
+ */
+void sar_init_mme_context (sar_t *ctx, void *user)
+{
+ dbg_assert (ctx);
+
+ ctx->ul_msg_ctx = user;
+}
+
+/**
+ * Add the upper data layer context to the SAR. It allows the sar to use
+ * the context in the callbacks to this layer.
+ *
+ * \param ctx the sar context
+ * \param user the upper layer msg context.
+ */
+void sar_init_measure_context (sar_t *ctx, void *user)
+{
+ dbg_assert (ctx);
+
+ ctx->ul_ce_ctx = user;
+}
+
+/**
+ * Used by the upper layers to send or received messages.
+ *
+ * \param ctx the sar context
+ * \param sar_seg_done used by the segmentation to inform the upper layer the
+ * buffer is not used anymore.
+ */
+void sar_init_segmentation_mme_cb (sar_t *ctx,
+ sar_segmentation_done_cb_t sar_seg_done)
+{
+ dbg_assert (ctx);
+
+ ctx->sar_seg_msg_done_cb = sar_seg_done;
+}
+
+/**
+ * Used to inform the upper layer when a Data has been provided to the CA.
+ *
+ * \param ctx the sar context
+ * \param sar_seg_done used by the segmentation to inform the upper layer the
+ * buffer is not used anymore.
+ */
+void sar_init_segmentation_data_cb (sar_t *ctx,
+ sar_segmentation_done_cb_t sar_seg_done)
+{
+ dbg_assert (ctx);
+
+ ctx->sar_seg_data_done_cb = sar_seg_done;
+}
+
+/**
+ * Initialise the callback pointer and return the contexte to the Upper layers
+ *
+ * \param ctx the sar context
+ * \param sar_rea_done inform the upper layers that the buffer is filled.
+ * \param data a boolean to indicate if it is a data stream or not.
+ */
+void sar_init_reassembly_ul (sar_t *ctx,
+ sar_reassembly_done_cb_t sar_rea_done, bool data)
+{
+ dbg_assert (ctx);
+
+ if (data)
+ {
+ dbg_assert (ctx->ul_data_ctx);
+
+ bridge_dma_list_init (&ctx->data_ctx.jobs_pending_list);
+ ctx->data_ctx.sar_rea_done = sar_rea_done;
+
+ circular_buffer_init (&ctx->data_ctx.buffer_address_list,
+ ctx->data_slots, SAR_NUMBER_OF_SLOTS_DATA);
+ }
+ else
+ {
+ dbg_assert (ctx->ul_msg_ctx);
+
+ bridge_dma_list_init (&ctx->mme_ctx.jobs_pending_list);
+
+ circular_buffer_init (&ctx->mme_ctx.buffer_address_list,
+ ctx->mme_slots, SAR_NUMBER_OF_SLOTS_MSG);
+
+ ctx->mme_ctx.sar_rea_done = sar_rea_done;
+ }
+}
+
+/**
+ * Initialize the callback to send the measurement contained in the PBs.
+ *
+ * \param ctx the sar context
+ * \param sar_measurement the function to call to get the buffers to stock
+ * the measurements.
+ */
+void sar_init_measurement_cb (sar_t *ctx, sar_measurement_cb_t sar_measurement)
+{
+ dbg_assert (ctx);
+
+ ctx->sar_measurement = sar_measurement;
+}
+
+/**
+ * Get the sar expiration context to add or remove MFS from the sar expiration
+ * mechanism.
+ *
+ * \param ctx the sar context
+ * \param cb the callback function to inform the upper layer when a MFS will
+ * expire, not used if the MFS is a plid kind.
+ */
+void sar_init_expiration (sar_t *ctx, sar_mfs_expired_cb_t cb)
+{
+ dbg_assert (ctx);
+ dbg_assert (ctx->ul_msg_ctx);
+
+ ctx->expiration.mfs_expiration_cb = cb;
+}
+
+/**
+ * Release all the data used in the sar.
+ *
+ * \param ctx the sar context.
+ */
+void sar_uninit (sar_t *ctx)
+{
+ cyg_thread_suspend (ctx->thread_handle);
+ cyg_thread_delete (ctx->thread_handle);
+
+ bridge_dma_uninit_list (&ctx->bridge_dma_jobs);
+
+ cyg_mbox_delete (ctx->mailbox_handle);
+
+ sar_expiration_uninit (&ctx->expiration);
+
+ phy_bridgedma_uninit(ctx->bridgedma_ctx);
+
+ sar_trace_uninit (ctx);
+}
+
+/**
+ * Add a buffer address to the sar to bridge pending jobs.
+ *
+ * \param ctx the sar context to add a buffer
+ * \param buffer_addr the buffer address to add to the sar in order to bridge
+ * the pending jobs.
+ * \param data if it is a data buffer.
+ * \return true if the buffer had been added, false, otherwise.
+ */
+bool sar_buffer_add (sar_t *ctx, u8* buffer_addr, bool data)
+{
+ sar_work_message_t *work;
+ bool result;
+
+ work = blk_alloc ();
+
+ if (data)
+ {
+ work->ctx = &ctx->data_ctx;
+ SAR_TRACE (DATA_BUFFER_ADD, mac_ntb(), buffer_addr);
+ }
+ else
+ {
+ work->ctx = &ctx->mme_ctx;
+ SAR_TRACE (MME_BUFFER_ADD, mac_ntb(), buffer_addr);
+ }
+
+ work->msg.buffer_addr = buffer_addr;
+ work->type = ADD_BUFFER;
+
+ result = circular_buffer_add (&work->ctx->buffer_address_list,
+ work->msg.buffer_addr);
+
+ if (result)
+ {
+ result = cyg_mbox_put (ctx->mailbox_handle, (void*) work);
+ SAR_TRACE (MBOX, mac_ntb(), cyg_mbox_peek (ctx->mailbox_handle));
+ }
+
+ return result;
+}
+
+/**
+ * MPDU RX callback.
+ * \param user user data
+ * \param mfs mfs for this RX or NULL
+ * \param mme mfs mme for this RX or NULL
+ * \param rx_params more parameters from this MPDU
+ * \param pb_first first PB descriptor
+ * \param pb_last last PB descriptor
+ * \param pb_nb number of PB
+ * \param chandata_first first channel data descriptor
+ * \param nb_chandata the quantity of PBs provided.
+ *
+ * When the mfs does not exist, \a mfs is NULL and the upper layer may create
+ * it.
+ *
+ */
+void sar_mpdu_add (void *user, mfs_t *mfs, mfs_t *mme,
+ const pbproc_rx_params_t *rx_params, pb_t *pb_first, pb_t *pb_last,
+ uint pb_nb, pb_t *chandata_first, uint nb_chandata)
+{
+ sar_t *ctx;
+ sar_work_message_t *rx;
+
+ dbg_assert (rx_params);
+ dbg_assert (user);
+
+ if (mfs)
+ dbg_assert (mfs->common.mme == false);
+ if (mme)
+ dbg_assert (mme->common.mme == true);
+
+ ctx = (sar_t *) user;
+
+ rx = blk_alloc ();
+ rx->msg.mpdu.rx_params = blk_alloc ();
+
+ if (mfs)
+ blk_addref (mfs);
+ if (mme)
+ blk_addref (mme);
+
+ rx->type = REA;
+ *(rx->msg.mpdu.rx_params) = *rx_params;
+ rx->msg.mpdu.chandata = chandata_first;
+ rx->msg.mpdu.nb_chandata = nb_chandata;
+ rx->msg.mpdu.mfs = (mfs_rx_t *) mfs;
+ rx->msg.mpdu.mme = (mfs_rx_t *) mme;
+ rx->msg.mpdu.head = pb_first;
+ rx->msg.mpdu.tail = pb_last;
+ rx->msg.mpdu.number = pb_nb;
+ rx->msg.mpdu.expiration_ntb = rx_params->preamble_ntb;
+
+ if (pb_nb)
+ {
+ pb_last->next = NULL;
+ }
+
+ cyg_mbox_put (((sar_t *)user)->mailbox_handle, (void*) rx);
+
+ /** Tracing system. */
+ SAR_TRACE (MPDU_ADD, mac_ntb(), rx_params->tei, rx_params->lid, mfs, mme, pb_nb);
+ SAR_TRACE (MBOX, mac_ntb(), cyg_mbox_peek (ctx->mailbox_handle));
+}
+
+/** Call by convergence layer or control plane to add data in transmit data
+ * path
+ * Add new data in the to_tx_list defined in segmentation.h
+ *
+ * \param ctx sar context
+ * \param buffer the buffer address containing the data to segment
+ * \param length the type and length of the data
+ * \param ats_confounder
+ * \param mfs the mfs to stock the PB generated
+ *
+ * \return bool true if correctly inserted
+ */
+bool sar_msdu_add (sar_t *ctx, u8 *buffer, u16 length, u32 ats_confounder,
+ mfs_tx_t *mfs)
+{
+ sar_work_message_t *work;
+ bool res;
+
+ dbg_assert (ctx);
+ dbg_assert (mfs);
+ dbg_assert (mfs->common.tx);
+
+ blk_addref (mfs);
+
+ work = (sar_work_message_t *) blk_alloc ();
+
+ work->msg.msdu.ats_confounder = ats_confounder;
+ work->msg.msdu.length = length;
+ work->msg.msdu.mfs = mfs;
+ work->msg.msdu.buffer_address = buffer;
+ work->type = SEG;
+
+ SAR_TRACE (MSDU_ADD, mac_ntb(), buffer, length, mfs->common.tei, mfs->common.lid,
+ mfs->common.mme);
+
+ res = cyg_mbox_put (ctx->mailbox_handle, work);
+ SAR_TRACE (MBOX, mac_ntb(), cyg_mbox_peek (ctx->mailbox_handle));
+ return res;
+}
+
+/** Add a MFS to the SAR.
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to add to the SAR.
+ */
+void sar_mfs_add (sar_t *ctx, mfs_t *mfs)
+{
+ dbg_assert (ctx);
+ dbg_assert (mfs);
+ sar_expiration_mfs_add (&ctx->expiration, mfs);
+
+ SAR_TRACE (MFS_ADD, mac_ntb(), mfs->common.tx, mfs->common.mme, mfs->common.tei, mfs->common.lid);
+}
+
+/** Remove a MFS from the SAR
+ *
+ * \param ctx the sar context
+ * \param mfs the mfs to remove from the SAR.
+ */
+void sar_mfs_remove (sar_t *ctx, mfs_t *mfs)
+{
+ dbg_assert (ctx);
+ dbg_assert (mfs);
+ sar_expiration_mfs_remove (&ctx->expiration, mfs);
+
+ SAR_TRACE (MFS_REMOVE, mac_ntb(), mfs->common.tx, mfs->common.mme, mfs->common.tei, mfs->common.lid);
+}
+
+/**
+ * Add a job to the bridge dma list
+ *
+ * \param ctx the sar context.
+ * \param head the first job for the bridge dma
+ * \param last the last job for the bridge dma
+ */
+void bridge_dma_add_job_to_process (sar_t *ctx, sar_job_mfs_t *head,
+ sar_job_mfs_t *last)
+{
+ dbg_assert (ctx);
+
+ bridge_dma_add_jobs (&ctx->bridge_dma_jobs, head, last);
+ phy_bridgedma_start (ctx->bridgedma_ctx, &head->job, &last->job);
+}
+
+/**
+ * Remove the first job of the bridge dma list
+ * Release all the PBs in it.
+ *
+ * \param ctx the sar context
+ */
+void
+bridge_dma_free_head (sar_t *ctx)
+{
+ sar_job_mfs_t *job;
+ dbg_assert (ctx);
+
+ /* Get the head of the list i.e. unleashed it from the bridge_dma_jobs
+ * and put it in the job.
+ */
+ if ((job = bridge_dma_get_head (&ctx->bridge_dma_jobs)) != NULL)
+ {
+ //tx transmission
+ if (!job->job.direction)
+ {
+ mfs_tx_t *local_mfs;
+
+ local_mfs = &job->mfs->tx;
+ job->mfs->tx.pending_jobs --;
+
+ if (job->mfs->tx.pending_jobs
+ && (job->last_pb_offset != BLK_SIZE))
+ {
+ pbproc_mfs_provide (&job->mfs->tx, job->pb_quantity - 1);
+ }
+ else
+ {
+ pbproc_mfs_provide (&job->mfs->tx, job->pb_quantity);
+ }
+
+ ca_mfs_update (ctx->expiration.ca, &job->mfs->tx);
+
+
+ if (local_mfs->common.mme)
+ {
+ dbg_assert (ctx->sar_seg_msg_done_cb);
+ (*ctx->sar_seg_msg_done_cb) (ctx->ul_msg_ctx,
+ job->job.data_addr);
+ }
+ else
+ {
+ dbg_assert (ctx->sar_seg_data_done_cb);
+ (*ctx->sar_seg_data_done_cb) (ctx->ul_data_ctx,
+ job->job.data_addr);
+ }
+ }
+ // RX transmission
+ else
+ {
+ /* If the CRC error is not raised i.e. THE checksum is correct. */
+ if (!job->job.crc_error)
+ {
+ if (((mfs_rx_t *) job->mfs)->common.mme)
+ {
+ uint cpt;
+ bool encrypted;
+ bool sta_auth;
+ pb_t *pb;
+ sta_t *sta;
+
+ /** Check if the Frame is encrypted. */
+ encrypted = false;
+ sta_auth = false;
+ for (cpt = job->pb_quantity, pb = (pb_t *)job->job.first_pb_desc;
+ pb && cpt; pb = pb->next, cpt --)
+ {
+ encrypted &= pb->header.spc_encrypted;
+ sta_auth |= pb->header.spc_encrypted;
+ }
+
+ /* Verify the station status. */
+ sta = mac_store_sta_get (ctx->expiration.mfs_store,
+ ((mfs_rx_t *) job->mfs)->common.tei);
+ if (sta && sta_auth)
+ {
+ sta->authenticated = true;
+ blk_release (sta);
+ }
+
+ dbg_assert (ctx->mme_ctx.sar_rea_done);
+ (*ctx->mme_ctx.sar_rea_done) (ctx->ul_msg_ctx,
+ job->job.data_addr, job->job.data_len,
+ (mfs_rx_t *)job->mfs, encrypted);
+ }
+ else
+ {
+ dbg_assert (ctx->data_ctx.sar_rea_done);
+ (*ctx->data_ctx.sar_rea_done) (ctx->ul_data_ctx,
+ job->job.data_addr, job->job.data_len,
+ (mfs_rx_t *) job->mfs, true);
+ }
+ }
+ else
+ {
+ /* Keep the buffer for another reassembly. */
+ sar_buffer_add (ctx, job->job.data_addr, !((mfs_rx_t *) job->mfs)->common.mme);
+ }
+
+ for (; job->pb_quantity; job->pb_quantity --)
+ {
+ job->job.first_pb_desc
+ = (blk_t *) pb_free ( (pb_t *)job->job.first_pb_desc);
+ }
+ }
+
+ /* tracing */
+ SAR_TRACE (BRIDGE, mac_ntb(), job->job.data_addr, job->job.direction, job->mfs->common.mme,
+ job->mfs->common.tei, job->mfs->common.lid,
+ job->job.crc_error);
+
+ blk_release (job->mfs);
+ blk_release (job);
+ }
+}
+
+/**
+ * Function called by the phy hal when the bridge return an IT
+ *
+ * \param user user data
+ * \param status_word l'etat du bridge
+ */
+bool bridge_dma_interruption (void *user, u32 status_word)
+{
+ sar_work_message_t *work;
+ sar_t *ctx;
+
+ dbg_assert (user);
+ ctx = (sar_t *) user;
+
+ work = blk_alloc ();
+ work->type = BRIDGE;
+ work->msg.bridge_direction = ctx->bridge_dma_jobs.head->job.direction;
+
+ cyg_mbox_put (ctx->mailbox_handle, work);
+ SAR_TRACE (MBOX, mac_ntb(), cyg_mbox_peek(ctx->mailbox_handle));
+
+ return true;
+}
+
+/**
+ * Function called by the phy hal when the bridge return an IT
+ *
+ * \param user, user data
+ */
+void bridge_dma_deffered_interruption (void *user)
+{
+
+}
+
+/**
+ * Allocate a new list of chained PB of the size of pb_nb to give it to the
+ * pbproc.
+ *
+ * \param ctx the sar context
+ * \param pb_nb the quantity of PBs to allocate.
+ */
+void pb_pool_refill (sar_t *ctx, uint pb_nb)
+{
+ pb_t *head = NULL;
+ pb_t *tail = NULL;
+
+ dbg_assert (ctx);
+ dbg_assert (ctx->pbproc_ctx);
+ dbg_assert (pb_nb);
+
+ if (pb_nb > 1)
+ {
+ head = (pb_t *) blk_alloc_desc_range (pb_nb, (blk_t **) &tail);
+ }
+ else if (pb_nb == 1)
+ {
+ head = (pb_t *) blk_alloc_desc ();
+ tail = head;
+ }
+
+ tail->next = NULL;
+ pbproc_rx_segment_refill (ctx->pbproc_ctx, head, tail, pb_nb);
+}
+
+/**
+ * Get the first work to do by the SAR
+ *
+ * \param ctx the sar context.
+ * \return the work message
+ */
+sar_work_message_t* sar_work_get (sar_t *ctx)
+{
+ mfs_t *mfs;
+ u32 delay = 100;
+ cyg_resolution_t res;
+ u32 tck_per_rtc;
+ sar_work_message_t *work;
+
+ res = cyg_clock_get_resolution (cyg_real_time_clock ());
+ tck_per_rtc = MAC_MS_TO_TCK (1000LL) * res.dividend / res.divisor /
+ 1000000000LL;
+
+ mfs = sar_expiration_get_mfs (&ctx->expiration);
+
+ if (mfs != NULL)
+ {
+ if ((delay = mfs->common.expiration_delay_ntb))
+ {
+ delay += mfs->common.expiration_ntb;
+ }
+
+ if (mfs->common.tx)
+ {
+ if (mfs->tx.head&& delay > mfs->tx.head->expiration_ntb)
+ {
+ delay = mfs->tx.head->expiration_ntb;
+ }
+ }
+ else
+ {
+ if (mfs->rx.head&& delay > mfs->rx.head->expiration_ntb)
+ {
+ delay = mfs->rx.head->expiration_ntb;
+ }
+ }
+
+ delay = delay / tck_per_rtc;
+ }
+
+ work = (sar_work_message_t *) cyg_mbox_timed_get (ctx->mailbox_handle,
+ cyg_current_time() + delay + SAR_GET_WORK_DELAY_RTC);
+
+ SAR_TRACE (MBOX, mac_ntb(), cyg_mbox_peek(ctx->mailbox_handle));
+ return work;
+}
+
+/**
+ * Launch the reassembly process to realize reassembly a new mpdu.
+ *
+ * \param ctx the sar context
+ * \param rx the rx data to process
+ */
+void reassembly_run (sar_t *ctx, sar_mpdu_t *rx)
+{
+ dbg_assert (ctx);
+ dbg_assert (rx);
+
+ pb_pool_refill (ctx, rx->number + rx->nb_chandata);
+
+ /** If the message only contains chandata.
+ * send the noise measurements to the CE. */
+ if (rx->chandata && !rx->head)
+ {
+ (*ctx->sar_measurement) (ctx->ul_ce_ctx, rx->rx_params, rx->number,
+ NULL, NULL, rx->chandata, rx->nb_chandata, NULL);
+ }
+ else
+ {
+ /* Verify if the MPDU has not expire before it can be reassemblied by
+ * the SAR. */
+ if (rx->expiration_ntb + SAR_MAX_REASSEMBLY_TIMER_NTB
+ <= mac_ntb())
+ {
+ SAR_TRACE (MSDU_EXP, mac_ntb(), rx->rx_params->tei,
+ rx->rx_params->lid);
+ pb_free_range (rx->head);
+ rx->head = NULL;
+ return;
+ }
+
+ rx_mpdu_process (ctx, rx);
+
+ if (rx->mfs)
+ {
+ sar_expiration_mfs_update_date (&ctx->expiration,
+ (mfs_t *) rx->mfs, mac_ntb());
+ rx_mfs_process (ctx, rx->mfs);
+ rx_upper_layer_transmit_data (ctx, &ctx->data_ctx);
+
+ blk_release (rx->mfs);
+ }
+
+ if (rx->mme)
+ {
+ sar_expiration_mfs_update_date (&ctx->expiration,
+ (mfs_t *) rx->mme, mac_ntb());
+ rx_mfs_process (ctx, rx->mme);
+ rx_upper_layer_transmit_data (ctx, &ctx->mme_ctx);
+
+ blk_release (rx->mme);
+ }
+ }
+}
+
+/**
+ * Parse the chain of PBs recevived from the pb proc.
+ * - Verifies if the PB is valid
+ * - Transmit the data to the CE.
+ * - Update the mfs window according with the HomePlug AV specification.
+ * - Verifies if the PB is in the window
+ * - Insert it in the right place in the corresponding MFS.
+ *
+ * \param ctx the sar context
+ * \param rx the mpdu_rx containing the PB to add to the MFS
+ */
+void rx_mpdu_process (sar_t *ctx, sar_mpdu_t * rx)
+{
+ mfs_rx_t *local_mfs = NULL;
+ pb_t *rx_head = NULL;
+ bool collect_measure;
+ uint blk_offset;
+ bool cont;
+
+ blk_t *blk_first;
+ blk_t *blk_last;
+ blk_t *blk_current;
+
+ dbg_assert (rx);
+ dbg_assert (ctx);
+ dbg_assert (ctx->sar_measurement);
+
+ //call the ce to get the blk to put the measurements
+ collect_measure = (*ctx->sar_measurement) (ctx->ul_ce_ctx,
+ rx->rx_params, rx->number, &blk_first, &blk_last, rx->chandata,
+ rx->nb_chandata, &blk_offset);
+ blk_current = blk_first;
+
+ rx_head = rx->head;
+ // Start to sort the mfs
+ while (rx_head != NULL)
+ {
+ dbg_assert (rx_head);
+ cont = true;
+
+ if (collect_measure)
+ {
+ dbg_assert (blk_current);
+ if (blk_offset == (BLK_SIZE >> 2))
+ {
+ blk_current = blk_last;
+ blk_offset = 0;
+ }
+
+ *((pb_measurement_t *)blk_current->data + blk_offset)
+ = rx_head->phy_pb.pb_rx.pb_measurement;
+ // the measurement is 32 bits long.
+ blk_offset ++;
+ }
+
+ //insert the expiration date in the PB
+ rx_head->expiration_ntb = rx->expiration_ntb;
+
+ if (!rx_head->header.vpbf
+ || rx_head->phy_pb.pb_rx.pb_measurement.crc_error
+ || ((!rx_head->header.mmqf) && (rx->rx_params->eks == MAC_EKS_CLEAR)))
+ {
+ SAR_TRACE (PB_ERROR, mac_ntb(), rx_head->header.ssn, rx->rx_params->tei,
+ rx->rx_params->lid);
+ // free the pb
+ rx_head = pb_free (rx_head);
+ cont = false;
+ }
+
+ if (cont && rx_head->header.mmqf && rx->rx_params->eks != MAC_EKS_CLEAR)
+ rx_head->header.spc_encrypted = true;
+ else if (cont)
+ rx_head->header.spc_encrypted = false;
+
+
+ /* If the lid is not a plid does not create the MFS
+ * All the segments are discarded */
+
+ if (cont && !(local_mfs = rx_get_associated_mfs (ctx, rx, rx_head)))
+ {
+ rx_head = pb_free (rx_head);
+ cont = false;
+ }
+
+ if (cont)
+ {
+ rx_mfs_resize_ssn (rx_head, local_mfs, rx->number);
+
+ // remove the PB if it is not in the window of the mfs
+ if (less_mod2p16 (rx_head->header.ssn, local_mfs->ssn_min)
+ || less_mod2p16 (rx_mfs_get_ssn_max (local_mfs),
+ rx_head->header.ssn))
+ {
+ SAR_TRACE (PB_SSN_NOT_IN_WIN, mac_ntb(), rx_head->header.ssn,
+ local_mfs->ssn_min, rx_mfs_get_ssn_max (local_mfs));
+ rx_head = pb_free (rx_head);
+ }
+ // PB in the window
+ else
+ {
+ // verify the state of the mfs if empty add the first_pb desc of the
+ // rx in the mfs
+ if (local_mfs->head == NULL)
+ {
+ local_mfs->head = rx_head;
+ rx_head = rx_head->next;
+ local_mfs->head->next = NULL;
+
+ rx_mfs_update_last_contiguous_and_tail (local_mfs,
+ local_mfs->head);
+ }
+ // if the PB is between the mfs->ssn_min and the head
+ else if (lesseq_mod2p16 (local_mfs->ssn_min,
+ rx_head->header.ssn) && less_mod2p16 (
+ rx_head->header.ssn, local_mfs->head->header.ssn))
+ {
+ pb_t *pb_tmp;
+
+ pb_tmp = rx_head->next;
+
+ rx_head->next = local_mfs->head;
+ local_mfs->head = rx_head;
+ rx_head = pb_tmp;
+
+ rx_mfs_update_last_contiguous_and_tail (local_mfs,
+ local_mfs->head);
+ }
+ // if the PB is between the tail and the mfs ssn max
+ else if (lesseq_mod2p16 (rx_head->header.ssn,
+ rx_mfs_get_ssn_max (local_mfs))&& less_mod2p16 (
+ local_mfs->tail->header.ssn, rx_head->header.ssn))
+ {
+ local_mfs->tail->next = rx_head;
+ rx_head = rx_head->next;
+ local_mfs->tail = local_mfs->tail->next;
+ local_mfs->tail->next = NULL;
+
+ rx_mfs_update_last_contiguous_and_tail (local_mfs,
+ local_mfs->last_contiguous);
+ }
+ // insert it between the last contiguous and the tail
+ else
+ {
+ pb_t *insert_after;
+
+ insert_after = rx_mfs_search_where_to_insert_pb (
+ local_mfs, rx_head->header.ssn);
+
+ if (insert_after != NULL)
+ {
+ rx_head = rx_mfs_add_pb_after (insert_after, rx_head);
+
+ // update the mfs last_contiguous from the old not
+ // contiguous
+ rx_mfs_update_last_contiguous_and_tail (local_mfs,
+ local_mfs->last_contiguous);
+ }
+ else
+ {
+ // free the pb
+ rx_head = pb_free (rx_head);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Create the job descriptor for the PBDMA to send the data to the CL.
+ *
+ * \param job the job to fill
+ * \param mfs the mfs to consider
+ * \param first_pb the first pb to use
+ * \param offset the offset to use in the pb
+ */
+void rx_job_desc_create (phy_bridgedma_job_t *job, mfs_rx_t *mfs,
+ pb_t *first_pb, u16 offset)
+{
+ /* Verify that the data are not null */
+ dbg_assert (job);
+ dbg_assert (mfs);
+ dbg_assert (first_pb);
+
+ job->first_pb_desc = (blk_t *) first_pb;
+ job->first_pb_offset = offset;
+ job->data_len = mf_get_length (first_pb, offset, true);
+ job->segment_len = BLK_SIZE;
+
+ /* Fill the header of the job */
+ switch (mf_get_type (first_pb, offset))
+ {
+ case 1:
+ job->header_len = 2;
+ job->mf_header1 = read_u16_from_word (first_pb->data + offset);
+ job->mf_header2 = 0x0;
+ break;
+ default:
+ job->header_len = 6;
+ job->mf_header1 = read_u32_from_word (first_pb->data + offset);
+ job->mf_header2 = read_u16_from_word (first_pb->data + offset
+ + sizeof(u32));
+ }
+
+ offset += job->data_len + job->header_len + SAR_MF_ICV_SIZE;
+ if (offset < BLK_SIZE)
+ {
+ first_pb->header.mfbo = offset;
+ }
+ else
+ {
+ first_pb->header.mfbf = 0x0;
+ }
+}
+
+/**
+ * Get the mfs from mac store or create it using the rx_params lid and dtei.
+ *
+ * \param sar the sar context.
+ * \param rx the rx_mpdu
+ * \param pb the PB from which it is possible to know if it needs the mme mfs
+ * or the data mfs
+ *
+ * \return the mfs corresponding, or the new one.
+ */
+mfs_rx_t *rx_get_associated_mfs (sar_t *sar, sar_mpdu_t * rx, pb_t *pb)
+{
+ mfs_rx_t *local_mfs = NULL;
+ bool added;
+ bool mme;
+
+ dbg_assert (rx);
+ dbg_assert (pb);
+
+ mme = pb->header.mmqf;
+
+ if (mme && rx->mme)
+ return rx->mme;
+ else if (!mme && rx->mfs)
+ return rx->mfs;
+
+ if ((local_mfs = mac_store_mfs_get_rx (sar->expiration.mfs_store,
+ rx->rx_params->bcast, mme, mme ? MAC_LID_NONE
+ : rx->rx_params->lid, rx->rx_params->tei)))
+ {
+ if (mme)
+ rx->mme = local_mfs;
+ else
+ rx->mfs = local_mfs;
+
+ return local_mfs;
+ }
+
+ if (!mme && !MAC_LID_IS_PLID (rx->rx_params->lid))
+ return NULL;
+
+ local_mfs = mac_store_mfs_add_rx (sar->expiration.mfs_store,
+ rx->rx_params->bcast, mme, mme ? MAC_LID_NONE
+ : rx->rx_params->lid, rx->rx_params->tei, &added);
+
+ /* Configure the mfs created, only do this if the MFS has been created*/
+
+ local_mfs->head = NULL;
+ local_mfs->last_contiguous = NULL;
+ local_mfs->tail = NULL;
+ local_mfs->last_offset_processed = 0;
+
+ sar_mfs_add (sar, (mfs_t *) local_mfs);
+
+ if (mme)
+ rx->mme = local_mfs;
+ else
+ rx->mfs = local_mfs;
+
+ return local_mfs;
+}
+
+/**
+ * Search where the PB with the ssn given can be inserted in the chain.
+ *
+ * \param mfs the mfs to search
+ * \param ssn the ssn of the current pb
+ * \return - the last after the one the PB can be inserted in the list.
+ * - null if the chain is empty
+ * - null if it can not be inserted (the value already already
+ * exists in the chain).
+ */
+pb_t *rx_mfs_search_where_to_insert_pb (mfs_rx_t *mfs, u16 ssn)
+{
+ pb_t *start;
+
+ dbg_assert (mfs);
+
+ if (mfs->head == NULL || mfs->last_contiguous->header.ssn == ssn
+ || mfs->tail->header.ssn == ssn)
+ {
+ return NULL;
+ }
+
+ start = mfs->last_contiguous;
+ while (start->next != NULL && less_mod2p16 (start->next->header.ssn, ssn))
+ {
+ start = start->next;
+ }
+
+ if (less_mod2p16 (start->header.ssn, ssn))
+ {
+ return start;
+ }
+
+ return NULL;
+}
+
+/**
+ * Detect a MF in the MFS and try to reconstitute a MF from the given MFS.
+ *
+ * \param mfs the mac frame to process
+ * \return the new job if a MF could be reconstitute, NULL otherwise
+ */
+sar_job_mfs_t *rx_mfs_detect_and_reconstitute_mf (mfs_rx_t *mfs)
+{
+ pb_t *pb;
+ u32 pb_available;
+ sar_job_mfs_t *job;
+ u8 number_pb = 0;
+ uint type;
+
+ job = NULL;
+ dbg_assert (mfs);
+
+ if (mfs->head == NULL)
+ {
+ return NULL;
+ }
+
+ pb = mfs->head;
+ /* Try to find a MF at the begining of the PB */
+
+ do
+ {
+ type = mf_get_type (pb, mfs->last_offset_processed);
+ /* Verify type. */
+ if ((((type == 1) || (type == 2)) && !mfs->common.mme)
+ || (type ==3 && mfs->common.mme))
+ {
+ number_pb = mf_get_quantity_of_pb (pb,
+ mfs->last_offset_processed);
+ break;
+ }
+
+ if (pb->header.mfbf && mf_get_type (pb, pb->header.mfbo) != type)
+ {
+ mfs->last_offset_processed = pb->header.mfbo;
+ }
+ else
+ {
+ pb = pb_free (pb);
+ mfs->last_offset_processed = 0;
+ }
+ }
+ while (pb != NULL && number_pb == 0);
+
+ if (pb == NULL)
+ {
+ mfs->head = NULL;
+ mfs->tail = NULL;
+ mfs->last_contiguous = NULL;
+
+ return NULL;
+ }
+
+ mfs->head = pb;
+ rx_mfs_update_last_contiguous_and_tail (mfs, pb);
+
+ if (mfs->last_contiguous->header.ssn > mfs->head->header.ssn)
+ {
+ pb_available = mfs->last_contiguous->header.ssn
+ - (mfs->head->header.ssn - 1);
+ }
+ else
+ {
+ pb_available = mfs->head->header.ssn
+ - (mfs->last_contiguous->header.ssn - 1);
+ }
+
+ pb = mfs->head;
+ /* If no PBs are missing then launch the job creator */
+ if (number_pb && number_pb <= pb_available)
+ {
+ job = sar_job_mfs_create (false);
+ job->mfs = (mfs_t *) mfs;
+ job->pb_quantity = number_pb;
+
+ rx_job_desc_create (&job->job, mfs, pb, mfs->last_offset_processed);
+
+ // modify the mfs last offset processed if the MF is contained in one PB
+ mfs->last_offset_processed = mfs->last_offset_processed
+ + mf_get_length (pb, mfs->last_offset_processed, false);
+
+ mfs->last_offset_processed %= BLK_SIZE;
+
+ for (number_pb--; number_pb; number_pb--)
+ {
+ mfs->head = mfs->head->next;
+ }
+
+ // add ref on the last pb of the job
+ blk_addref_desc ((blk_t *) mfs->head);
+ blk_addref ((blk_t *) mfs);
+ }
+
+ return job;
+}
+
+/**
+ * Process the MFS to reconstitute MF until the MFS contains PBs or the MF
+ * can not be reconsitute because of missing PBs.
+ *
+ * \param ctx the sar context
+ * \param mfs the mfs to proccess.
+ */
+void rx_mfs_process (sar_t *ctx, mfs_rx_t * mfs)
+{
+ sar_job_mfs_t *job;
+ sar_reassembly_ctx_t *rea_ctx;
+
+ dbg_assert (mfs);
+
+ if (mfs->common.mme)
+ {
+ rea_ctx = &ctx->mme_ctx;
+ }
+ else
+ {
+ rea_ctx = &ctx->data_ctx;
+ }
+
+ while ((job = rx_mfs_detect_and_reconstitute_mf (mfs)))
+ {
+ bridge_dma_add_pending_job (&rea_ctx->jobs_pending_list, job);
+ }
+}
+
+/**
+ * Insert a PB after the PB this in the PBs chain
+ *
+ * \param this the pb which the new is the next
+ * \param new the Pb to insert
+ * \return the pb after new
+ */
+pb_t *rx_mfs_add_pb_after (pb_t *this, pb_t *new)
+{
+ pb_t *rx_tmp;
+
+ dbg_assert (this);
+ dbg_assert (new);
+
+ // insert the valid pb in the mfs
+ rx_tmp = new->next;
+
+ new->next = this->next;
+ this->next = new;
+
+ // go to the next pb
+ return rx_tmp;
+}
+
+/**
+ * Verify if one or various buffers are available for the CP. If they are the
+ * a list of jobs are chained to the bridge DMA job list to be processed.
+ *
+ * This function never loop cause of the implementation, When a buffer is
+ * haded this function is called as the same is done at each reconstitution of
+ * a MF.
+ *
+ * \param sar_ctx the sar context.
+ * \param ctx the reassembly context to transmit the data.
+ */
+void rx_upper_layer_transmit_data (sar_t *sar_ctx, sar_reassembly_ctx_t *ctx)
+{
+ u8 *address;
+ sar_job_mfs_t *job_head = NULL;
+ sar_job_mfs_t *job_tail = NULL;
+
+ dbg_assert (sar_ctx);
+ dbg_assert (ctx);
+
+ while (!bridge_dma_list_is_empty (&ctx->jobs_pending_list))
+ {
+ address = circular_buffer_get (&ctx->buffer_address_list);
+
+ if (address)
+ {
+ if (!job_head)
+ {
+ job_head = bridge_dma_get_head (&ctx->jobs_pending_list);
+ job_tail = job_head;
+ job_tail->next = NULL;
+ }
+ else
+ {
+ job_tail->next = bridge_dma_get_head (&ctx->jobs_pending_list);
+ job_tail->job.next = &job_tail->next->job;
+ job_tail = job_tail->next;
+ }
+ job_tail->job.data_addr = address;
+ }
+ else
+ break;
+ }
+
+ if (job_head)
+ bridge_dma_add_job_to_process (sar_ctx, job_head, job_tail);
+}
+
+/** create mac frame to transmit in preparing next job of bridge dma for
+ * segmentation
+ *
+ * \param ctx the sar context.
+ * \param md_data the Mac Frame to fill the job descriptor
+ */
+sar_job_mfs_t * tx_mac_framing (sar_t *ctx, sar_msdu_t *md_data)
+{
+ sar_job_mfs_t *job_mfs;
+
+ dbg_assert (md_data);
+ dbg_assert (ctx);
+
+ job_mfs = sar_job_mfs_create (true);
+ job_mfs->mfs = (mfs_t *) md_data->mfs;
+ job_mfs->mfs->tx.pending_jobs ++;
+
+ /**
+ * Get the last PB from the sar context if the jobs pending in the MFS are
+ * not null
+ */
+ if (md_data->mfs->last_seg_offset < BLK_SIZE)
+ {
+ job_mfs->job.first_pb_desc
+ = (blk_t *) pbproc_mfs_extract_tail (md_data->mfs);
+ if (job_mfs->job.first_pb_desc)
+ job_mfs->pb_last_taken = true;
+ }
+ else
+ {
+ job_mfs->job.first_pb_desc = NULL;
+ }
+
+ /* Create the job for the Bridge DMA
+ * Fill the job and create allocate the PBs necessary to stock the MF
+ * contained in the md_data
+ */
+ job_mfs->tail = tx_job_desc_create (md_data, md_data->mfs, job_mfs);
+
+ bridge_dma_add_job_to_process (ctx, job_mfs, job_mfs);
+
+ return job_mfs;
+}
+
+/**
+ * Create a job_desc_t from the md_data and allocate the PBs neccessary to stock
+ * the MF contained in the md_data
+ *
+ * Create the list of PBs necessary to contain the MF and put it via the
+ * PB proc in the MFS.
+ *
+ * \param md_data the data to segment
+ * \param mfs the corresponding mfs
+ * \param job_mfs the job to fill
+ *
+ * \return the last pb of the chain
+ */
+pb_t * tx_job_desc_create (sar_msdu_t *md_data, mfs_tx_t * mfs,
+ sar_job_mfs_t *job_mfs)
+{
+ /*
+ * author laranjeiro
+ * 20 sept. 07 - 10:19:35
+ *
+ * Modification of the length.
+ * For the bridgedma the mf_header1 must be filled with :
+ * type | ((length - 1) << 2)
+ * In the job, the data_len start at 1 for when the mf is 1 byte long.
+ */
+
+ u16 ssn;
+ u16 mf_complete_length = 0;
+ u8 type;
+
+ pb_t *pb_first;
+ pb_t *pb_last;
+ phy_bridgedma_job_t *job;
+
+ dbg_assert (mfs);
+ dbg_assert (job_mfs);
+
+ job = &job_mfs->job;
+
+ if (mfs->last_seg_offset == BLK_SIZE)
+ {
+ mfs->last_seg_offset = 0;
+ }
+
+ if (mfs->common.ats == true)
+ type = 2;
+ else if (mfs->common.mme)
+ type = 3;
+ else
+ type = 1;
+
+ // data addr
+ job->data_addr = md_data->buffer_address;
+ // data length
+ job->data_len = md_data->length;
+
+ if (type < 2)
+ {
+ /*
+ * No Ats / no Payload
+ * Mac Frame Header length = 2 bites
+ */
+ job->header_len = 2; // 2 Bytes
+
+ // data_type + header_len (length_ATS + length_Payload)
+ job->mf_header1 = type | ((md_data->length -1) << 2);
+ job->mf_header2 = 0x00; // null
+
+ // 3, the 2 bytes for the header and icv + 1 for the human count
+ mf_complete_length = 6 + md_data->length;
+ }
+ else
+ {
+ /*
+ * Prescence of an MSDU payload with a Confounder
+ * Mac Frame Header length = 6 Bytes
+ * MFL = length - 1 + the ATS or confounder size.
+ */
+ job->header_len = 0x06; // 6 Bytes
+
+ job->mf_header1 = type | ((md_data->length - 1 + SAR_MF_ATS_SIZE) << 2)
+ | (md_data->ats_confounder << 16);
+ job->mf_header2 = md_data->ats_confounder >> 16;
+ // 11, the 10 bytes for the header ats and icv + 1 for the human count
+ mf_complete_length = 10 + md_data->length;
+ }
+
+ /* Create the list of PBs */
+
+ ssn = mfs->next_ssn;
+ job->next = NULL;
+ job->first_pb_offset = mfs->last_seg_offset;
+
+ // It there is no PB in the job a new list is created
+ if (job->first_pb_desc == NULL)
+ {
+ mfs->last_seg_offset = mf_complete_length % BLK_SIZE;
+ job_mfs->last_pb_offset = mfs->last_seg_offset;
+
+ job_mfs->pb_quantity
+ = tx_job_desc_create_complete_list (mf_complete_length, ssn,
+ mfs->common.mme, &pb_first, &pb_last);
+
+ job->first_pb_desc = (blk_t *) pb_first;
+
+ mfs->next_ssn = pb_last->header.ssn + 1;
+
+ /* Add the PB to the MFS */
+ pbproc_mfs_insert (md_data->mfs, pb_first, pb_last,
+ job_mfs->pb_quantity, 0);
+
+ return pb_last;
+ }
+ // If the MF can be contained in the left space
+ else if (mf_complete_length > BLK_SIZE - mfs->last_seg_offset)
+ {
+ u16 offset;
+ /* calculate the number of bytes the last pb of the mfs can stock of
+ * this MF, and entrenched from the total Mf length
+ */
+ offset = mfs->last_seg_offset;
+
+ mfs->last_seg_offset = (mfs->last_seg_offset + mf_complete_length)
+ % BLK_SIZE;
+ job_mfs->last_pb_offset = mfs->last_seg_offset;
+
+ mf_complete_length -= BLK_SIZE - offset;
+
+ if (!((pb_t *) job_mfs->job.first_pb_desc)->header.mfbf)
+ {
+ ((pb_t *) job_mfs->job.first_pb_desc)->header.mfbf
+ = true;
+ ((pb_t *) job_mfs->job.first_pb_desc)->header.mfbo
+ = offset;
+ }
+
+ job_mfs->pb_quantity
+ = tx_job_desc_create_complete_list (mf_complete_length, ssn,
+ mfs->common.mme, &pb_first, &pb_last) + 1;
+
+ //update the ssn of the mfs
+ mfs->next_ssn = pb_last->header.ssn + 1;
+ ((pb_t *)job->first_pb_desc)->next = pb_first;
+
+ /* Add the PB to the MFS */
+ pbproc_mfs_insert (md_data->mfs, pb_first, pb_last,
+ job_mfs->pb_quantity - 1, 0);
+
+ return pb_last;
+ }
+ else
+ // No PB to create only create the new job with the right data
+ {
+ mfs->last_seg_offset = mf_complete_length + mfs->last_seg_offset;
+ job_mfs->last_pb_offset = mfs->last_seg_offset;
+
+ /* one PB token from the MFS */
+ job_mfs->pb_quantity = 1;
+
+ return (pb_t *) job->first_pb_desc;
+ }
+}
+
+/**
+ * Create a complete or a partial list of PBs for the mac framing
+ * \param length the length of the complete MF or the end of the MF
+ * \param ssn the next ssn to put on the header
+ * \param mme if the segments will contain messages.
+ * \param begin the first pb of the chain
+ * \param last the last pb of the chain.
+ * \return the number of PBs allocated
+ */
+u8 tx_job_desc_create_complete_list (u16 length, u8 ssn, bool mme,
+ pb_t **begin, pb_t **last)
+{
+ pb_t *pb_first;
+ pb_t *pb_last;
+ pb_t *pb;
+ u8 number_pb;
+
+ number_pb = (length >> SAR_DIV_BY_BLK_SIZE) + 1;
+
+ if (number_pb == 1)
+ {
+ pb_first = (pb_t *) blk_alloc_desc ();
+ pb_last = pb_first;
+
+ pb_first->header.ssn = ssn;
+ pb_first->header.mfbf = 0x01;
+ pb_first->header.mfbo = 0x00;
+ pb_first->header.mmqf = mme;
+ pb_first->header.vpbf = true;
+
+ *begin = pb_first;
+ *last = pb_last;
+ pb_last->next = NULL;
+ }
+ else
+ {
+ pb_first = (pb_t *) blk_alloc_desc_range (number_pb,
+ (blk_t **) &pb_last);
+ pb_last->next = NULL;
+
+ pb = pb_first;
+ pb->header.ssn = ssn++;
+ pb->header.mfbf = 0x1;
+ pb->header.mfbo = 0x0;
+ pb->header.mmqf = mme;
+ pb->header.vpbf = true;
+
+ // Fill the header for each PB
+ for (pb = pb->next; pb; pb = pb->next, ssn ++)
+ {
+ pb->header.ssn = ssn;
+ pb->header.mfbf = 0x0;
+ pb->header.mfbo = 0x0;
+ pb->header.mmqf = mme;
+ pb->header.vpbf = true;
+ }
+
+ *begin = pb_first;
+ *last = pb_last;
+ }
+
+ return number_pb;
+}
+
+/**
+ * Msdu expiration
+ * cf the specification HomePlug AV on page 260 (5.4.1.6.1 Transmit buffer
+ * management).
+ *
+ * \param ctx the sar context
+ * \param msdu the msdu to verify
+ * \return true if it had expired, false otherwise.
+ */
+bool tx_msdu_expiration (sar_t *ctx, sar_msdu_t * msdu)
+{
+ dbg_assert (msdu);
+ dbg_assert (ctx);
+
+ if (msdu->ats_confounder + SAR_MAX_SEGMENTATION_TIMER_NTB
+ <= mac_ntb())
+ {
+ SAR_TRACE (MSDU_EXP, mac_ntb(), msdu->buffer_address);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Create a job with all the minimum configuration for the bridge dma
+ *
+ * \param tx if it is a TX way
+ * \return sar job mfs for the bridge dma.
+ */
+sar_job_mfs_t *sar_job_mfs_create (bool tx)
+{
+ sar_job_mfs_t *sar_job;
+
+ sar_job = blk_alloc ();
+ sar_job->next = NULL;
+ /*
+ * author nelio
+ * 25 sept. 07 - 10:10:15
+ *
+ * No rollover
+ */
+ sar_job->job.eth_buffer_mask = 0x0;
+ sar_job->job.direction = !tx;
+ sar_job->job.crc_reset = 1;
+ sar_job->job.crc_store = 1;
+ sar_job->job.job_it = 1;
+ sar_job->job.segment_len = BLK_SIZE;
+ sar_job->pb_last_taken = false;
+
+ return sar_job;
+}
+
+/**
+ * Segmentation process for the SAR module.
+ *
+ * \param ctx the sar context
+ * \param msdu the msdu to process
+ */
+void segmentation_run (sar_t *ctx, sar_msdu_t *msdu)
+{
+ dbg_assert (ctx);
+ dbg_assert (msdu);
+
+ //sar_unit_test_add_msdu_print_debug();
+ if (!tx_msdu_expiration (ctx, msdu))
+ {
+ tx_mac_framing (ctx, msdu);
+ }
+ else
+ {
+ // callback the upperlayer and inform it that the buffer is newly available.
+ if (msdu->mfs->common.mme)
+ {
+ dbg_assert (ctx->sar_seg_msg_done_cb);
+ (*ctx->sar_seg_msg_done_cb) (ctx->ul_msg_ctx,
+ msdu->buffer_address);
+ }
+ else
+ {
+ dbg_assert (ctx->sar_seg_data_done_cb);
+ (*ctx->sar_seg_data_done_cb) (ctx->ul_data_ctx,
+ msdu->buffer_address);
+ }
+ }
+}
+
+/**
+ * Sar procedure
+ * Launch the SAR.
+ *
+ * \param sar the sar context.
+ */
+void sar_launch (sar_t *sar)
+{
+ dbg_assert (sar);
+ sar_work_message_t *work;
+ sar_msdu_t *msdu;
+ sar_mpdu_t *mpdu;
+
+ work = sar_work_get (sar);
+
+ if (work != NULL)
+ {
+ switch (work->type)
+ {
+ case SEG:
+ msdu = &work->msg.msdu;
+ segmentation_run (sar, msdu);
+ break;
+ case REA:
+ mpdu = &work->msg.mpdu;
+ reassembly_run (sar, mpdu);
+ break;
+ case ADD_BUFFER:
+ rx_upper_layer_transmit_data (sar, work->ctx);
+ break;
+ case BRIDGE:
+ bridge_dma_free_head (sar);
+ }
+
+ blk_release ((blk_t *) work);
+ }
+ else
+ {
+ sar_expiration_mfs (&sar->expiration, mac_ntb());
+ }
+}
+
+void sar_process (cyg_addrword_t data)
+{
+ while (true)
+ {
+ sar_launch ((sar_t *) data);
+ }
+ return;
+}
+
+/**
+ * Provides the beacon to the Control plane
+ *
+ * \param sar the sar context
+ * \param user_data
+ * \param uf upper layer function call
+ */
+void sar_init_beacon_cb (sar_t *sar, void *user_data, sar_beacon_cb_t uf)
+{
+ dbg_assert (sar);
+
+ sar->beacon_user_data = user_data;
+ sar->beacon_function_cb = uf;
+}
+
+/**
+ * add a beacon to the SAR.
+ * It will provide it to the CP to process the beacon.
+ *
+ * \param sar the sar context
+ * \param pb pb containing the beacon
+ * \param params the rx params.
+ */
+void sar_beacon_add (void *sar, pb_beacon_t *pb,
+ pbproc_rx_beacon_params_t *params)
+{
+ sar_t *ctx;
+ dbg_assert (sar);
+ dbg_assert (pb);
+ dbg_assert (params);
+ dbg_assert (((sar_t *)sar)->ul_msg_ctx);
+
+ ctx = (sar_t *) sar;
+ SAR_TRACE (BEACON, mac_ntb(), pb);
+ (*ctx->beacon_function_cb) (ctx->ul_msg_ctx, pb, params);
+}
+
+/**
+ * Request the SAR to send a beacon.
+ *
+ * \param ctx the sar context.
+ * \param beacon the beacon to send.
+ * \param beacon_mfs the mfs use to send the beacon
+ * \param bto_bpsto the address to provide to the pbproc.
+ */
+void
+sar_beacon_send (sar_t *ctx, pb_beacon_t *beacon, mfs_tx_t *beacon_mfs, void
+ *bto_bpsto)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (beacon_mfs);
+ dbg_assert (bto_bpsto);
+
+ dbg_assert (ctx->pbproc_ctx);
+
+
+ pbproc_mfs_beacon_prepare (ctx->pbproc_ctx, beacon_mfs, (pb_beacon_t *) beacon,
+ bto_bpsto);
+
+ ca_mfs_update (ctx->expiration.ca, beacon_mfs);
+}
+
diff --git a/cesar/mac/sar/src/sar_expiration.c b/cesar/mac/sar/src/sar_expiration.c
new file mode 100644
index 0000000000..2978c8ff7f
--- /dev/null
+++ b/cesar/mac/sar/src/sar_expiration.c
@@ -0,0 +1,459 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_expiration.c
+ * \brief the function for the sar expiration process.
+ * \ingroup mac/sar/src
+ *
+ */
+
+#include "common/std.h"
+#include "mac/sar/inc/sar_expiration.h"
+
+/**
+ * initialize the sar expiration and returns a context.
+ *
+ * \param ctx the context.
+ * \param ca the Channel Access context.
+ */
+void sar_expiration_init (sar_expiration_t *ctx, ca_t *ca)
+{
+ // init the expiration mechanism for the PBs and MFSs.
+ heap_init (&ctx->mfs_expiration_heap, sar_expiration_mfs_less);
+ cyg_mutex_init (&ctx->expiration_heap_mutex);
+
+ ctx->mfs_store = NULL;
+ ctx->mfs_expiration_cb = NULL;
+
+ dbg_assert (ca);
+ ctx->ca = ca;
+}
+
+/**
+ * initialize the sar expiration and returns a context.
+ *
+ * \param ctx the context.
+ */
+void sar_expiration_uninit (sar_expiration_t *ctx)
+{
+ mfs_t *mfs;
+
+ while ((mfs = sar_expiration_get_mfs (ctx)))
+ {
+ sar_expiration_mfs_remove_element (ctx, mfs);
+ mac_store_mfs_remove (ctx->mfs_store, mfs);
+ if (mfs->common.tx && mfs->tx.head)
+ pb_free_range (mfs->tx.head);
+ else if (mfs->rx.head)
+ pb_free_range (mfs->rx.head);
+
+ blk_release (mfs);
+ }
+
+ cyg_mutex_destroy (&ctx->expiration_heap_mutex);
+}
+
+/** Add a MFS to the SAR.
+ *
+ * \param ctx the expiration context
+ * \param mfs the mfs to add to the SAR.
+ */
+void sar_expiration_mfs_add (sar_expiration_t *ctx, mfs_t *mfs)
+{
+ dbg_assert (mfs);
+
+ // add a reference on the mfs
+ blk_addref ((blk_t *) mfs);
+
+ // lock the mutex to access to the heap.
+ cyg_mutex_lock (&ctx->expiration_heap_mutex);
+
+ heap_node_init (&mfs->common.expiration_heap_node);
+
+ heap_insert (&ctx->mfs_expiration_heap, &mfs->common.expiration_heap_node);
+
+ // unlock the mutex to access to the heap.
+ cyg_mutex_unlock (&ctx->expiration_heap_mutex);
+}
+
+/** Remove a MFS from the SAR
+ *
+ * \param ctx the expiration context
+ * \param mfs the mfs to remove from the SAR.
+ */
+void sar_expiration_mfs_remove (sar_expiration_t *ctx, mfs_t *mfs)
+{
+ dbg_assert (mfs);
+ dbg_assert (ctx);
+ dbg_assert (ctx->ca);
+
+ if (mfs->common.tx)
+ {
+ if (mfs->common.tx && !ca_mfs_remove (ctx->ca, (mfs_tx_t *) mfs))
+ {
+ mfs->common.expiration_ntb += CA_DELAY_RELEASE;
+ sar_expiration_ajust (ctx, mfs);
+ return;
+ }
+
+ mfs->common.release = true;
+ if (mfs->tx.head)
+ pb_free_range (mfs->tx.head);
+ mfs->tx.head = NULL;
+
+ mfs->common.expiration_ntb += RELEASE_TIMER_VALUE;
+ sar_expiration_ajust (ctx, mfs);
+ }
+ else
+ {
+ sar_expiration_mfs_destroy (ctx, mfs);
+ }
+}
+
+/** Destroy a MFS from the SAR
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to remove from the SAR.
+ *
+ * \return true if successed, false otherwise.
+ */
+bool sar_expiration_mfs_destroy (sar_expiration_t *ctx, mfs_t *mfs)
+{
+ dbg_assert (mfs);
+ dbg_assert (ctx);
+
+ //release the pbs
+ if (mfs->common.tx && mfs->tx.head)
+ {
+ pb_free_range (mfs->tx.head);
+ mfs->tx.head = NULL;
+ }
+ else if (!mfs->common.tx && mfs->rx.head)
+ {
+ pb_free_range (mfs->rx.head);
+ mfs->rx.head = NULL;
+ }
+
+ // released from the SAR.
+ sar_expiration_mfs_remove_element (ctx, mfs);
+
+ mac_store_mfs_remove (ctx->mfs_store, mfs);
+
+ /* release the reference on the mfs. */
+ blk_release (mfs);
+
+ return true;
+}
+
+/**
+ * get the next mfs to expire.
+ *
+ * \param ctx the sar expiration context
+ *
+ * \return the mfs on the root element of the heap.
+ */
+mfs_t* sar_expiration_get_mfs (sar_expiration_t *ctx)
+{
+ dbg_assert (ctx);
+ mfs_t *mfs_type = NULL;
+
+ // lock the mutex to access to the heap.
+ cyg_mutex_lock (&ctx->expiration_heap_mutex);
+
+ if (!heap_empty (&ctx->mfs_expiration_heap))
+ {
+ mfs_type = PARENT_OF (mfs_t, common, PARENT_OF (mfs_common_t,
+ expiration_heap_node,
+ heap_get_root (&ctx->mfs_expiration_heap)));
+ }
+
+ cyg_mutex_unlock (&ctx->expiration_heap_mutex);
+
+ return mfs_type;
+}
+
+/**
+ * ajust the expiration heap
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to adjust in the expiration machanism
+ */
+void sar_expiration_ajust (sar_expiration_t *ctx, mfs_t *mfs)
+{
+ dbg_assert (mfs);
+
+ cyg_mutex_lock (&ctx->expiration_heap_mutex);
+
+ heap_adjust (&ctx->mfs_expiration_heap, &mfs->common.expiration_heap_node);
+
+ cyg_mutex_unlock (&ctx->expiration_heap_mutex);
+}
+
+/**
+ * remove the mfs from the sar expiration mechanism.
+ *
+ * \param ctx the sar expiration context
+ * \param mfs the mfs to remove
+ */
+void sar_expiration_mfs_remove_element (sar_expiration_t *ctx, mfs_t *mfs)
+{
+ cyg_mutex_lock (&ctx->expiration_heap_mutex);
+
+ heap_remove (&ctx->mfs_expiration_heap, &mfs->common.expiration_heap_node);
+
+ cyg_mutex_unlock (&ctx->expiration_heap_mutex);
+}
+
+/**
+ * Update the expiration date of the RX MFS
+ *
+ * \param ctx the sar expiration ctx to update the expiration machanism
+ * \param mfs the mfs to update
+ * \param date the current date
+ */
+void sar_expiration_mfs_update_date (sar_expiration_t *ctx, mfs_t *mfs,
+ u32 date)
+{
+ dbg_assert (ctx);
+ dbg_assert (mfs);
+
+ mfs->common.expiration_ntb = date;
+
+ sar_expiration_ajust (ctx, mfs);
+}
+
+/**
+ * Check the validity of the PBs for the mfs
+ *
+ * \param ctx the sar expiration context.
+ * \param phy_curr_ntb the actual phy date.
+ */
+void sar_expiration_mfs (sar_expiration_t *ctx, u32 phy_curr_ntb)
+{
+ mfs_t *mfs_type;
+ pb_t *pb;
+
+ mfs_type = sar_expiration_get_mfs (ctx);
+
+ if (mfs_type == NULL)
+ {
+ return;
+ }
+
+ // Release Time OUT.
+ if (mfs_type->common.release && mfs_type->common.expiration_ntb
+ < phy_curr_ntb)
+ {
+ sar_expiration_mfs_destroy (ctx, mfs_type);
+ return;
+ }
+
+ else if (mfs_type->common.tx && !ca_mfs_remove (ctx->ca, (mfs_tx_t *) mfs_type))
+ {
+ mfs_type->common.expiration_ntb += CA_DELAY_RELEASE;
+ return;
+ }
+
+ if (mfs_type->common.expiration_delay_ntb != 0
+ && (u32)(mfs_type->common.expiration_delay_ntb
+ + mfs_type->common.expiration_ntb)< phy_curr_ntb)
+ {
+ /** The MFS had expired, all the PBs in it will be released and
+ * The MFS will be put in the release state. */
+
+ //removes all the PBs in the MFS
+ if (mfs_type->common.tx && mfs_type->tx.head)
+ {
+ pb_free_range (mfs_type->tx.head);
+ mfs_type->tx.head = NULL;
+ }
+ else if (!mfs_type->common.tx
+ && !MAC_LID_IS_PLID (mfs_type->common.lid)
+ && mfs_type->rx.head)
+ {
+ pb_free_range (mfs_type->rx.head);
+ mfs_type->rx.head = NULL;
+ }
+ else if (!mfs_type->common.tx
+ && MAC_LID_IS_PLID (mfs_type->common.lid)&& mfs_type->rx.head)
+ {
+ sar_expiration_mfs_destroy (ctx, mfs_type);
+ return;
+ }
+
+ // prevent the upper layer if it is not a PLID MFS
+ if (!MAC_LID_IS_PLID (mfs_type->common.lid))
+ {
+ (*ctx->mfs_expiration_cb) (NULL, mfs_type);
+ }
+
+ // Modify the state of the MFS
+ mfs_type->common.release = true;
+
+ // Modified the expiration date of the MFS
+ mfs_type->common.expiration_ntb = phy_curr_ntb+ RELEASE_TIMER_VALUE;
+ }
+
+ // PB expiration part
+ else if (mfs_type->common.tx)
+ {
+ if (mfs_type->tx.head != NULL)
+ {
+ mfs_type->tx.head = sar_expiration_pb (mfs_type->tx.head,
+ SAR_MAX_SEGMENTATION_TIMER_NTB, phy_curr_ntb);
+ }
+ }
+ else
+ {
+ if (mfs_type->common.ats)
+ {
+ pb = mfs_type->rx.head;
+ while (pb != NULL)
+ {
+ if (pb->header.mfbf && mf_get_ats (pb, pb->header.mfbo)
+ + SAR_MAX_SEGMENTATION_TIMER_NTB <= phy_curr_ntb)
+ {
+ pb = pb_free (pb);
+ }
+ else if (pb->expiration_ntb + SAR_MAX_REASSEMBLY_TIMER_NTB
+ <= phy_curr_ntb)
+ {
+ pb = pb_free (pb);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ mfs_type->rx.head = pb;
+ }
+ else if (mfs_type->rx.head != NULL)
+ {
+ mfs_type->rx.head= sar_expiration_pb (mfs_type->rx.head,
+ SAR_MAX_REASSEMBLY_TIMER_NTB, phy_curr_ntb);
+ }
+
+ rx_mfs_update_last_contiguous_and_tail ((mfs_rx_t *) mfs_type,
+ mfs_type->rx.head);
+ }
+
+ sar_expiration_ajust (ctx, mfs_type);
+}
+
+/**
+ * Called by the mfs_manage_expiration to expire the pbs in the MFS.
+ *
+ * \param head the first pb to check.
+ * \param expiration_delay expiration delay
+ * \param phy_curr_date the current phy date.
+ * \return the new head of the chain.
+ */
+pb_t * sar_expiration_pb (pb_t *head, uint expiration_delay, u32 phy_curr_ntb)
+{
+ while (head != NULL && head->expiration_ntb + expiration_delay
+ <= phy_curr_ntb)
+ {
+ head = pb_free (head);
+ }
+
+ return head;
+}
+
+/**
+ * Compare the two nodes of the tree, if the left side is lesser than the right
+ * it returns true otherwise it returns false.
+ *
+ * \param left the left heap node
+ * \param right the right heap node
+ * \return true if left expires before right, wrong otherwise.
+ */
+bool sar_expiration_mfs_less (heap_node_t *left, heap_node_t *right)
+{
+ mfs_t *mfs_left;
+ mfs_t *mfs_right;
+
+ pb_t *pb_left;
+ pb_t *pb_right;
+
+ bool res;
+
+ dbg_assert (left);
+ dbg_assert (right);
+
+ mfs_left = PARENT_OF (mfs_t, common, PARENT_OF (mfs_common_t,
+ expiration_heap_node, left));
+ mfs_right = PARENT_OF (mfs_t, common, PARENT_OF (mfs_common_t,
+ expiration_heap_node, right));
+
+ dbg_assert (mfs_left);
+ dbg_assert (mfs_right);
+
+ if (mfs_left->common.tx)
+ {
+ pb_left = mfs_left->tx.head;
+ }
+ else
+ {
+ pb_left = mfs_left->rx.head;
+ }
+
+ if (mfs_right->common.tx)
+ {
+ pb_right = mfs_right->tx.head;
+ }
+ else
+ {
+ pb_right = mfs_right->rx.head;
+ }
+
+ res = false;
+
+ if (pb_left == NULL && pb_right != NULL)
+ {
+ res = false;
+ }
+ else if (pb_left != NULL && pb_right == NULL)
+ {
+ res = true;
+ }
+ else if (pb_left != NULL && (pb_left->expiration_ntb
+ > pb_right->expiration_ntb))
+ {
+ res = false;
+ }
+ else if (pb_right != NULL && (pb_left->expiration_ntb
+ < pb_right->expiration_ntb))
+ {
+ res = true;
+ }
+
+ if (mfs_left->common.expiration_delay_ntb == 0
+ && mfs_right->common.expiration_delay_ntb != 0)
+ {
+ res = false;
+ }
+ else if (mfs_left->common.expiration_delay_ntb != 0
+ && mfs_right->common.expiration_delay_ntb == 0)
+ {
+ res = true;
+ }
+ else if (mfs_left->common.expiration_delay_ntb
+ + mfs_left->common.expiration_ntb
+ > mfs_right->common.expiration_delay_ntb
+ + mfs_right->common.expiration_ntb)
+ {
+ res = false;
+ }
+ else
+ {
+ res = true;
+ }
+
+ return res;
+}
diff --git a/cesar/mac/sar/src/sar_mf.c b/cesar/mac/sar/src/sar_mf.c
new file mode 100644
index 0000000000..6d1047ecb2
--- /dev/null
+++ b/cesar/mac/sar/src/sar_mf.c
@@ -0,0 +1,180 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mf.c
+ * \brief the function to process a MF.
+ * \ingroup mac/sar/src
+ *
+ */
+
+#include "common/std.h"
+#include "lib/read_word.h"
+#include "mac/sar/inc/sar_mf.h"
+
+/**
+ * Get the type of the MF from the PB at the data adress plus the offset
+ *
+ * \param pb The first pb containing the MF.
+ * \param offset the offset to start reading
+ * \return MF type.
+ */
+uint mf_get_type (pb_t * pb, uint offset)
+{
+ dbg_assert (pb);
+ dbg_assert (offset < BLK_SIZE);
+
+ return read_u8_from_word (pb->data + offset) & 3;
+}
+
+/**
+ * Test the existance of a MF at the address given by mf and return its length.
+ * Will be used to determine if a complete MF is avaliable in the MFS.
+ * Test if the MF start in the end of the PB by verifying the offset, if the MFH
+ * is in two PBs.
+ *
+ * \param pb The first pb containing the MF.
+ * \param offset the offset to start reading
+ * \param payload_only request to return only the payload length if true.
+ *
+ * \return length of the payload with the header and icv
+ */
+uint mf_get_length (pb_t *pb, uint offset, bool payload_only)
+{
+ dbg_assert (pb);
+ uint length;
+ uint type;
+
+ /* If the offset is in the last 6 bytes of the PB data. */
+ if (offset == BLK_SIZE - 1 && pb->next)
+ {
+ length = read_u8_from_word (pb->data + offset)
+ | (read_u8_from_word (pb->next->data) << 8);
+ type = length & 0x3;
+ length = length >> 2;
+ }
+ else if (offset == BLK_SIZE - 1 && !pb->next)
+ {
+ return 0;
+ }
+ else
+ {
+ length = read_u16_from_word (pb->data + offset);
+ type = length & 0x3;
+ length = length >> 2;
+ }
+
+ if (length < ETH_PACKET_MIN_SIZE || length
+ > ETH_PACKET_MAX_SIZE + SAR_MF_ICV_SIZE)
+ return 0;
+
+ if (payload_only && (type > 1))
+ {
+ return length + 1 - SAR_MF_ATS_SIZE;
+ }
+ else if (payload_only)
+ {
+ return length + 1;
+ }
+ else
+ {
+ return length + 1 + SAR_MF_ICV_SIZE + SAR_MF_MFH_SIZE;
+ }
+}
+
+/**
+ * Calculate the number of PB used for the MF
+ *
+ * Depends of the mf_get_length function
+ *
+ * \param pb the first PB where the MF starts
+ * \param offset the offset of the PB where the MF starts
+ * \return the quantity of PBs
+ */
+uint mf_get_quantity_of_pb (pb_t *pb, uint offset)
+{
+ uint number_of_pb;
+ uint mf_length;
+
+ if ((mf_length = mf_get_length (pb, offset, false)) == 0)
+ {
+ return 0;
+ }
+
+ number_of_pb = ((mf_length + offset) >> SAR_DIV_BY_BLK_SIZE) + 1;
+
+ return number_of_pb;
+}
+
+/**
+ * gets the ATS of a MF in the address pointed by the PB plus the offset
+ *
+ * Depends of mf_get_type
+ *
+ * \param pb the first PB where the MF starts
+ * \param offset the offset of the PB where the MF starts
+ * \return the ATS of the MF.
+ */
+u32 mf_get_ats (pb_t *pb, uint offset)
+{
+ u8 type;
+ pb_t *pb_curr;
+
+ type = mf_get_type (pb, offset);
+
+ if (type < 0x2)
+ {
+ return 0;
+ }
+
+ offset += SAR_MF_MFH_SIZE;
+ if (offset > BLK_SIZE && !pb->next)
+ {
+ return 0;
+ }
+ else if (offset > BLK_SIZE && pb->next)
+ {
+ pb_curr = pb->next;
+ offset = offset % BLK_SIZE;
+ }
+ else
+ {
+ pb_curr = pb;
+ }
+
+ /* Normal case */
+ if (offset < BLK_SIZE - SAR_MF_ATS_SIZE)
+ {
+ return read_u32_from_word (pb_curr->data + offset);
+ }
+ else if (pb->next)
+ {
+ uint ats1;
+ uint ats2;
+
+ switch (offset) {
+ case BLK_SIZE - SAR_MF_ATS_SIZE + 1:
+ ats2 = read_u8_from_word (pb_curr->next->data);
+ ats1 = read_u24_from_word (pb_curr->data + offset);
+ return (ats2 << 24) | ats1;
+ break;
+ case BLK_SIZE - SAR_MF_ATS_SIZE + 2:
+ ats2 = read_u16_from_word (pb_curr->next->data);
+ ats1 = read_u16_from_word (pb_curr->data + offset);
+ return (ats2 << 16) | ats1;
+ case BLK_SIZE - SAR_MF_ATS_SIZE + 3:
+ ats2 = read_u24_from_word (pb_curr->next->data);
+ ats1 = read_u8_from_word (pb_curr->data + offset);
+ return (ats2 << 8) | ats1;
+ break;
+ default:
+ return read_u32_from_word (pb_curr->data + offset);
+ }
+ }
+
+ return 0;
+}
diff --git a/cesar/mac/sar/src/sar_mfs.c b/cesar/mac/sar/src/sar_mfs.c
new file mode 100644
index 0000000000..3049995733
--- /dev/null
+++ b/cesar/mac/sar/src/sar_mfs.c
@@ -0,0 +1,105 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mfs.c
+ * \brief the function for the sar mfs.
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#include "common/std.h"
+#include "mac/sar/inc/sar_mfs.h"
+
+/**
+ * Update last pb continuous on the mfs
+ *
+ * Verify the continuity of the chain from the first PB of the MFS to the last
+ * contiguous.
+ *
+ * If the counter of ssn had been reseted it verify the coninuity search the ssn
+ * 0 after the ssn 655535.
+ *
+ * \param mfs the MFS to update
+ * \param pb of the MFS from wich one it is needed to update
+ */
+void rx_mfs_update_last_contiguous_and_tail (mfs_rx_t *mfs, pb_t *pb)
+{
+ dbg_assert (mfs);
+
+ if (pb != NULL)
+ {
+ while (pb->next != NULL&& ((pb->header.ssn + 1) & 0x0000ffff)
+ == (0x0000ffff & pb->next->header.ssn))
+ {
+ pb = pb->next;
+ }
+
+ mfs->last_contiguous = pb;
+
+ while (pb->next != NULL)
+ {
+ pb = pb->next;
+ }
+
+ mfs->tail = pb;
+
+ //update the mfs window
+ if (mfs->head->header.ssn == mfs->ssn_min|| less_mod2p16 (
+ mfs->head->header.ssn, mfs->ssn_min))
+ {
+ mfs->ssn_min = mfs->last_contiguous->header.ssn + 1;
+ }
+ }
+
+ if (mfs->head == NULL)
+ {
+ mfs->last_contiguous = NULL;
+ mfs->tail = NULL;
+ }
+}
+
+/**
+ * Verify if it is necessary to modify the ssn of the MFS according with the
+ * Homeplug AV norm.
+ *
+ * \param pb the pb to make the test.
+ * \param mfs the mfs to verify.
+ * \param pb_nb number of PBs in the mpdu given by the pbproc.
+ */
+void rx_mfs_resize_ssn (pb_t *pb, mfs_rx_t *mfs, uint pb_nb)
+{
+ if (pb_nb == 1&& mfs->common.bcast && pb->header.opsf&& less_mod2p16 (
+ mfs->ssn_min + mfs->window_size, pb->header.ssn))
+ {
+ mfs->ssn_min = pb->header.ssn + 1;
+
+ while (mfs->head&& less_mod2p16 (mfs->head->header.ssn, mfs->ssn_min))
+ {
+ mfs->head = pb_free (mfs->head);
+ }
+
+ rx_mfs_update_last_contiguous_and_tail (mfs, mfs->head);
+ }
+ //Update the window of the mfs.
+ else if (mfs->common.bcast && !pb->header.opsf&& less_mod2p16 (mfs->ssn_min
+ + mfs->window_size, pb->header.ssn))
+ {
+ mfs->ssn_min = pb->header.ssn - mfs->window_size;
+ }
+}
+
+/**
+ * Return the max ssn of the MFS
+ *
+ * \param mfs the mfs.
+ */
+u16 rx_mfs_get_ssn_max (mfs_rx_t *mfs)
+{
+ return ((u16) (mfs->ssn_min + mfs->window_size));
+}
+
diff --git a/cesar/mac/sar/src/sar_pb.c b/cesar/mac/sar/src/sar_pb.c
new file mode 100644
index 0000000000..1315323453
--- /dev/null
+++ b/cesar/mac/sar/src/sar_pb.c
@@ -0,0 +1,48 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_pb.c
+ * \brief common function to process pbs
+ * \ingroup mac/sar/src
+ *
+ */
+
+#include "common/std.h"
+#include "mac/sar/inc/sar_pb.h"
+
+/**
+ * Free a pb of a chain and return the next PB of the PB given in parameter
+ *
+ * \param pb The PB to free
+ * \return The next PB of the freed PB.
+ */
+pb_t *pb_free (pb_t *pb)
+{
+ pb_t *next;
+
+ dbg_assert (pb);
+
+ next = pb->next;
+ blk_release_desc ((blk_t *) pb);
+
+ return next;
+}
+
+/**
+ * Free a range of pb
+ *
+ * \param pb The PB to free
+ * \return The next PB of the freed PB.
+ */
+void pb_free_range (pb_t *pb)
+{
+ dbg_assert (pb);
+
+ while ((pb = pb_free (pb)))
+ ;
+}
diff --git a/cesar/mac/sar/src/trace.c b/cesar/mac/sar/src/trace.c
new file mode 100644
index 0000000000..0704e61291
--- /dev/null
+++ b/cesar/mac/sar/src/trace.c
@@ -0,0 +1,73 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/src/trace.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/trace.h"
+#include "mac/sar/inc/sar_context.h"
+
+/**
+ * Initialize the trace system
+ * \param ctx the sar context.
+ */
+void
+sar_trace_init (sar_t *ctx)
+{
+ static trace_namespace_t namespace;
+ static const trace_event_id_t event_ids[] =
+ {
+ TRACE_EVENT (SAR_TRACE_INIT, "SAR_INIT", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_UNINIT, "SAR_UNINIT", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_DATA_BUFFER_ADD, "SAR_DATA_BUFFER_ADD, buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MME_BUFFER_ADD, "SAR_MME_BUFFER_ADD, buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MPDU_ADD, "SAR_MPDU_ADD, tei : %x, lid : %x, mfs : %d, mme : %d, pb_number : %d", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MSDU_ADD, "SAR_MSDU_ADD, buffer : %x, length : %d, tei :%x, lid : %x, mme : %d", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MFS_ADD, "SAR_MFS_ADD, is tx : %d, is mme : %d, tei :%x, lid : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MFS_REMOVE, "SAR_MFS_REMOVE, is tx : %d, is mme : %d, tei :%x, lid : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_BRIDGE, "SAR_BRIDGE, buffer : %x, RX : %d, MME : %d, tei :%x, lid : %x, CRC : %d", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_PB_ERROR, "SAR_MPDU_PROCESS PBs invalid or CRC error, ssn : %d, tei : %x, lid : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MPDU_EXP, "SAR_EXP MDPU Expired, tei : %x, lid : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_PB_SSN_NOT_IN_WIN, "SAR_PB_WRONG_SSN ssn : %d, mfs ssn min : %d, mfs ssn max : %d", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MSDU_EXP, "SAR_MSDU_EXP buffer : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_BEACON, "SAR_BEACON buffer : %x", TIMESTAMP),
+ TRACE_EVENT (SAR_TRACE_MBOX, "SAR_MBOX state : Number of pending Msg %d", TIMESTAMP),
+ };
+ dbg_assert (ctx);
+ trace_namespace_init (&namespace, event_ids, COUNT (event_ids));
+ trace_buffer_add (&ctx->trace, "sar", 8, 4, true, &namespace);
+}
+
+/**
+ * Uninitialize the trace system
+ * \param ctx the sar context
+ */
+void
+sar_trace_uninit (sar_t *ctx)
+{
+ dbg_assert (ctx);
+ trace_buffer_remove(&ctx->trace);
+}
+
+/**
+ * Print the traces
+ * \param ctx the sar context.
+ */
+void
+sar_trace_print (sar_t *ctx)
+{
+ dbg_assert(ctx);
+ trace_buffer_dbg_dump(&ctx->trace);
+}
+
diff --git a/cesar/mac/sar/test/Module b/cesar/mac/sar/test/Module
new file mode 100644
index 0000000000..6b37bee5f9
--- /dev/null
+++ b/cesar/mac/sar/test/Module
@@ -0,0 +1,2 @@
+SOURCES := reassembly_unit_test_functions.c sar_unit_test_functions.c \
+ ce.c \ No newline at end of file
diff --git a/cesar/mac/sar/test/inc/ce.h b/cesar/mac/sar/test/inc/ce.h
new file mode 100644
index 0000000000..8a9a04c3b4
--- /dev/null
+++ b/cesar/mac/sar/test/inc/ce.h
@@ -0,0 +1,76 @@
+#ifndef CE_H_
+#define CE_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file ce.h
+ * \brief Context of the CE
+ * \ingroup mac/sar/test/inc
+ *
+ * contains a minimum of the CE data to take the measurement of the PBs.
+ *
+ */
+
+#include "lib/blk.h"
+#include "mac/pbproc/pbproc.h"
+
+struct ce_store_rx_params_t
+{
+ struct ce_store_rx_params_t *next;
+ pbproc_rx_params_t *rx_params;
+};
+typedef struct ce_store_rx_params_t ce_store_rx_params_t;
+
+struct ce_t
+{
+ blk_t *measurement_head;
+ blk_t *measurement_tail;
+
+ ce_store_rx_params_t *rx_params_head;
+ ce_store_rx_params_t *rx_params_tail;
+
+ pb_t *chandata;
+};
+typedef struct ce_t ce_t;
+
+/** Global context of the CE */
+ce_t ce_ctx;
+
+/**
+ * Init the CE and get the context pointer.
+ */
+ce_t *ce_init (void);
+
+/**
+ * Pb measurement RX callback for Channel estimation.
+ * This call back will return one or two block in order to insert all the
+ * measurements contained in each PB of the mpdu received.
+ * Two cases can happen, the first the pb_nb is lesser than the blk capacity,
+ * this callback will return only a blk pointed by the first and the last
+ * pointer.
+ * In the second case the quantity of PB are greater than one blk capacity, this
+ * callback will return two blk (chained) the first pointed by the first pointer
+ * and the last one by the last pointer.
+ *
+ * \param user User data
+ * \param rx_params Frame control information to know date and tonemap used
+ * \param number of pbs
+ * \param first blk to insert the measurements.
+ * \param last blk to insert the measurements.
+ * \param chandata chan data measurements
+ *
+ * \return boolean to indicate if a block had been returned or not.
+ */
+bool ce_measurements (void *user, pbproc_rx_params_t *rx_params, uint pb_nb,
+ blk_t **first, blk_t **last, pb_t *chandata, uint nb_chandata, uint
+ *blk_offset);
+
+void ce_uninit (void);
+
+#endif /*CE_H_*/
diff --git a/cesar/mac/sar/test/inc/eth_packets.h b/cesar/mac/sar/test/inc/eth_packets.h
new file mode 100644
index 0000000000..2e183f42da
--- /dev/null
+++ b/cesar/mac/sar/test/inc/eth_packets.h
@@ -0,0 +1,141 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file eth_packets.h
+ * \brief Ethernet packets for the SAR
+ * \ingroup mac/sar/test/inc/
+ *
+ * Command used to generate the data.
+ * od -tx4 -An -v < packet4 | perl -pe 's/[0-9a-f]+/0x$&,/g' > packet4_little.c
+ *
+ */
+
+#ifndef ETH_PACKETS_H_
+#define ETH_PACKETS_H_
+
+// Modify this value if another Ethernet packet is added to the test.
+#define PACKETS_QTE 3
+
+u8 *packets[PACKETS_QTE];
+u32 packets_len[PACKETS_QTE];
+
+unsigned int packet1 []__attribute__((aligned(2048))) =
+{ 0xa1b2c3d4, 0x00040002, 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 packet1_len = 106;
+
+unsigned int packet2[] = { 0xa1b2c3d4, 0x00040002, 0x00000000, 0x00000000,
+ 0x0000ffff, 0x00000001, 0x469732d4, 0x0000da24, 0x0000005d,
+ 0x0000005d, 0x12005452, 0x00080235, 0x4c205227, 0x00450008,
+ 0x09064f00, 0x06400040, 0x000a901c, 0x000a0f02, 0x01040202,
+ 0x46d6bd01, 0x0d0071cf, 0x185072c5, 0x4b65b0f9, 0x00000000,
+ 0x53ff2300, 0x0071424d, 0x18000000, 0x0000c807, 0x00000000,
+ 0x00000000, 0x00010000, 0x0000feff, 0x00000a01, 0x00000000 };
+unsigned int packet2_len = 133;
+
+unsigned int packet3[]__attribute__((aligned(2048))) =
+{ 0xa1b2c3d4, 0x00040002, 0x00000000, 0x00000000,
+ 0x0000ffff, 0x00000001, 0x469f2f9c, 0x000278d1,
+ 0x00000596, 0x00000596, 0x52270008, 0x54524c20,
+ 0x02351200, 0x08450008, 0x6e008805, 0x06400000,
+ 0x55d1f115, 0x000aa581, 0x50000f02, 0x76011704,
+ 0xccc2f41c, 0x1850386e, 0xf1e23822, 0x947e0000,
+ 0x972c94bd, 0x3484d422, 0xfcfe8c0c, 0x5bd98513,
+ 0x8eb0bbc0, 0xa20c7fb8, 0xad107af5, 0xb7ad1045,
+ 0x8ffd6882, 0x772aa883, 0xd2b3b25a, 0x462bc08d,
+ 0xb10c0c76, 0x6abc270b, 0xf5dce5d9, 0x6c0b3469,
+ 0x7c270996, 0xee56cd9c, 0x1b0b8aa3, 0x5448c7b2,
+ 0x9d47df2d, 0xac9d816d, 0xb600f0de, 0x17745543,
+ 0x39579379, 0x1265b911, 0xf3bffc91, 0xe5d5b539,
+ 0xa9bd450a, 0x8ed972fe, 0x7f2a2b93, 0xfb800f26,
+ 0x3d25744a, 0x5fc3aa7a, 0x8c8e08e7, 0x9c06d988,
+ 0x96dad6de, 0x5bd0540b, 0x1d30d90d, 0x67d5a9c3,
+ 0x1425f548, 0xe203c41d, 0x4060f233, 0x458f4b0a,
+ 0x0f013a45, 0x01d86015, 0x0e4645c7, 0xbdbdafb6,
+ 0x729f5a62, 0x71e63c30, 0x01356144, 0xd6fcc94c,
+ 0x6c623ab8, 0x89eaa4b3, 0x50c8a38f, 0x93272716,
+ 0x42209f65, 0xce3b3f7d, 0x53d25a1a, 0x97b49ca7,
+ 0x0686c36e, 0x6dfe025c, 0x733ec134, 0x270c6303,
+ 0xe2d7b518, 0x92891ca5, 0xc2422f68, 0x5bf0ff88,
+ 0x177f0d84, 0x072ba333, 0xac671f0f, 0x3e3d5ce1,
+ 0xd2d8fad6, 0x7880e64a, 0x7facd78f, 0x7632dcee,
+ 0x38931fd1, 0xb9dea336, 0x7a5c9e9c, 0xbcd2f0ee,
+ 0xa7a7bb72, 0x2f4f8b73, 0x9aef79b9, 0xcfef7e5f,
+ 0xc693f7c3, 0x3f4dfa9d, 0xa0bba5b8, 0x6cf772e9,
+ 0xf25c9e6c, 0x8f4fdbbb, 0x79d9f1ee, 0x8e1b56ff,
+ 0x1a387d48, 0xd3adcfce, 0x5d9ac7ee, 0x7bf567b3,
+ 0xfb73f812, 0xdf0887e3, 0x3d5b7970, 0xd7cdd694,
+ 0xd55cdf18, 0x6fbae307, 0x77b7780f, 0x9e1b3c7f,
+ 0x7ef3b3b8, 0xb9bdb9d7, 0x4f2f3538, 0x1019f9b0,
+ 0xfd357278, 0x90139ac4, 0xcf8c1b52, 0x5ce6f467,
+ 0x0a7ebdbb, 0xadefd329, 0xebed2eaa, 0x3c9f687a,
+ 0xabf8d6c4, 0xf43c6836, 0xfe9f5f7a, 0xa1868f98,
+ 0x39b8379c, 0xa735393d, 0x09b5370e, 0xd3a5de4f,
+ 0xa2f30d0f, 0xf4be4e6b, 0x9a68734d, 0x8f106ee6,
+ 0x75d77d0d, 0x22bb6c7d, 0xbad56a34, 0xfbfdfef6,
+ 0x0444327a, 0x1fa8d2c5, 0x556bd41c, 0xc2efa6bd,
+ 0x0bf855e9, 0x20503844, 0x41021408, 0x04c91c1c,
+ 0x84fa7006, 0x8f3993eb, 0xbba38d05, 0xd65eb96a,
+ 0x5c32d5ca, 0xb5217690, 0x820c9b20, 0x956c614b,
+ 0x43b50f0e, 0x35346f4d, 0xa8d879bd, 0x80757569,
+ 0x5cc492d1, 0x6c1cc3cb, 0xfaacab48, 0x2b3093ef,
+ 0x699c9b46, 0xa0ee3561, 0x4338004c, 0xdf46741c,
+ 0x7894f9bf, 0x6ca05c6a, 0x25c46809, 0x8a6a01f6,
+ 0x3782a8e0, 0x784ad833, 0x305b7fbe, 0xcc65f401,
+ 0x8a6c8464, 0x463c461c, 0xfdd48445, 0x078b610a,
+ 0x8a715241, 0x24409850, 0xff7c84c2, 0xb06b422b,
+ 0x3b8d485c, 0xe6b9c6ea, 0x22a68cd5, 0xea10f56d,
+ 0x80b380a1, 0xeb67c574, 0x1e7fd638, 0x2e1bfac7,
+ 0xb1c6dfd4, 0x63827ffe, 0xfbb2e6ef, 0xe3078e2a,
+ 0xa3f3f73b, 0xd45d6f7f, 0xec9b1c33, 0xf4d2f8e9,
+ 0x8e06dedc, 0x84a24acf, 0xc5eddecd, 0x7a777ea4,
+ 0xdd0bda76, 0x517676ae, 0x1c2a3fed, 0xfbcf565e,
+ 0xa34fb5c7, 0x7e70f9e3, 0x24af333d, 0xb7c48f20,
+ 0xa4ebdfb5, 0x1f59e576, 0xfae0c6fd, 0xeb5d627c,
+ 0x35f635ba, 0xff1eb9fa, 0x61b9f371, 0xe1a7f25e,
+ 0x7860f77d, 0xa9bd397f, 0xcccf987e, 0x3dd56ee3,
+ 0x5727c7be, 0xc9f3e91a, 0x40ea67e0, 0xee9a64af,
+ 0xec04d0c7, 0x7e6d135d, 0xa3d29166, 0xccceec39,
+ 0x3cc349e1, 0xf792341f, 0xb752eb05, 0xe81cbd3f,
+ 0x2fecd4e6, 0x84dd5c40, 0x9722caa7, 0x167d1006,
+ 0x5006684c, 0x123cfc47, 0xea246df5, 0xe7f123af,
+ 0x891b68d3, 0xec48ebfa, 0xe92871f1, 0x06884e02,
+ 0xa2cc73e8, 0xc38dbe88, 0x58c200cf, 0x1bfdf930,
+ 0x95c112a2, 0xdfef889c, 0xc098f3b2, 0x42346481,
+ 0x703b8217, 0x3a039e73, 0x18139001, 0xd302c485,
+ 0x446ac022, 0x36f4fc70, 0xe3715f18, 0xa2b280cf,
+ 0x7dcdd876, 0xbee5ca57, 0xcdb0baab, 0x0e9c00af,
+ 0xc3336f38, 0x24015685, 0x9cafc581, 0x092bd44a,
+ 0x16726fe4, 0x2bbea352, 0xddc4cda8, 0x6a765722,
+ 0x5112a566, 0x46846131, 0x9574a499, 0x5eeada94,
+ 0x3bcd015c, 0xbf400fb5, 0x392feb53, 0x98886394,
+ 0x67c9d5c1, 0x8f34b873, 0xe4c071c7, 0x59501cac,
+ 0x3c36a9d9, 0x6808ec45, 0xbd0709a5, 0x480e5237,
+ 0xe605fdb0, 0x325eeab7, 0xd1f1823e, 0xabdeb54e,
+ 0x5c3cc3c1, 0x6a9de856, 0xd0d1ab37, 0x86f4aa4a,
+ 0xb6225798, 0x17a69714, 0x060965b0, 0x23c01a2d,
+ 0xb320324d, 0x4e814079, 0x56aba687, 0x996ae1f1,
+ 0x838f96a4, 0x514d3487, 0x7237cb72, 0x2c400f8b,
+ 0x64dd3e48, 0x2f9881df, 0x828568a9, 0xf56eccbb,
+ 0x10c74e6f, 0x10fa9183, 0x2e3170e7, 0x3c11190f,
+ 0x9b2c8ee2, 0x935f1c3e, 0x089c01d9, 0x23abc8a9,
+ 0x44afdee7, 0x73e38217, 0xc977ab97, 0x82d82511,
+ 0x36fd2949, 0x17030e55, 0x4f8ba0ae, 0x77e58d26,
+ 0x7c3d438a, 0xd88e75ca, 0x97d845d8, 0x020cce46,
+ 0xe1203a80, 0xb728a263, 0xe528d2ac, 0x2fc6f435,
+ 0xdeff851f, 0xbf79ccac, 0x573ca6e6, 0x199c88db,
+ 0x0b25015a, 0xcef50e31, 0xb0c8517a, 0xf3d33e97,
+ 0xb6c1f270, 0x35ed1ff3, 0x15fe1117, 0x00000000};
+unsigned int packet3_len = 1470;
+
+#endif /*ETH_PACKETS_H_*/
diff --git a/cesar/mac/sar/test/inc/reassembly_unit_test_functions.h b/cesar/mac/sar/test/inc/reassembly_unit_test_functions.h
new file mode 100644
index 0000000000..314fea9ecd
--- /dev/null
+++ b/cesar/mac/sar/test/inc/reassembly_unit_test_functions.h
@@ -0,0 +1,52 @@
+#ifndef REASSEMBLY_UNIT_TEST_FUNCTIONS_H_
+#define REASSEMBLY_UNIT_TEST_FUNCTIONS_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_unit_test_functions.h
+ * \brief test to verify the mfs processing function
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#include "lib/blk.h"
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+
+uint list[12] = {273, 231, 1221, 159, 217, 383, 72, 1489, 230, 1176, 175};
+
+void test_sar_rx_noise_cb (void *user, const pbproc_rx_params_t *rx_params,
+ phy_chandata_t *first);
+
+/**
+ * Release the MFS in the store
+ * Release the MFS from the SAR
+ * Remove the STA from the Store
+ *
+ * Uninit the store
+ */
+void sar_unit_test_uninit_reassembly_tests (mfs_t * mfs);
+
+/**
+ * Initialize the Reassembly test generating a list of PBs.
+ */
+void sar_unit_test_generate_pb_list (pb_t **first, pb_t **last);
+
+void sar_unit_test_generate_mme_pb_list (pb_t **first, pb_t **last);
+
+/**
+ * Implementation of the sar_reassembly_done_cb_t call back.
+ * Only used in this test.
+ *
+ * \param user User data
+ * \param buffer the buffer to reassembly the data
+ * \param length the buffer length.
+ */
+void sar_reassembly_done (void *user, u8* buffer, uint length, mfs_rx_t *mfs);
+
+#endif /*REASSEMBLY_UNIT_TEST_FUNCTIONS_H_*/
diff --git a/cesar/mac/sar/test/inc/sar_unit_test_functions.h b/cesar/mac/sar/test/inc/sar_unit_test_functions.h
new file mode 100644
index 0000000000..86b533dc43
--- /dev/null
+++ b/cesar/mac/sar/test/inc/sar_unit_test_functions.h
@@ -0,0 +1,112 @@
+#ifndef SAR_UNIT_TEST_FUNCTIONS_H_
+#define SAR_UNIT_TEST_FUNCTIONS_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_unit_test_functions.h
+ * \brief function for the unit tests.
+ * \ingroup mac/sar/inc
+ *
+ */
+
+#include <stdio.h>
+
+#include "lib/rnd.h"
+#include "mac/sar/sar.h"
+
+/** TODO REMOVE THIS FUNCTIONS **/
+
+/** PB pool a pool used by the Pb proc to stock the data received from the other
+ * STA.
+ * TODO TBR*/
+struct pb_pool_t
+{
+ pb_t *head;
+ pb_t *tail;
+ uint quantity;
+};
+typedef struct pb_pool_t pb_pool_t;
+
+/** Structure to konw the status of the PBDMA
+ * TBR*/
+struct dma_status_t
+{
+BITFIELDS_WORD
+ (
+ u32 stop :1;,
+ u32 request_irq :1;,
+ u32 direction :1;,
+ u32 cv_error :1;,
+ u32 icv_reset :1;,
+ u32 icv_store :1;,
+ u32 append_zero :1;,
+ u32 data_addr_mask :25;
+)};
+typedef struct dma_status_t dma_status_t;
+
+
+struct sar_pbproc_t
+{
+ u32 cpt_expiration;
+};
+typedef struct sar_pbproc_t sar_pbproc_t;
+
+/**
+ * Initialise pbproc and return its context.
+ * \param config global mac configuration
+ * \param store MFS and STA store
+ * \param user_data user data passed to any callback
+ * \param rx_cb MPDU RX callback
+ * \return pbproc context
+ */
+pbproc_t * pbproc_init (mac_config_t *config, mac_store_t *store);
+
+void
+pbproc_init_cb (pbproc_t *ctx, void *user_data, pbproc_rx_cb_t rx_cb,
+ pbproc_rx_beacon_cb_t rx_beacon_cb);
+
+void
+pbproc_uninit(pbproc_t *ctx);
+
+/**
+ * Give segments back to pbproc for reception.
+ * \param ctx pbproc context
+ * \param first first segment
+ * \param last last segment
+ * \param nb number of segment
+ */
+void
+pbproc_rx_segment_refill (pbproc_t *ctx, pb_t *first, pb_t *last,
+ uint nb);
+
+/**
+* Unregister an MFS from the Channel Access, so that it can no longer be
+* sent.
+* \param ctx ca context
+* \param mfs the MFS to remove
+* \return true if successful
+*
+* If unsuccessful, the caller should try later because the MFS is currently
+* been used for a transmission.
+*/
+bool
+ca_mfs_remove (ca_t *ctx, mfs_tx_t *mfs);
+
+/**
+* Register an MFS with the Channel Access, so it can be sent.
+* \param ctx ca context
+* \param mfs the MFS to add
+*/
+void
+ca_mfs_add (ca_t *ctx, mfs_tx_t *mfs);
+
+void
+ca_mfs_update (ca_t *ctx, mfs_tx_t *mfs);
+
+#endif /*SAR_UNIT_TEST_FUNCTIONS_H_*/
diff --git a/cesar/mac/sar/test/maximus_test/Makefile b/cesar/mac/sar/test/maximus_test/Makefile
new file mode 100644
index 0000000000..5cfc14110a
--- /dev/null
+++ b/cesar/mac/sar/test/maximus_test/Makefile
@@ -0,0 +1,14 @@
+BASE = ../../../..
+
+ECOS = y
+
+HOST_PROGRAMS = Maximus_sar
+Maximus_sar_SOURCES = Maximus_sar.cpp
+Maximus_sar_MODULES = lib maximus
+
+TARGET_PROGRAMS = Sta_sar
+Sta_sar_SOURCES = Sta_sar.c
+Sta_sar_MODULES = lib mac/sar mac/common host hal/phy/maximus mac/pbproc mac/sar/test
+mac_pbproc_MODULE_SOURCES = mfs.c
+
+include $(BASE)/common/make/top.mk \ No newline at end of file
diff --git a/cesar/mac/sar/test/maximus_test/ecos.ecc.sh b/cesar/mac/sar/test/maximus_test/ecos.ecc.sh
new file mode 100644
index 0000000000..19597e4621
--- /dev/null
+++ b/cesar/mac/sar/test/maximus_test/ecos.ecc.sh
@@ -0,0 +1,104 @@
+config=${1:-ecos-gen.ecc}
+ecosconfig --config=$config new maximus default
+cat >> $config <<'EOF'
+cdl_option CYGPKG_HAL_MAXIMUS_CFLAGS_ADD {
+ user_value "-I\$(BASE) -I\$(OBJ_DIR)/inc"
+ # value_source user
+ # Default value: "-I\$(REPOSITORY)/../.."
+}
+cdl_option CYGBLD_GLOBAL_CFLAGS {
+ user_value "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority -finline"
+ # value_source user
+ # Default value: "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority"
+}
+cdl_option CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT {
+ user_value 0
+ inferred_value 0
+}
+cdl_option CYGBLD_ISO_CTYPE_HEADER {
+ inferred_value 1 <cyg/libc/i18n/ctype.inl>
+}
+cdl_option CYGBLD_ISO_ERRNO_CODES_HEADER {
+ inferred_value 1 <cyg/error/codes.h>
+}
+cdl_option CYGBLD_ISO_ERRNO_HEADER {
+ inferred_value 1 <cyg/error/errno.h>
+}
+cdl_option CYGBLD_ISO_STDIO_FILETYPES_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_STREAMS_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_FILEOPS_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_FILEACCESS_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_FORMATTED_IO_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_CHAR_IO_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_DIRECT_IO_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_FILEPOS_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDIO_ERROR_HEADER {
+ inferred_value 1 <cyg/libc/stdio/stdio.h>
+}
+cdl_option CYGBLD_ISO_STDLIB_STRCONV_HEADER {
+ inferred_value 1 <cyg/libc/stdlib/atox.inl>
+}
+cdl_option CYGBLD_ISO_STDLIB_ABS_HEADER {
+ inferred_value 1 <cyg/libc/stdlib/abs.inl>
+}
+cdl_option CYGBLD_ISO_STDLIB_DIV_HEADER {
+ inferred_value 1 <cyg/libc/stdlib/div.inl>
+}
+cdl_option CYGBLD_ISO_STRERROR_HEADER {
+ inferred_value 1 <cyg/error/strerror.h>
+}
+cdl_option CYGBLD_ISO_STRTOK_R_HEADER {
+ inferred_value 1 <cyg/libc/string/string.h>
+}
+cdl_option CYGBLD_ISO_STRING_LOCALE_FUNCS_HEADER {
+ inferred_value 1 <cyg/libc/string/string.h>
+}
+cdl_option CYGBLD_ISO_STRING_BSD_FUNCS_HEADER {
+ inferred_value 1 <cyg/libc/string/bsdstring.h>
+}
+cdl_option CYGBLD_ISO_STRING_MEMFUNCS_HEADER {
+ inferred_value 1 <cyg/libc/string/string.h>
+}
+cdl_option CYGBLD_ISO_STRING_STRFUNCS_HEADER {
+ inferred_value 1 <cyg/libc/string/string.h>
+}
+cdl_option CYGBLD_ISO_C_TIME_TYPES_HEADER {
+ inferred_value 1 <cyg/libc/time/time.h>
+}
+cdl_option CYGBLD_ISO_C_CLOCK_FUNCS_HEADER {
+ inferred_value 1 <cyg/libc/time/time.h>
+}
+cdl_option CYGBLD_ISO_SIGNAL_NUMBERS_HEADER {
+ inferred_value 1 <cyg/libc/signals/signal.h>
+}
+cdl_option CYGBLD_ISO_SIGNAL_IMPL_HEADER {
+ inferred_value 1 <cyg/libc/signals/signal.h>
+}
+cdl_option CYGBLD_ISO_SETJMP_HEADER {
+ inferred_value 1 <cyg/libc/setjmp/setjmp.h>
+}
+cdl_option CYGNUM_LIBC_MAIN_DEFAULT_STACK_SIZE {
+ user_value 16384
+ inferred_value 16384
+}
+cdl_option CYGSEM_ERROR_PER_THREAD_ERRNO {
+ user_value 0
+}
+EOF
+ecosconfig --config=$config check
diff --git a/cesar/mac/sar/test/maximus_test/inc/blk_t.h b/cesar/mac/sar/test/maximus_test/inc/blk_t.h
new file mode 100644
index 0000000000..eebbb60c15
--- /dev/null
+++ b/cesar/mac/sar/test/maximus_test/inc/blk_t.h
@@ -0,0 +1,27 @@
+#ifndef BLK_T_H_
+#define BLK_T_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file blk_t.h
+ * \brief <<brief>>
+ * \ingroup mac/sar/test/maximus_test/inc
+ *
+ */
+
+struct blk_t
+{
+ unsigned int qte;
+ unsigned char pbs[50][1024];
+ unsigned int header[50];
+};
+typedef struct blk_t blk_t;
+
+
+#endif /*BLK_T_H_*/
diff --git a/cesar/mac/sar/test/maximus_test/inc/max_job.h b/cesar/mac/sar/test/maximus_test/inc/max_job.h
new file mode 100644
index 0000000000..7c1b0d2c2c
--- /dev/null
+++ b/cesar/mac/sar/test/maximus_test/inc/max_job.h
@@ -0,0 +1,30 @@
+#ifndef MAX_JOB_H_
+#define MAX_JOB_H_
+
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file max_job.h
+ * \brief <brief>
+ * \ingroup mac/sar/test/maximus_test/inc
+ *
+ */
+
+struct sar_max_job_t
+{
+ struct sar_max_job_t *next;
+ unsigned char lid;
+ unsigned char tei_src;
+ unsigned char tei_dest;
+ bool bcast;
+ unsigned char mf_type;
+ unsigned char packet_id;
+};
+typedef struct sar_max_job_t sar_max_job_t;
+
+#endif /*MAX_JOB_H_*/
diff --git a/cesar/mac/sar/test/maximus_test/src/Maximus_sar.cpp b/cesar/mac/sar/test/maximus_test/src/Maximus_sar.cpp
new file mode 100644
index 0000000000..adbc0f9b42
--- /dev/null
+++ b/cesar/mac/sar/test/maximus_test/src/Maximus_sar.cpp
@@ -0,0 +1,431 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file Maximus_sar.c
+ * \brief header of the segmentation test function on maximus.
+ * \ingroup mac/sar/test/maximus_test/maximus/src
+ *
+ * Maximus selects a packet to segment in a raw of Ethernet packets.
+ * This packet is split in packet of 1024 bytes long corresponding to the
+ * maximum size of the maximus parameter.
+ *
+ * Maximus send the segmentation request and provide the parameters for the
+ * segmentation module of the SAR.
+ *
+ * The Station take the parameters and reconstitute the packet to segment
+ * ( simulate the CL or CP function ). It gives the data necessary for
+ * the SAR to segment the packet.
+ *
+ * Once the segmentation is over, the Station answer the request by giving
+ * back the PBs filled with the Ethernet packet.
+ *
+ * Maximus take the PBs and verify each byte comparing it with the Ethernet
+ * packet data.
+ */
+
+#include "maximus/common/interfaces/Maximus.h"
+#include "maximus/common/interfaces/Sta.h"
+#include "maximus/common/interfaces/Msg.h"
+#include "Error.h"
+#include <iostream> // for 'cout', 'cerr' and 'clog'
+using namespace std;
+
+#include "mac/sar/test/maximus_test/inc/blk_t.h"
+#include "mac/sar/test/maximus_test/inc/max_job.h"
+
+typedef void (station_cb_t) (Msg &msg);
+
+/**
+ * The station 1 callback
+ *
+ * \param msg the message
+ */
+void station1_cb (Msg &msg);
+
+/**
+ * The station 2 callback
+ *
+ * \param msg the message
+ */
+void station2_cb (Msg &msg);
+
+/**
+ * Launch the segmentation process on the sta with the packet provided given by
+ * packet number.
+ *
+ * \param maximus the maximus object simulator
+ * \param station the station on which the segmentation must be done
+ * \param sta_cb the callback to call once the bridge dma had finished to
+ * process a segmentation.
+ * \param job the job to be processed
+ *
+ * \return a boolean set to true.
+ */
+bool segmentation (Maximus *maximus, Sta *station, station_cb_t sta_cb,
+ sar_max_job_t *job) throw();
+
+/**
+ * Launch the segmentation process on the sta with the packet provided given by
+ * packet number.
+ *
+ * \param maximus the maximus object simulator
+ * \param station the station on which the segmentation must be done
+ * \param sta_cb the callback to call once the bridge dma had finished to
+ * process a segmentation.
+ * \param job the job to be processed
+ *
+ *
+ * \return a boolean set to true.
+ */
+bool reassembly (Maximus *maximus, Sta *station, station_cb_t sta_cb,
+ sar_max_job_t *sar_max_job) throw();
+
+/**
+ * Launch the procedure with n segmentation and one reassembly
+ *
+ * \param argc the quantity of arguments provided
+ * \param argv the char array containing the arguments
+ * \param sar_max_job an array containing the list of the row's number of the
+ * Ethernet packets.
+ *
+ * \return the end value
+ */
+int launch_x_segs (int argc, char *argv[], sar_max_job_t *sar_max_job);
+
+bool station1_rsp;
+bool station2_rsp;
+bool test_fail;
+
+int fifo_blk[2];
+
+int max_jobs_qte;
+
+int main (int argc, char *argv[])
+{
+ sar_max_job_t *sar_max_job = NULL;
+
+ try
+ {
+ station1_rsp = 0;
+ station2_rsp = 0;
+
+ /* create the fifo */
+ if (pipe (fifo_blk) < 0)
+ {
+ printf ("Can not create the pipe for the PBs communication\n");
+ exit (-1);
+ }
+
+ sar_max_job = (sar_max_job_t *) malloc (sizeof (sar_max_job_t));
+ sar_max_job->next = (sar_max_job_t *) malloc (sizeof (sar_max_job_t));
+ sar_max_job->next->next = (sar_max_job_t *) malloc (sizeof (sar_max_job_t));
+ sar_max_job->next->next->next = NULL;
+
+ /* Init job 1 */
+ sar_max_job->lid = 1;
+ sar_max_job->tei_src = 1;
+ sar_max_job->tei_dest = 2;
+ sar_max_job->bcast = false;
+ sar_max_job->mf_type = 2;
+ sar_max_job->packet_id = 0;
+
+ /* Init job 2 */
+ sar_max_job->next->lid = 1;
+ sar_max_job->next->tei_src = 1;
+ sar_max_job->next->tei_dest = 2;
+ sar_max_job->next->bcast = false;
+ sar_max_job->next->mf_type = 2;
+ sar_max_job->next->packet_id = 1;
+
+ /* Init job 3 */
+ sar_max_job->next->next->lid = 1;
+ sar_max_job->next->next->tei_src = 1;
+ sar_max_job->next->next->tei_dest = 2;
+ sar_max_job->next->next->bcast = false;
+ sar_max_job->next->next->mf_type = 2;
+ sar_max_job->next->next->packet_id = 2;
+
+ max_jobs_qte = 3;
+
+ return launch_x_segs (argc, argv, sar_max_job);
+ }
+ catch (Error &e)
+ {
+ sar_max_job_t *sar_max_job_curr;
+ while (sar_max_job)
+ {
+ sar_max_job_curr = sar_max_job;
+ sar_max_job = sar_max_job->next;
+ free (sar_max_job_curr);
+ }
+ }
+}
+
+/**
+ * Launch the procedure with n segmentation and one reassembly
+ *
+ * \param argc the quantity of arguments provided
+ * \param argv the char array containing the arguments
+ * \param sar_max_job an array containing the list of the row's number of the
+ * Ethernet packets.
+ *
+ * \return the end value
+ */
+int launch_x_segs (int argc, char *argv[], sar_max_job_t *sar_max_job)
+{
+ bool logs;
+ int i;
+ test_fail = false;
+
+ Maximus maximus;
+ maximus.init (argc, argv);
+
+ Sta station1 = maximus.create_sta ();
+ //station1.debug ();
+ Sta station2 = maximus.create_sta ();
+ //station2.debug ();
+
+ // activate the sta 1 logs
+ Msg fc = maximus.create_fc ("activate_logs");
+ logs = true;
+ fc.add_param ("rea", sizeof(unsigned char), (unsigned char *) &logs);
+ //fc.send (station1);
+ fc.send (station2);
+
+ segmentation (&maximus, &station1, station1_cb, sar_max_job);
+
+ i = 0;
+ while (!station1_rsp && !test_fail)
+ {
+ if (i > 50)
+ {
+ test_fail = true;
+ }
+ i++;
+
+ maximus.process ();
+ }
+
+ if (test_fail)
+ return -1;
+
+ reassembly (&maximus, &station2, &station2_cb, sar_max_job);
+
+ i = 0;
+ while (!station2_rsp && !test_fail)
+ {
+ if (i > 50)
+ {
+ test_fail = true;
+ }
+ i++;
+
+ maximus.process ();
+ }
+
+ maximus.wait (100);
+
+ if (test_fail)
+ return -1;
+ else
+ return 0;
+}
+
+/**
+ * The station 1 callback
+ *
+ * \param msg the message
+ */
+void station1_cb (Msg &msg)
+{
+ char value[2];
+ char id [5];
+ unsigned int val;
+ void *msg_return;
+ blk_t *blk;
+
+ //char * buffer = new char [FUNCTION_CALL_PARAM_MAX_SIZE];
+ char * buffer = new char [512];
+ unsigned long length = 512*sizeof(char);
+
+ // Try to get the error message if the segmentation fail.
+ msg_return = msg.bind_param ("type", length, (unsigned char * &) buffer);
+
+ if (strcmp (buffer, "SEG") != 0)
+ {
+ test_fail = true;
+ }
+ else
+ {
+ blk = (blk_t *) malloc (sizeof(blk_t));
+ blk->qte = msg.bind_param<unsigned int> ("qte");
+
+ for (val = 0; val < blk->qte; val++)
+ {
+ sprintf (value, "%d", val);
+
+ strcpy (id, "pb");
+ strcat (id, value);
+
+ length = 512*sizeof(char);
+ msg_return = msg.bind_param (id, length,
+ (unsigned char * &) buffer);
+
+ if (msg_return != NULL)
+ {
+ memcpy (blk->pbs[val], buffer, 512);
+ }
+
+ strcpy (id, "pbh");
+ strcat (id, value);
+ blk->header[val] = msg.bind_param<unsigned int> (id);
+ }
+
+ write (fifo_blk[1], blk, sizeof(blk_t));
+ }
+
+ delete [] buffer;
+ buffer = NULL;
+
+ station1_rsp = true;
+}
+
+/**
+ * The station 2 callback
+ *
+ * \param msg the message
+ */
+void station2_cb (Msg &msg)
+{
+ station2_rsp = true;
+}
+
+/**
+ * Launch the segmentation process on the sta with the packet provided given by
+ * packet number.
+ *
+ * \param maximus the maximus object simulator
+ * \param station the station on which the segmentation must be done
+ * \param sta_cb the callback to call once the bridge dma had finished to
+ * process a segmentation.
+ * \param job the job to be processed
+ *
+ * \return a boolean set to true.
+ */
+bool segmentation (Maximus *maximus, Sta *station, station_cb_t sta_cb,
+ sar_max_job_t *job) throw()
+{
+ sar_max_job_t *curr;
+ unsigned char job_nb;
+ char id[5];
+ char val[2];
+
+ if (!maximus || !station || !job)
+ {
+ throw Error (__PRETTY_FUNCTION__, "!maximus || !station || !job");
+ }
+
+ curr = job;
+
+ //create the function call
+ Msg fc_sta = maximus->create_fc ("segmentation");
+
+ /* add the buffer address */
+ job_nb = 0;
+ for (curr = job; curr; curr = curr->next, job_nb++)
+ {
+ sprintf (val, "%d", job_nb);
+ strcpy (id, "job");
+ strcat (id, val);
+ fc_sta.add_param (id, sizeof(sar_max_job_t), (unsigned char*) curr);
+ printf ("[DEBUG - MAX] job id : %d\n", curr->packet_id);
+ }
+
+ fc_sta.add_param ("qte", sizeof(unsigned char), (unsigned char*) &job_nb);
+
+ fc_sta.set_cb (sta_cb);
+ fc_sta.send (*station);
+
+ return true;
+}
+
+/**
+ * Launch the segmentation process on the sta with the packet provided given by
+ * packet number.
+ *
+ * \param maximus the maximus object simulator
+ * \param station the station on which the segmentation must be done
+ * \param sta_cb the callback to call once the bridge dma had finished to
+ * process a segmentation.
+ * \param job the job to be processed
+ *
+ *
+ * \return a boolean set to true.
+ */
+bool reassembly (Maximus *maximus, Sta *station, station_cb_t sta_cb,
+ sar_max_job_t *sar_max_job) throw()
+{
+ char value[3];
+ char id[5];
+ unsigned int i;
+ sar_max_job_t *curr;
+ blk_t blk;
+ unsigned char job_nb;
+
+ if (!maximus || !station || !sar_max_job)
+ {
+ throw Error (__PRETTY_FUNCTION__, "!maximus || !station || !job");
+ }
+
+ // take the first element of the fifo
+ if (read (fifo_blk[0], &blk, sizeof(blk_t)) != sizeof(blk_t))
+ {
+ return false;
+ }
+
+ //create the function call
+ Msg fc_sta = maximus->create_fc ("reassembly");
+
+ job_nb = 0;
+ for (curr = sar_max_job; curr; curr = curr->next, job_nb++)
+ {
+ sprintf (value, "%d", job_nb);
+ strcpy (id, "job");
+ strcat (id, value);
+ fc_sta.add_param (id, sizeof(sar_max_job_t), (unsigned char*) curr);
+ printf ("[DEBUG - MAX] job id : %d\n", curr->packet_id);
+ }
+
+ fc_sta.add_param ("job_qte", sizeof(unsigned char),
+ (unsigned char*) &job_nb);
+
+ /* add the buffer address */
+ fc_sta.add_param ("pb_qte", sizeof(unsigned int),
+ (unsigned char*) &blk.qte);
+
+ for (i = 0; i < blk.qte; i++)
+ {
+ sprintf (value, "%d", i);
+ strcpy (id, "pb");
+ strcat (id, value);
+
+ fc_sta.add_param (id, 1024 * sizeof(unsigned char),
+ (unsigned char*) blk.pbs[i]);
+
+ strcpy (id, "pbh");
+ strcat (id, value);
+ fc_sta.add_param (id, sizeof(unsigned int),
+ (unsigned char*) &blk.header[i]);
+ }
+
+ fc_sta.set_cb (sta_cb);
+ fc_sta.send (*station);
+
+ return true;
+}
+
diff --git a/cesar/mac/sar/test/maximus_test/src/Sta_sar.c b/cesar/mac/sar/test/maximus_test/src/Sta_sar.c
new file mode 100644
index 0000000000..0fc067355b
--- /dev/null
+++ b/cesar/mac/sar/test/maximus_test/src/Sta_sar.c
@@ -0,0 +1,1187 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file station_seg_test.c
+ * \brief header of the segmentation test function on maximus.
+ * \ingroup mac/sar/test/maximus_test/station/src
+ *
+ ****************************************************************************
+ * SEGMENTATION PROCESS *
+ *
+ * Maximus selects a packet knowing the quantity of Packets availables in the
+ * Sta
+ *
+ * Maximus send the segmentation request and provide the parameters for the
+ * segmentation module of the SAR i.e. lid, tei, packet row number.
+ *
+ * The Station takes the parameters.
+ * 1. It create the STA if it does not exists yet to segment the Ethernet
+ * packet.
+ * 2. It adds the MFS to the store and the expiration mechanism of the SAR.
+ * 3. It launch the segmentation process.
+ *
+ * Once the segmentation is over, the Sta goes to an IDLE state and will be
+ * awaken in the futur by the Maximus bridge dma.
+ * This one will create in the bridge_dma function interruption (the STA one
+ * written in this test) to provide the PBs to Maximus.
+ *
+ ****************************************************************************
+ * REASSEMBLY PROCESS *
+ *
+ * Maximus provides to the STA the following data for the reassembly process
+ *
+ * - lid, for the link with the STA which had sent the PBs
+ * - tei, the Terminal indentifier of the STA.
+ * - PBs, to reassembly.
+ * - the packet row number used to verify if the reassembly hab been correctly
+ * done.
+ *
+ * 1. The Sta receives the parameters. It will create the sta in the mac store
+ * if it does not exists yet.
+ * 2. It will create the data MFS and the mme MFS associated with the Sta if it
+ * does not exits.
+ * 3. Il will launch the reassembly process.
+ */
+
+#include <cyg/infra/diag.h>
+#include <cyg/kernel/kapi.h>
+#include <errno.h>
+#include <string.h>
+#include "common/std.h"
+#include "host/station.h"
+
+#include "mac/ca/ca.h"
+#include "mac/pbproc/pbproc.h"
+
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/sar_context.h"
+#include "mac/sar/inc/sar.h"
+#include "mac/sar/inc/sar_job_mfs.h"
+
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+
+#include "mac/sar/test/inc/eth_packets.h"
+#include "mac/sar/test/inc/ce.h"
+#include "mac/sar/test/maximus_test/inc/max_job.h"
+
+/**
+ * The function call used by maximus to launch a segmentation process to the STA.
+ *
+ */
+int activate_logs (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data);
+
+/**
+ * The function call used by maximus to launch a segmentation process to the STA.
+ *
+ */
+int segmentation (fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg,
+ void *data);
+
+/**
+ * The function call used by maximus to reassembly a Ethernet packet.
+ */
+int reassembly (fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg,
+ void *data);
+
+/**
+ * Fill the mac store if necessary
+ *
+ * \param tx if it is a tx mfs (segmentation)
+ * \param job_curr current request.
+ *
+ */
+void fill_mac_store (bool tx, sar_max_job_t *job_curr);
+
+/**
+ * Verify the data
+ * \param the way
+ * \param job_curr the current sar_max_job to verify the lid and tei
+ *
+ */
+bool verify_data_recivied (bool tx, sar_max_job_t *job_curr);
+
+/**
+ * The bridge dma function call back.
+ */
+bool bridge_dma_interruption_station (void *user, u32 status_word);
+
+/**
+ * bridge dma segmentation call back.
+ */
+bool bridge_dma_interruption_seg (sar_job_mfs_t *sar_job);
+
+/**
+ * bridge dma segmentation call back.
+ */
+bool bridge_dma_interruption_rea (sar_job_mfs_t *sar_job);
+
+/**
+ * A function to simulate the pbprocessing.
+ * It only modify the PBs order.
+ */
+u16 mix_up_pbs (pb_t **first, pb_t **last);
+
+sar_t *sar_ctx;
+mac_store_t *mac_store;
+ca_t *ca;
+pbproc_t *pbproc;
+
+extern station_ctx_t my_station;
+unsigned short msg_id;
+
+unsigned char lid;
+unsigned char tei_src;
+unsigned char tei_dest;
+bool mfs_is_mme;
+bool mfs_is_bcast;
+
+unsigned int seg_counter;
+unsigned int rea_counter;
+unsigned int mf_qte;
+
+/** Debuging data */
+/** Debug info, print all the kind of logs */
+bool debug_info;
+
+/** Print all the initialization logs for the rea and reassembly */
+bool log_init_info;
+
+/** Print all the logs of the segmentation */
+bool log_seg_info;
+
+/** Print all the logs of the reassembly*/
+bool log_rea_info;
+
+void sar_segmentation_done (void *user, u8* buffer)
+{
+
+}
+
+void sar_complete_reassembly_done (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs)
+{
+ dbg_assert (mfs);
+
+ blk_release (mfs);
+
+}
+
+void sar_expired_done (void *user, mfs_t *mfs)
+{
+ dbg_assert (mfs);
+
+ blk_release (mfs);
+}
+
+int main (void)
+{
+ int i;
+
+ debug_info = false;
+ log_init_info = false;
+ log_seg_info = false;
+ log_rea_info = false;
+
+ station_log_set_level (&my_station, STATION_LOG_DEBUG);
+ station_log_set_mask (&my_station, STATION_LOGTYPE_ALL);
+ my_station.pipe_log_fd = 1;
+
+ ca = blk_alloc ();
+ pbproc = blk_alloc ();
+
+ packets[0] = (u8 *) packet1;
+ packets[1] = (u8 *) packet2;
+ packets[2] = (u8 *) packet3;
+
+ packets_len[0] = packet1_len;
+ packets_len[1] = packet2_len;
+ packets_len[2] = packet3_len;
+
+ diag_printf ("/****************** ******************/\n");
+ for (i = 0; i < PACKETS_QTE; i++)
+ {
+ diag_printf ("PACKET %d length : %d\n", i, packets_len[i]);
+ }
+ diag_printf ("/****************** ******************/\n");
+
+ // test function call
+ fcall_register (my_station.fcall, "segmentation", &segmentation, NULL);
+ fcall_register (my_station.fcall, "reassembly", &reassembly, NULL);
+ fcall_register (my_station.fcall, "activate_logs", &activate_logs, NULL);
+
+ mac_store = mac_store_init ();
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ sar_init_measure_context (sar_ctx, sar_ctx);
+ sar_init_mme_context (sar_ctx, sar_ctx);
+ sar_init_data_context (sar_ctx, sar_ctx);
+
+ sar_init_measurement_cb (sar_ctx, NULL);
+
+ sar_init_segmentation_data_cb (sar_ctx, sar_segmentation_done);
+ sar_init_segmentation_mme_cb (sar_ctx, sar_segmentation_done);
+
+ sar_init_reassembly_data_cb (sar_ctx, sar_complete_reassembly_done);
+ sar_init_segmentation_mme_cb (sar_ctx, sar_segmentation_done);
+ sar_init_reassembly_mme_cb (sar_ctx, sar_complete_reassembly_done);
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ sar_init_expiration (sar_ctx, sar_expired_done);
+
+ sar_ctx->bridgedma_ctx = phy_bridgedma_init (NULL,
+ bridge_dma_interruption_station, bridge_dma_deffered_interruption);
+
+ return 0;
+}
+
+/**
+ * The function call used by maximus to launch a segmentation process to the STA.
+ *
+ */
+int activate_logs (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data)
+{
+ fcall_param_bind (*param, *msg, "debug", sizeof(u8), &debug_info);
+ fcall_param_bind (*param, *msg, "init", sizeof(u8), &log_init_info);
+ fcall_param_bind (*param, *msg, "seg", sizeof(u8), &log_seg_info);
+ fcall_param_bind (*param, *msg, "rea", sizeof(u8), &log_rea_info);
+
+ log_init_info |= debug_info;
+ log_seg_info |= debug_info;
+ log_rea_info |= debug_info;
+
+ /** reset the param list **/
+ fcall_param_reset (*param);
+
+ /* return */
+ fcall_return (my_station.fcall, *param, *msg);
+
+ return true;
+}
+
+/**
+ * Fill the mac store if necessary
+ *
+ * \param tx if it is a tx mfs (segmentation)
+ * \param job_curr current request.
+ *
+ */
+void fill_mac_store (bool tx, sar_max_job_t *job_curr)
+{
+ sta_t *sta= NULL;
+ bool added;
+
+ if (tx)
+ {
+ mfs_tx_t *mfs;
+ if (MAC_TEI_IS_STA (job_curr->tei_dest))
+ {
+ sta = mac_store_sta_get (sar_ctx->expiration.mfs_store,
+ job_curr->tei_dest);
+ }
+
+ if (!sta && MAC_TEI_IS_STA (job_curr->tei_dest))
+ {
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT SEG] Adding the STA to the mac store, tei : %d\n",
+ job_curr->tei_dest);
+ }
+
+ /* Add the sta to the mac store */
+ mac_store_sta_add (sar_ctx->expiration.mfs_store,
+ job_curr->tei_dest);
+
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT SEG] Adding the MFS to the mac store, lid : %d, tei : %d, bcast : %d\n",
+ job_curr->lid, job_curr->tei_dest, job_curr->bcast);
+ }
+ /* Add the MFS to the mac store */
+ if (job_curr->lid != MAC_LID_NONE)
+ {
+ mfs = mac_store_mfs_add_tx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, false, job_curr->lid,
+ job_curr->tei_dest, &added);
+ }
+ else
+ {
+ mfs = mac_store_mfs_add_tx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, true, job_curr->lid,
+ job_curr->tei_dest, &added);
+ }
+
+ dbg_assert (added);
+ mfs->head = NULL;
+ mfs->tail = NULL;
+ }
+ else
+ {
+ /* Get the MFS from the Store */
+ if (job_curr->lid != MAC_LID_NONE)
+ {
+ mfs= mac_store_mfs_get_tx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, false, job_curr->lid,
+ job_curr->tei_dest);
+ }
+ else
+ {
+ mfs = mac_store_mfs_get_tx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, true, job_curr->lid,
+ job_curr->tei_dest);
+ }
+
+ if (!mfs)
+ {
+ /* Add the MFS to the mac store */
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT-SEG] Adding the MFS to the mac store, lid : %d, tei : %d, bcast : %d\n",
+ job_curr->lid, job_curr->tei_dest,
+ job_curr->bcast);
+ }
+
+ mfs = mac_store_mfs_add_tx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, false, job_curr->lid,
+ job_curr->tei_dest, &added);
+ dbg_assert (added);
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ // add the mfs to the sar expiration
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+ }
+ }
+ }
+ else
+ {
+ if (!sta && MAC_TEI_IS_STA (job_curr->tei_src))
+ {
+ mfs_rx_t * mfs;
+
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT-REA] Add the STA to the mac store, tei : %d\n",
+ job_curr->tei_src);
+ }
+ /* Add the sta to the store */
+ mac_store_sta_add (sar_ctx->expiration.mfs_store,
+ job_curr->tei_src);
+
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT-REA] Add the data MFS to the mac store, lid : %d, tei : %d\n",
+ job_curr->lid, job_curr->tei_src);
+ diag_printf ("[INIT-REA] Add the data MFS to SAR expiration mechanism\n");
+ }
+
+ /* Add the mfs to the store */
+ mfs = mac_store_mfs_add_rx (sar_ctx->expiration.mfs_store, false,
+ false, job_curr->lid, job_curr->tei_src, &added);
+ dbg_assert (added);
+
+ /* Add the mfs to the SAR expiration */
+ mfs->common.expiration_ntb = mac_ntb() + 100;
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT-REA] Add the mme MFS to the mac store, lid : %d, tei : %d\n",
+ job_curr->lid, job_curr->tei_src);
+ diag_printf ("[INIT-REA] Add the mme MFS to SAR expiration mechanism\n");
+ }
+ /* Add the MME MFS to the store */
+ mfs = mac_store_mfs_add_rx (sar_ctx->expiration.mfs_store, false,
+ true, MAC_LID_NONE, job_curr->tei_src, &added);
+ dbg_assert (added);
+
+ /* Add the mfs to the sar expiration */
+ mfs->common.expiration_ntb = mac_ntb() + 100;
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+ }
+ else
+ {
+ /* Verify if the lid is a plid one */
+ if (!MAC_LID_IS_PLID (job_curr->lid))
+ {
+ mfs_rx_t * mfs;
+
+ /* Add the mfs to the store */
+ mfs = mac_store_mfs_get_rx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, false, job_curr->lid,
+ job_curr->tei_src);
+
+ if (!mfs)
+ {
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT-REA] Add the data MFS to the mac store, lid : %d, tei : %d\n",
+ job_curr->lid, job_curr->tei_src);
+ diag_printf ("[INIT-REA] Add the data MFS to SAR expiration mechanism\n");
+ }
+ /* Add the mfs to the store */
+ mfs = mac_store_mfs_add_rx (
+ sar_ctx->expiration.mfs_store, job_curr->bcast,
+ false, job_curr->lid, job_curr->tei_src, &added);
+ dbg_assert (added);
+
+ /* Add the mfs to the SAR expiration */
+ mfs->common.expiration_ntb = mac_ntb() + 100;
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+ }
+
+ /* Verifies the MME mfs */
+ mfs = mac_store_mfs_get_rx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, true, MAC_LID_NONE,
+ job_curr->tei_src);
+
+ if (!mfs)
+ {
+ if (log_init_info)
+ {
+ diag_printf (
+ "[INIT-REA] Add the mme MFS to the mac store, lid : %d, tei : %d\n",
+ job_curr->lid, job_curr->tei_src);
+ diag_printf ("[INIT-REA] Add the mme MFS to SAR expiration mechanism\n");
+ }
+
+ /* Add the MME MFS to the store */
+ mfs = mac_store_mfs_add_rx (
+ sar_ctx->expiration.mfs_store, job_curr->bcast,
+ true, MAC_LID_NONE, job_curr->tei_src, &added);
+ dbg_assert (added);
+
+ /* Add the mfs to the sar expiration */
+ mfs->common.expiration_ntb = mac_ntb() + 100;
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Verify the data
+ * \param the way
+ * \param job_curr the current sar_max_job to verify the lid and tei
+ *
+ */
+bool verify_data_recivied (bool tx, sar_max_job_t *job_curr)
+{
+ /* Verifying the data received */
+ if (job_curr->lid == 0)
+ {
+ job_curr->lid = MAC_LID_NONE;
+ lid = MAC_LID_NONE;
+
+ if (log_init_info && tx)
+ diag_printf ("[INIT SEG] lid had been modified to MAC_LID_NONE\n");
+ else
+ diag_printf ("[INIT REA] lid had been modified to MAC_LID_NONE\n");
+ }
+
+ /* Verify if the type of the MF is compatible with the lid */
+ if (job_curr->mf_type != 3&& job_curr->lid == MAC_LID_NONE)
+ {
+ if (log_init_info)
+ diag_printf ("[INIT SEG] lid is a mme lid and the MF type is not a mme type\n");
+ return false;
+ }
+
+ if (tx && job_curr->bcast&& job_curr->tei_dest != MAC_TEI_BCAST)
+ {
+ job_curr->tei_dest = MAC_TEI_BCAST;
+ tei_dest = MAC_TEI_BCAST;
+
+ if (log_init_info)
+ diag_printf ("[INIT SEG] tei had been modified to MAC_TEI_BCAST\n");
+ }
+ else if (!tx && job_curr->bcast&& job_curr->tei_src != MAC_TEI_BCAST)
+ {
+ job_curr->tei_src = MAC_TEI_BCAST;
+ tei_src = MAC_TEI_BCAST;
+
+ if (log_init_info)
+ diag_printf ("[INIT REA] tei had been modified to MAC_TEI_BCAST\n");
+ }
+
+ return true;
+}
+
+/**
+ * The function call used by maximus to launch a segmentation process to the STA.
+ *
+ */
+int segmentation (fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg,
+ void *data)
+{
+ u8 jobs_qte;
+ mfs_tx_t *mfs;
+ u8 i;
+ u8 id[5];
+ u8 val[2];
+ bool mme;
+
+ sar_max_job_t *jobs= NULL;
+ sar_max_job_t *job_curr= NULL;
+
+ msg_id = (*param)->msg_id;
+
+ fcall_param_bind (*param, *msg, "qte", sizeof(u8), &jobs_qte);
+
+ seg_counter = 0;
+ mf_qte = jobs_qte;
+
+ for (i = 0; i < jobs_qte; i++)
+ {
+ if (!jobs)
+ {
+ jobs = (sar_max_job_t *) malloc (sizeof(sar_max_job_t));
+ job_curr = jobs;
+ }
+ else
+ {
+ job_curr->next = (sar_max_job_t *) malloc (sizeof(sar_max_job_t));
+ job_curr = job_curr->next;
+ }
+ job_curr->next = NULL;
+
+ sprintf (val, "%d", i);
+ strcpy (id, "job");
+ strcat (id, val);
+ fcall_param_bind (*param, *msg, id, sizeof(sar_max_job_t), job_curr);
+ }
+
+ /** store the lid and tei in the STA
+ * If it is not done, the fcall answer will be false
+ * All the jobs must be to the same MFS.
+ * */
+ lid = jobs->lid;
+ tei_dest = jobs->tei_dest;
+ mfs_is_bcast = jobs->bcast;
+
+ for (job_curr = jobs; job_curr; job_curr = job_curr->next)
+ {
+ if (log_init_info)
+ {
+ diag_printf ("[INIT SEG] lid : %d\n", job_curr->lid);
+ diag_printf ("[INIT SEG] tei : %d\n", job_curr->tei_dest);
+ diag_printf ("[INIT SEG] mf_type : %d\n", job_curr->mf_type);
+ diag_printf ("[INIT SEG] bcast : %d\n", job_curr->bcast);
+ diag_printf ("[INIT SEG] packet : %d\n", job_curr->packet_id);
+ }
+
+ fill_mac_store (true, job_curr);
+
+ if (lid == job_curr->lid&& tei_dest == job_curr->tei_dest
+ && verify_data_recivied (true, job_curr))
+ {
+
+ /* Get the MFS from the store */
+ if (job_curr->mf_type == 3)
+ mme = true;
+ else
+ mme = false;
+
+ mfs = mac_store_mfs_get_tx (sar_ctx->expiration.mfs_store,
+ job_curr->bcast, mme, job_curr->lid, job_curr->tei_dest);
+ mfs->common.ats = true;
+
+ if (log_init_info)
+ {
+ diag_printf ("[SEG] Adding an msdu \n");
+ diag_printf ("[SEG] packet number : %d\n",
+ job_curr->packet_id);
+ diag_printf ("[SEG] msdu type : %d\n", job_curr->mf_type);
+ diag_printf ("[SEG] packet len : %d\n",
+ packets_len[job_curr->packet_id]- 1);
+ diag_printf ("[SEG] ATS : %x\n", 0x12345678);
+ diag_printf ("[SEG] mfs @ : %p\n", mfs);
+ diag_printf ("[SEG] lid : %d\n", mfs->common.lid);
+ diag_printf ("[SEG] tei : %d\n", mfs->common.tei);
+ diag_printf ("[SEG] bcast : %d\n", mfs->common.bcast);
+ }
+
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+
+ sar_msdu_add (sar_ctx, packets[job_curr->packet_id],
+ packets_len[job_curr->packet_id], 0x12345678, mfs);
+
+ /** Launch the SAR to segment the msdu **/
+ sar_launch (sar_ctx);
+
+ if (log_seg_info)
+ diag_printf ("[SEG] MSDU segmented\n");
+
+ }
+ }
+
+ for (job_curr = jobs; jobs; job_curr = jobs)
+ {
+ jobs = job_curr->next;
+ free (job_curr);
+ }
+
+ fcall_param_set_async (*param, 1);
+
+ return true;
+}
+
+///**
+// * The function call used by maximus to reassembly a Ethernet packet.
+// */
+int reassembly (fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg,
+ void *data)
+{
+ u32 pb_nb;
+ u32 i;
+ u8 value [3];
+ u8 id [5];
+ u8 jobs_qte;
+
+ u8 param_buffer[1024];
+
+ mfs_rx_t *mfs;
+ bool mme;
+ pbproc_rx_params_t rx_params;
+
+ u16 mf_length;
+
+ /* buffer aligned for the reassembly process */
+ u8 *sar_buffer __attribute__((aligned(2048)));
+
+ pb_t *pb_head;
+ pb_t *pb_tail;
+
+ sar_max_job_t *sar_max_jobs= NULL;
+ sar_max_job_t *sar_max_job_curr= NULL;
+
+ rea_counter = 0;
+
+ msg_id = (*param)->msg_id;
+
+ fcall_param_bind (*param, *msg, "job_qte", sizeof(u8), &jobs_qte);
+ mf_qte = jobs_qte;
+
+ for (i = 0; i < jobs_qte; i++)
+ {
+ if (!sar_max_jobs)
+ {
+ sar_max_jobs = (sar_max_job_t *) malloc (sizeof(sar_max_job_t));
+ sar_max_job_curr = sar_max_jobs;
+ }
+ else
+ {
+ sar_max_job_curr->next
+ = (sar_max_job_t *) malloc (sizeof(sar_max_job_t));
+ sar_max_job_curr = sar_max_job_curr->next;
+ }
+ sar_max_job_curr->next = NULL;
+
+ sprintf (value, "%d", i);
+ strcpy (id, "job");
+ strcat (id, value);
+ fcall_param_bind (*param, *msg, id, sizeof(sar_max_job_t),
+ sar_max_job_curr);
+ }
+
+ /** store the lid and tei in the STA
+ * If it is not done, the fcall answer will be false
+ * All the jobs must be to the same MFS.
+ * */
+ lid = sar_max_jobs->lid;
+ tei_src = sar_max_jobs->tei_src;
+
+ if (log_init_info)
+ {
+ diag_printf ("[INIT-REA] lid : %d\n", sar_max_job_curr->lid);
+ diag_printf ("[INIT-REA] tei : %d\n", sar_max_job_curr->tei_src);
+ diag_printf ("[INIT-REA] bcast : %d\n", sar_max_job_curr->bcast);
+ diag_printf ("[INIT-REA] packet : %d\n", sar_max_job_curr->packet_id);
+ }
+
+ verify_data_recivied (false, sar_max_job_curr);
+ fill_mac_store (false, sar_max_job_curr);
+
+ if (sar_max_job_curr->mf_type > 2)
+ mme = true;
+ else
+ mme = false;
+
+ mfs = mac_store_mfs_get_rx (sar_ctx->expiration.mfs_store,
+ sar_max_job_curr->bcast, mme, lid, tei_src);
+ mfs->common.ats = true;
+
+ /* Getting the PBs from Maximus */
+ fcall_param_bind (*param, *msg, "pb_qte", sizeof(u32), &pb_nb);
+
+ if (log_rea_info)
+ diag_printf ("[REA] PBs received : %d\n", pb_nb);
+
+ pb_head = NULL;
+ pb_tail = NULL;
+
+ for (i = 0; i < pb_nb; i++)
+ {
+ sprintf (value, "%d", i);
+ strcpy (id, "pb");
+ strcat (id, value);
+
+ if (!pb_head)
+ {
+ pb_head = (pb_t *) blk_alloc_desc ();
+ pb_tail = pb_head;
+ pb_head->next = NULL;
+ }
+ else
+ {
+ pb_tail->next = (pb_t *) blk_alloc_desc ();
+ pb_tail = pb_tail->next;
+ pb_tail->next = NULL;
+ }
+
+ /* Get the pb with the header concatenate with the data */
+ fcall_param_bind (*param, *msg, id, 1024 * sizeof(u8), param_buffer);
+
+ /* copy the data to the PB */
+ memcpy (pb_tail->data, param_buffer, BLK_SIZE);
+
+ strcpy (id, "pbh");
+ strcat (id, value);
+ /* Get the PB header */
+ fcall_param_bind (*param, *msg, id, sizeof(u32), param_buffer);
+ memcpy (&pb_tail->header, param_buffer, sizeof(u32));
+
+ /* Validate the PB putting the vpbf flag to 1 */
+ pb_tail->header.vpbf = true;
+ }
+
+ mf_length = mf_get_length (pb_head, pb_head->header.mfbo, true);
+
+ if (debug_info)
+ {
+ pb_t *pb_curr;
+
+ for (pb_curr = pb_head; pb_curr; pb_curr = pb_curr->next)
+ {
+ diag_printf ("[DEBUG - TX] @ : %p\n", pb_curr);
+ diag_printf ("[DEBUG - RX] ssn : %d\n", pb_curr->header.ssn);
+ diag_printf ("[DEBUG - RX] vpbf : %d\n", pb_curr->header.vpbf);
+ }
+ diag_printf ("[DEBUG - RX] MF length : %d\n", mf_length);
+ }
+
+ if (log_rea_info)
+ {
+ diag_printf ("[REA] **** Mixing the PBs **** \n");
+ }
+
+ mix_up_pbs (&pb_head, &pb_tail);
+
+ if (log_rea_info)
+ {
+ pb_t *pb_curr;
+
+ for (pb_curr = pb_head; pb_curr; pb_curr = pb_curr->next)
+ {
+ diag_printf ("[DEBUG - TX] @ : %p\n", pb_curr);
+ diag_printf ("[DEBUG - RX] ssn : %d\n", pb_curr->header.ssn);
+ }
+
+ diag_printf ("[REA] **** PBs Mixed **** \n");
+ }
+
+ rx_params.tei = tei_src;
+ rx_params.lid = lid;
+ rx_params.bcast = sar_max_job_curr->bcast;
+
+ if (log_rea_info)
+ {
+ diag_printf ("[REA] MFS : %p\n", mfs);
+ if (mfs && debug_info)
+ {
+ diag_printf ("[DEBUG-REA] data MFS, lid : %d, tei : %d\n",
+ mfs->common.lid, mfs->common.tei);
+ }
+
+ diag_printf ("[REA] lid : %d\n", rx_params.lid);
+ diag_printf ("[REA] tei : %d\n", rx_params.tei);
+ diag_printf ("[REA] bcast : %d\n", rx_params.bcast);
+
+ diag_printf ("[REA] Launching the reassembly process...\n");
+ }
+
+ for (i = 0; i < mf_qte; i++)
+ {
+ /* add the buffer to the sar for the reassembly */
+ sar_buffer = (u8 *) malloc (2048 * sizeof(u8));
+
+ if (log_rea_info)
+ {
+ diag_printf ("[REA] buffer added : %p\n", sar_buffer);
+ }
+ sar_data_buffer_add (sar_ctx, sar_buffer);
+ sar_launch (sar_ctx);
+ }
+
+ if (mfs && mfs->common.mme)
+ {
+ sar_mpdu_add (sar_ctx, NULL, (mfs_t *) mfs, &rx_params, pb_head,
+ pb_tail, pb_nb, NULL);
+ }
+ else if (mfs)
+ {
+ sar_mpdu_add (sar_ctx, (mfs_t *)mfs, NULL, &rx_params, pb_head,
+ pb_tail, pb_nb, NULL);
+ }
+
+ sar_launch (sar_ctx);
+ if (log_rea_info)
+ diag_printf ("[REA] Reassembly process executed\n");
+
+ for (sar_max_job_curr = sar_max_jobs; sar_max_jobs; sar_max_job_curr
+ = sar_max_jobs)
+ {
+ sar_max_jobs = sar_max_job_curr->next;
+ free (sar_max_job_curr);
+ }
+
+ fcall_param_set_async (*param, 1);
+
+ return true;
+}
+
+/**
+ * The bridge dma function call back.
+ */
+bool bridge_dma_interruption_station (void *user, u32 status_word)
+{
+ sar_job_mfs_t *sar_job;
+
+ sar_job = bridge_dma_get_head (&sar_ctx->bridge_dma_jobs);
+ dbg_assert (sar_job);
+
+ if (sar_job->job.direction == 0)
+ {
+ return bridge_dma_interruption_seg (sar_job);
+ }
+ else
+ {
+ return bridge_dma_interruption_rea (sar_job);
+ }
+}
+
+/**
+ * bridge dma segmentation call back.
+ */
+bool bridge_dma_interruption_seg (sar_job_mfs_t *sar_job)
+{
+ static fcall_param_t return_param;
+ static sci_msg_t return_msg;
+ static unsigned char return_buffer[SCI_MSG_MAX_SIZE];
+
+ bool error = false;
+ u16 pb_qte;
+
+ dbg_assert (sar_job);
+
+ pb_qte = mf_get_quantity_of_pb ((pb_t *) sar_job->job.first_pb_desc,
+ sar_job->job.first_pb_offset);
+
+ if (debug_info)
+ {
+ diag_printf ("\t[BRIDGE - TX] sar_job @ %p\n", sar_job);
+ diag_printf ("\t[BRIDGE - TX] job->data_addr : %p\n",
+ sar_job->job.data_addr);
+ diag_printf ("\t[BRIDGE - TX] job->first_pb_desc : %p\n",
+ sar_job->job.first_pb_desc);
+ diag_printf ("\t[BRIDGE - TX] job->first_pb_offset : %d\n",
+ sar_job->job.first_pb_offset);
+ diag_printf ("\t[BRIDGE - TX] job->pb_quantity : %d\n",
+ sar_job->pb_quantity);
+ diag_printf ("\t[BRIDGE - TX] job->data_addr : %p\n",
+ sar_job->job.data_addr);
+ diag_printf ("\t[BRIDGE - TX] job->data_len : %d\n",
+ sar_job->job.data_len);
+ diag_printf ("\t[BRIDGE - TX] MF len : %d\n", mf_get_length (
+ (pb_t *)sar_job->job.first_pb_desc,
+ sar_job->job.first_pb_offset, false));
+ diag_printf ("\t[BRIDGE - TX] MF qte PB : %d\n",
+ mf_get_quantity_of_pb ((pb_t *)sar_job->job.first_pb_desc,
+ sar_job->job.first_pb_offset));
+ diag_printf ("\t[BRIDGE - TX] job @ : %p\n", sar_job);
+
+ if (debug_info)
+ {
+ int deb;
+ diag_printf ("[DEBUG - TX] PB data header : ");
+ for (deb = 0; deb < 6; deb++)
+ {
+ diag_printf (
+ "%02x ",
+ ((pb_t *)sar_job->job.first_pb_desc)->data[deb + sar_job->job.first_pb_offset]);
+ }
+ diag_printf ("\n");
+ }
+ }
+
+ if (!(pb_qte == sar_job->pb_quantity&& sar_job->mfs->tx.head))
+ {
+ diag_printf ("/***********************************************************/\n");
+ diag_printf (" :( [Segmentation] FAIL :(\n");
+ diag_printf ("/***********************************************************/\n");
+
+ blk_release (sar_job->mfs);
+ blk_release (sar_job);
+
+ return false;
+ }
+
+ diag_printf ("/***********************************************************/\n");
+ diag_printf (" ^^ [Segmentation] SUCCESS ^^\n");
+ diag_printf ("/***********************************************************/\n");
+ blk_release (sar_job->mfs);
+ blk_release (sar_job);
+
+ seg_counter ++;
+
+ /** Create the return call back function */
+ if (seg_counter == mf_qte)
+ {
+ int _pb_qte;
+ mfs_tx_t *mfs;
+
+ if (lid == MAC_LID_NONE)
+ {
+ mfs_is_mme = true;
+ }
+ else
+ {
+ mfs_is_mme = false;
+ }
+
+ /** Get the MFS */
+ mfs = mac_store_mfs_get_tx (sar_ctx->expiration.mfs_store,
+ mfs_is_bcast, mfs_is_mme, lid, tei_dest);
+
+ /** init structures **/
+ fcall_param_init (&return_param, "seg_complete_done", msg_id);
+ sci_msg_init (&return_msg, return_buffer, SCI_MSG_MAX_SIZE);
+
+ /** reset the param list **/
+ fcall_param_reset (&return_param);
+
+ u8 id [5];
+ u8 value [3];
+ u8 i;
+ pb_t *pb_curr;
+
+ fcall_param_add (&return_param, &return_msg, "type", 4* sizeof(u8),
+ (unsigned char *) "SEG");
+
+ for (_pb_qte = 0, i = 0, pb_curr = mfs->head; pb_curr; i++, _pb_qte ++)
+ {
+ sprintf (value, "%d", i);
+
+ if (debug_info)
+ {
+ diag_printf ("[DEBUG - TX] ssn : %d\n", pb_curr->header.ssn);
+ }
+
+ strcpy (id, "pbh");
+ strcat (id, value);
+ fcall_param_add_long (&return_param, &return_msg, id,
+ &pb_curr->header);
+
+ strcpy (id, "pb");
+ strcat (id, value);
+ fcall_param_add (&return_param, &return_msg, id, BLK_SIZE,
+ (unsigned char *) pb_curr->data);
+
+ pb_curr = pb_free (pb_curr);
+ }
+
+ fcall_param_add_long (&return_param, &return_msg, "qte",
+ (unsigned char *) &_pb_qte);
+
+ /* return */
+ fcall_return (my_station.fcall, &return_param, &return_msg);
+ }
+
+ return !error;
+}
+
+/**
+ * bridge dma segmentation call back.
+ */
+bool bridge_dma_interruption_rea (sar_job_mfs_t *sar_job)
+{
+ static fcall_param_t return_param;
+ static sci_msg_t return_msg;
+ static unsigned char return_buffer[SCI_MSG_MAX_SIZE];
+
+ uint i;
+ u16 mf_length;
+ u8 packet_nb;
+ bool error = false;
+
+ dbg_assert (sar_job->pb_quantity);
+
+ mf_length = mf_get_length ((pb_t *)sar_job->job.first_pb_desc,
+ sar_job->job.first_pb_offset, true);
+
+ if (debug_info)
+ {
+ uint deb;
+ diag_printf ("[DEBUG - RX] PB data header : ");
+ for (deb = 0; deb < 6; deb++)
+ {
+ diag_printf ("%02x ", ((pb_t *)sar_job->job.first_pb_desc)->data[deb]);
+ }
+ diag_printf ("\n");
+ }
+
+ for (packet_nb = 0; packet_nb < PACKETS_QTE && mf_length
+ != packets_len[packet_nb]; packet_nb++)
+ ;
+
+ if (debug_info)
+ {
+ diag_printf ("\t[BRIDGE - RX] sar_job @ %p\n", sar_job);
+ diag_printf ("\t[BRIDGE - RX] job->data_addr : %p\n",
+ sar_job->job.data_addr);
+ diag_printf ("\t[BRIDGE - RX] job->first_pb_desc : %p\n",
+ sar_job->job.first_pb_desc);
+ diag_printf ("\t[BRIDGE - RX] job->first_pb_offset : %d\n",
+ sar_job->job.first_pb_offset);
+ diag_printf ("\t[BRIDGE - RX] job->pb_quantity : %d\n",
+ sar_job->pb_quantity);
+ diag_printf ("\t[BRIDGE - RX] job->data_addr : %p\n",
+ sar_job->job.data_addr);
+ diag_printf ("\t[BRIDGE - RX] job->data_len : %d\n",
+ sar_job->job.data_len);
+ diag_printf ("\t[BRIDGE - RX] MF len : %d\n", mf_get_length (
+ (pb_t *)sar_job->job.first_pb_desc,
+ sar_job->job.first_pb_offset, false));
+ diag_printf ("\t[BRIDGE - RX] MF qte PB : %d\n",
+ mf_get_quantity_of_pb ((pb_t *)sar_job->job.first_pb_desc,
+ sar_job->job.first_pb_offset));
+ diag_printf ("\t[BRIDGE - RX] job @ : %p\n", sar_job);
+ }
+
+ for (i = 0; i < packets_len[packet_nb]&& !error; i++)
+ {
+ if (packets[packet_nb][i] != sar_job->job.data_addr[i])
+ {
+ error = true;
+ }
+ }
+
+ if (packet_nb == PACKETS_QTE || error)
+ {
+ error = true;
+
+ diag_printf ("/***********************************************************/\n");
+ diag_printf (" :( [Reassembly] FAIL :(\n");
+ diag_printf ("/***********************************************************/\n");
+ }
+ else
+ {
+ diag_printf ("/***********************************************************/\n");
+ diag_printf (" ^^ [Reassembly] SUCCESS ^^\n");
+ diag_printf ("/***********************************************************/\n");
+ }
+
+ for (i = 0; i < sar_job->pb_quantity; i++)
+ {
+ sar_job->job.first_pb_desc
+ = (blk_t *) pb_free ((pb_t *) sar_job->job.first_pb_desc);
+ }
+
+ blk_release (sar_job->mfs);
+ free (sar_job->job.data_addr);
+ blk_release (sar_job);
+
+ rea_counter ++;
+
+ if (rea_counter == mf_qte)
+ {
+ /** init structures **/
+ fcall_param_init (&return_param, "rea_complete_done", msg_id);
+ sci_msg_init (&return_msg, return_buffer, SCI_MSG_MAX_SIZE);
+
+ /** reset the param list **/
+ fcall_param_reset (&return_param);
+
+ fcall_param_add (&return_param, &return_msg, "type", 4* sizeof(u8),
+ (unsigned char*) "REA");
+
+ fcall_return (my_station.fcall, &return_param, &return_msg);
+ }
+
+ return !error;
+}
+
+/**
+ * A function to simulate the pbprocessing.
+ * It only modify the PBs order.
+ */
+u16 mix_up_pbs (pb_t **first, pb_t **last)
+{
+ pb_t *list[100];
+ u16 size;
+ pb_t *head;
+ pb_t *tmp;
+ lib_rnd_t rnd_ctx1;
+ lib_rnd_t rnd_ctx2;
+ int i;
+ u16 slot1;
+ u16 slot2;
+
+ lib_rnd_init (&rnd_ctx1, 123456);
+ lib_rnd_init (&rnd_ctx2, 234567);
+
+ //count the quantity of PBs.
+ for (size = 0, head = *first; head != NULL; head = head->next, size++)
+ {
+ list[size] = head;
+ }
+ list[size] = NULL;
+
+ // randomize the list
+ for (i = 0; i < size; i++)
+ {
+ slot1 = lib_rnd32 (&rnd_ctx1) % size;
+ slot2 = lib_rnd32 (&rnd_ctx2) % size;
+
+ tmp = list[slot1];
+ list[slot1] = list[slot2];
+ list[slot2] = tmp;
+ }
+
+ //Chain the PB list
+ for (i = 0; i < size - 1; i++)
+ {
+ list[i]->next = list[i+1];
+ }
+
+ *first = list[0];
+ *last = list[size - 1];
+ list[size - 1]->next = NULL;
+
+ return size;
+}
diff --git a/cesar/mac/sar/test/src/ce.c b/cesar/mac/sar/test/src/ce.c
new file mode 100644
index 0000000000..a56c7019c9
--- /dev/null
+++ b/cesar/mac/sar/test/src/ce.c
@@ -0,0 +1,140 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file ce.c
+ * \brief Context of the CE
+ * \ingroup mac/sar/test/src
+ *
+ * contains a minimum of the CE data to take the measurement of the PBs.
+ *
+ */
+
+#include "common/std.h"
+#include "mac/sar/test/inc/ce.h"
+
+/**
+ * Init the CE and get the context pointer.
+ */
+ce_t *ce_init (void)
+{
+ ce_ctx.measurement_head = NULL;
+ ce_ctx.measurement_tail = NULL;
+
+ ce_ctx.rx_params_head = NULL;
+ ce_ctx.rx_params_tail = NULL;
+
+ return &ce_ctx;
+}
+
+/**
+ * Pb measurement RX callback for Channel estimation.
+ * This call back will return one or two block in order to insert all the
+ * measurements contained in each PB of the mpdu received.
+ * Two cases can happen, the first the pb_nb is lesser than the blk capacity,
+ * this callback will return only a blk pointed by the first and the last
+ * pointer.
+ * In the second case the quantity of PB are greater than one blk capacity, this
+ * callback will return two blk (chained) the first pointed by the first pointer
+ * and the last one by the last pointer.
+ *
+ * \param user User data
+ * \param rx_params Frame control information to know date and tonemap used
+ * \param number of pbs
+ * \param first blk to insert the measurements.
+ * \param last blk to insert the measurements.
+ * \param chandata chan data measurements
+ *
+ * \return boolean to indicate if a block had been returned or not.
+ */
+bool ce_measurements (void *user, pbproc_rx_params_t *rx_params, uint pb_nb,
+ blk_t **first, blk_t **last, pb_t *chandata, uint nb_chandata, uint
+ *blk_offset)
+{
+ ce_store_rx_params_t *ce_rx_params = NULL;
+
+ /*
+ * author nelio
+ * 26 sept. 07 - 09:56:56
+ *
+ * Not use by the SAR the rx_params are only copied from the CA to provide
+ * it to the CE.
+ */
+
+ dbg_assert (rx_params);
+ ce_rx_params = blk_alloc ();
+
+ /* If the quantity of PBs are greater than 128 allocates two BLK */
+ if (pb_nb > 128)
+ {
+ *first = blk_alloc_desc ();
+ *last = blk_alloc_desc ();
+ ((blk_t *)*first)->next = *last;
+ }
+ else
+ {
+ *first = blk_alloc_desc ();
+ *last = *first;
+ }
+
+ /* Keep it in the structure */
+ if (ce_ctx.measurement_head == NULL)
+ {
+ ce_ctx.measurement_head = *first;
+ ce_ctx.measurement_tail = *last;
+ }
+ else
+ {
+ ce_ctx.measurement_tail->next = *first;
+ ce_ctx.measurement_tail = *last;
+ }
+
+ /* allocate the structure to store the rx_params */
+ ce_rx_params->rx_params = rx_params;
+
+ /* Store the rx_params to the structure */
+ if (ce_ctx.rx_params_head == NULL)
+ {
+ ce_ctx.rx_params_head = ce_rx_params;
+ ce_ctx.rx_params_tail = ce_rx_params;
+ }
+ else
+ {
+ ce_ctx.rx_params_tail->next = ce_rx_params;
+ ce_ctx.rx_params_tail = ce_rx_params;
+ }
+ ce_ctx.rx_params_tail->next = NULL;
+
+ ce_ctx.chandata = chandata;
+
+ ((blk_t *)*last)->next = NULL;
+ *blk_offset = 0;
+
+ return true;
+}
+
+void ce_uninit (void)
+{
+ ce_store_rx_params_t *tmp;
+
+ blk_t *curr;
+ while (ce_ctx.measurement_head)
+ {
+ curr = ce_ctx.measurement_head;
+ ce_ctx.measurement_head = ce_ctx.measurement_head->next;
+
+ blk_release_desc (curr);
+ }
+
+ while (ce_ctx.rx_params_head)
+ {
+ tmp = ce_ctx.rx_params_head;
+ ce_ctx.rx_params_head = ce_ctx.rx_params_head->next;
+ blk_release (tmp->rx_params);
+ blk_release (tmp);
+ }
+}
diff --git a/cesar/mac/sar/test/src/reassembly_unit_test_functions.c b/cesar/mac/sar/test/src/reassembly_unit_test_functions.c
new file mode 100644
index 0000000000..7447338f04
--- /dev/null
+++ b/cesar/mac/sar/test/src/reassembly_unit_test_functions.c
@@ -0,0 +1,304 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_unit_test_functions.c
+ * \brief test to verify the mfs processing function
+ * \ingroup mac/sar/src
+ *
+ */
+#include <stdio.h>
+
+#include "common/std.h"
+#include "lib/bitstream.h"
+#include "lib/read_word.h"
+
+#include "mac/sar/inc/sar_mf.h"
+#include "mac/pbproc/pbproc.h"
+
+void test_sar_rx_noise_cb (void *user, const pbproc_rx_params_t *rx_params,
+ phy_chandata_t *first, uint nb_chandata)
+{
+
+}
+
+static void
+write_mfh (u8 *addr, uint length, uint type, uint ats)
+{
+ bitstream_t bitstream;
+
+ dbg_assert (addr);
+
+ if (type > 1)
+ {
+ length += SAR_MF_ATS_SIZE - 1;
+
+ bitstream_init (&bitstream, addr, 6, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &type, 2);
+ bitstream_access (&bitstream, &length, 14);
+ bitstream_access (&bitstream, &ats, 32);
+ }
+ else
+ {
+ length -= 1;
+
+ bitstream_init (&bitstream, addr, 2, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &type, 2);
+ bitstream_access (&bitstream, &length, 14);
+ }
+
+ bitstream_finalise (&bitstream);
+}
+
+/**
+ * Initialize the Reassembly test generating a list of PBs.
+ */
+void sar_unit_test_generate_pb_list (pb_t **first, pb_t **last)
+{
+ pb_t *pb_list[14];
+ pb_t *pb;
+
+ uint length;
+ uint ats;
+ uint type;
+
+ uint i;
+
+ *first = (pb_t *) blk_alloc_desc_range (14, (blk_t **) last);
+ (*last)->next = NULL;
+
+ for (i = 0, pb = *first; pb; i++, pb = pb->next)
+ {
+ pb_list[i] = pb;
+ pb_list[i]->expiration_ntb = 100;
+ pb_list[i]->header.ssn = i;
+ pb_list[i]->header.vpbf = true;
+ pb_list[i]->header.mmqf = false;
+ pb_list[i]->header.opsf = false;
+ }
+
+ // fill the first pb
+ pb_list[0]->header.mfbf = true;
+ pb_list[0]->header.mfbo = 0;
+
+ pb_list[1]->header.mfbf = true;
+ pb_list[1]->header.mfbo = 12;
+
+ pb_list[3]->header.mfbf = true;
+ pb_list[3]->header.mfbo = 219;
+
+ pb_list[4]->header.mfbf = true;
+ pb_list[4]->header.mfbo = 103;
+
+ pb_list[5]->header.mfbf = true;
+ pb_list[5]->header.mfbo = 66;
+
+ pb_list[8]->header.mfbf = true;
+ pb_list[8]->header.mfbo = 29;
+
+ pb_list[10]->header.mfbf = true;
+ pb_list[10]->header.mfbo = 431;
+
+ // MF of 283 bytes => 0x0452 (with type = 2 and ats in length)
+ length = 273;
+ type = 2;
+ write_mfh (pb_list[0]->data, length, type, 0);
+
+ // MF of 241 bytes => 0x398 + 2 = 0x3AA
+ length = 231;
+ ats = 0x1234;
+ write_mfh (pb_list[0]->data + 283, length, type, ats);
+
+ // MF of 1231 bytes => 0x1310 + type = 0x1312
+ length = 1221;
+ ats = 0x1234;
+ write_mfh (pb_list[1]->data + 12, length, type, ats);
+
+ // MF of 169 bytes => 0x278 + type = 0x27A
+ length = 159;
+ ats = 0x1234;
+ write_mfh (pb_list[3]->data + 219, length, type, ats);
+
+ // MF of 227 bytes => 0x360 + type = 0x362
+ length = 217;
+ ats = 0x1234;
+ write_mfh (pb_list[3]->data + 388, length, type, ats);
+
+ // MF of 393 bytes => 0x5f8 + type = 0x5FA
+ length = 383;
+ ats = 0x1234;
+ write_mfh (pb_list[4]->data + 103, length, type, ats);
+
+ // MF of 82 bytes => 0x11C + type = 0x11E
+ length = 72;
+ ats = 0x1234;
+ write_mfh (pb_list[4]->data + 496, length, type, ats);
+
+ // MF of 1499 bytes => 0x1740 + type = 0x1742
+ length = 1489;
+ ats = 0x1234;
+ write_mfh (pb_list[5]->data + 66, length, type, ats);
+
+ // MF of 240 bytes => 0x394 + type = 0x396
+ length = 230;
+ ats = 0x1234;
+ write_mfh (pb_list[8]->data + 29, length, type, ats);
+
+ // MF of 1186 bytes => 0x125C + type = 0x125E
+ length = 1176;
+ ats = 0x1234;
+ write_mfh (pb_list[8]->data + 269, length, type, ats);
+
+ // MF of 185 bytes => 0x2B8 + type = 0x2BA
+ length = 175;
+ ats = 0x1234;
+ write_mfh (pb_list[10]->data + 431, length, type, ats);
+
+ // Repeat the PB with the ssn = 1.
+ memcpy (&pb_list[12]->header, &pb_list[1]->header, 4);
+ memcpy (pb_list[12]->data, pb_list[1]->data, 512);
+
+ memcpy (&pb_list[13]->header, &pb_list[10]->header, 4);
+ memcpy (pb_list[13]->data, pb_list[10]->data, 512);
+
+ *first = pb_list[6];
+ pb_list[6]->next= pb_list[2];
+ pb_list[2]->next= pb_list[0];
+ pb_list[0]->next= pb_list[1];
+ pb_list[1]->next= pb_list[12];
+ pb_list[12]->next= pb_list[4];
+ pb_list[4]->next= pb_list[10];
+ pb_list[10]->next= pb_list[13];
+ pb_list[13]->next= pb_list[5];
+ pb_list[5]->next= pb_list[9];
+ pb_list[9]->next= pb_list[8];
+ pb_list[8]->next= pb_list[3];
+ pb_list[3]->next= pb_list[7];
+ pb_list[7]->next = pb_list[11];
+ pb_list[11]->next = NULL;
+ *last = pb_list[11];
+}
+
+/**
+ * Initialize the Reassembly test generating a list of PBs.
+ */
+void sar_unit_test_generate_mme_pb_list (pb_t **first, pb_t **last)
+{
+ pb_t *pb_list[12];
+ pb_t *pb;
+
+ uint length;
+ uint ats;
+ uint type;
+ uint i;
+
+ *first = (pb_t *) blk_alloc_desc_range (12, (blk_t **) last);
+ (*last)->next = NULL;
+
+ for (i = 0, pb = *first; pb; i++, pb = pb->next)
+ {
+ pb_list[i] = pb;
+ pb_list[i]->expiration_ntb = 100;
+ pb_list[i]->header.ssn = i;
+ pb_list[i]->header.vpbf = true;
+ pb_list[i]->header.mmqf = true;
+ pb_list[i]->header.opsf = false;
+ }
+
+ // fill the first pb
+ pb_list[0]->header.mfbf = true;
+ pb_list[0]->header.mfbo = 0;
+
+ pb_list[1]->header.mfbf = true;
+ pb_list[1]->header.mfbo = 12;
+
+ pb_list[3]->header.mfbf = true;
+ pb_list[3]->header.mfbo = 219;
+
+ pb_list[4]->header.mfbf = true;
+ pb_list[4]->header.mfbo = 103;
+
+ pb_list[5]->header.mfbf = true;
+ pb_list[5]->header.mfbo = 66;
+
+ pb_list[8]->header.mfbf = true;
+ pb_list[8]->header.mfbo = 29;
+
+ pb_list[10]->header.mfbf = true;
+ pb_list[10]->header.mfbo = 431;
+
+ // MF of 283 bytes => 0x0452 (with type = 2 and ats in length)
+ length = 273;
+ type = 3;
+ write_mfh (pb_list[0]->data, length, type, 0);
+
+ // MF of 241 bytes => 0x398 + 2 = 0x3AA
+ length = 231;
+ ats = 0x1234;
+ write_mfh (pb_list[0]->data + 283, length, type, ats);
+
+ // MF of 1231 bytes => 0x1310 + type = 0x1312
+ length = 1221;
+ ats = 0x1234;
+ write_mfh (pb_list[1]->data + 12, length, type, ats);
+
+ // MF of 169 bytes => 0x278 + type = 0x27A
+ length = 159;
+ ats = 0x1234;
+ write_mfh (pb_list[3]->data + 219, length, type, ats);
+
+ // MF of 227 bytes => 0x360 + type = 0x362
+ length = 217;
+ ats = 0x1234;
+ write_mfh (pb_list[3]->data + 388, length, type, ats);
+
+ // MF of 393 bytes => 0x5f8 + type = 0x5FA
+ length = 383;
+ ats = 0x1234;
+ write_mfh (pb_list[4]->data + 103, length, type, ats);
+
+ // MF of 82 bytes => 0x11C + type = 0x11E
+ length = 72;
+ ats = 0x1234;
+ write_mfh (pb_list[4]->data + 496, length, type, ats);
+
+ // MF of 1499 bytes => 0x1740 + type = 0x1742
+ length = 1489;
+ ats = 0x1234;
+ write_mfh (pb_list[5]->data + 66, length, type, ats);
+
+ // MF of 240 bytes => 0x394 + type = 0x396
+ length = 230;
+ ats = 0x1234;
+ write_mfh (pb_list[8]->data + 29, length, type, ats);
+
+ // MF of 1186 bytes => 0x125C + type = 0x125E
+ length = 1176;
+ ats = 0x1234;
+ write_mfh (pb_list[8]->data + 269, length, type, ats);
+
+ // MF of 185 bytes => 0x2B8 + type = 0x2BA
+ length = 175;
+ ats = 0x1234;
+ write_mfh (pb_list[10]->data + 431, length, type, ats);
+
+ *first = pb_list[0];
+ pb_list[0]->next= pb_list[6];
+ pb_list[6]->next= pb_list[2];
+ pb_list[2]->next= pb_list[1];
+ pb_list[1]->next= pb_list[4];
+ pb_list[4]->next= pb_list[10];
+ pb_list[10]->next= pb_list[5];
+ pb_list[5]->next= pb_list[9];
+ pb_list[9]->next= pb_list[8];
+ pb_list[8]->next= pb_list[3];
+ pb_list[3]->next= pb_list[7];
+ pb_list[7]->next = pb_list[11];
+ pb_list[11]->next = NULL;
+ *last = pb_list[11];
+}
+
diff --git a/cesar/mac/sar/test/src/sar_unit_test_functions.c b/cesar/mac/sar/test/src/sar_unit_test_functions.c
new file mode 100644
index 0000000000..085c267cec
--- /dev/null
+++ b/cesar/mac/sar/test/src/sar_unit_test_functions.c
@@ -0,0 +1,100 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_unit_test_functions.c
+ * \brief function for the unit tests.
+ * \ingroup mac/sar/src
+ *
+ */
+#include "common/std.h"
+#include "mac/sar/test/inc/sar_unit_test_functions.h"
+
+/** TODO REMOVE THIS FUNCTIONS **/
+
+static sar_pbproc_t pbproc_global;
+
+/**
+ * Initialise pbproc and return its context.
+ * \param config global mac configuration
+ * \param store MFS and STA store
+ * \param user_data user data passed to any callback
+ * \param rx_cb MPDU RX callback
+ * \return pbproc context
+ */
+pbproc_t *
+pbproc_init (mac_config_t *config, mac_store_t *store)
+{
+ pbproc_global.cpt_expiration = 0;
+ return (pbproc_t *) &pbproc_global;
+}
+
+void
+pbproc_init_cb (pbproc_t *ctx, void *user_data, pbproc_rx_cb_t rx_cb,
+ pbproc_rx_beacon_cb_t rx_beacon_cb)
+{
+
+}
+
+void
+pbproc_uninit(pbproc_t *ctx)
+{
+
+}
+
+/**
+ * Give segments back to pbproc for reception.
+ * \param ctx pbproc context
+ * \param first first segment
+ * \param last last segment
+ * \param nb number of segment
+ */
+void pbproc_rx_segment_refill (pbproc_t *ctx, pb_t *first, pb_t *last, uint nb)
+{
+ pb_t *pb_curr;
+ while (first != last)
+ {
+ pb_curr = first;
+ first = first->next;
+ blk_release_desc ((blk_t *)pb_curr);
+ }
+
+ blk_release_desc ((blk_t *) first);
+}
+
+
+/**
+* Unregister an MFS from the Channel Access, so that it can no longer be
+* sent.
+* \param ctx ca context
+* \param mfs the MFS to remove
+* \return true if successful
+*
+* If unsuccessful, the caller should try later because the MFS is currently
+* been used for a transmission.
+*/
+bool
+ca_mfs_remove (ca_t *ctx, mfs_tx_t *mfs)
+{
+ return true;
+}
+
+/**
+* Register an MFS with the Channel Access, so it can be sent.
+* \param ctx ca context
+* \param mfs the MFS to add
+*/
+void
+ca_mfs_add (ca_t *ctx, mfs_tx_t *mfs)
+{
+}
+
+void
+ca_mfs_update (ca_t *ctx, mfs_tx_t *mfs)
+{
+
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/Makefile b/cesar/mac/sar/test/unit_test/ecos/Makefile
new file mode 100644
index 0000000000..6f30a011ef
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/Makefile
@@ -0,0 +1,75 @@
+BASE = ../../../../../
+
+ECOS = y
+
+DEFS = -DSAR_UNIT_TEST=1
+
+TARGET_PROGRAMS = reassembly_complete rea_cov_test \
+ reassembly_create_mfs lib_sar_mfs reassembly_measurement \
+ reassembly_mfs_update_expiration_date sar_call_back_ul \
+ lib_sar_expiration \
+ sar_mfs_resising segmentation_complete test_store_memory test_crc_error \
+ msdu-timeout beacon_path test-seg-provide-pb
+
+test_store_memory_SOURCES = test_store_memory.c
+test_store_memory_MODULES = lib mac/common mac/sar/bridgedma
+
+reassembly_complete_SOURCES = reassembly_complete.c
+reassembly_complete_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/pbproc mac/sar/test/
+
+rea_cov_test_SOURCES = reassembly_two_jobs.c
+rea_cov_test_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/pbproc mac/sar/test/
+
+reassembly_create_mfs_SOURCES = reassembly_create_mfs.c
+reassembly_create_mfs_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/pbproc mac/sar/test
+
+lib_sar_mfs_SOURCES = lib_sar_mfs.c
+lib_sar_mfs_MODULES = lib mac/sar mac/pbproc mac/common mac/sar/test \
+ mac/sar/bridgedma
+
+reassembly_measurement_SOURCES = reassembly_measurement.c
+reassembly_measurement_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/sar/test mac/pbproc
+
+reassembly_mfs_update_expiration_date_SOURCES = reassembly_mfs_update_expiration_date.c
+reassembly_mfs_update_expiration_date_MODULES = lib mac/sar mac/common \
+ mac/sar/bridgedma mac/sar/test mac/pbproc
+
+sar_call_back_ul_SOURCES = sar_call_back_ul.c
+sar_call_back_ul_MODULES = lib mac/common mac/sar mac/sar/bridgedma \
+ mac/pbproc mac/sar/test
+
+msdu-timeout_SOURCES = msdu-timeout.c
+msdu-timeout_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/pbproc mac/sar/test
+
+lib_sar_expiration_SOURCES = lib_sar_expiration.c
+lib_sar_expiration_MODULES = lib mac/sar mac/common mac/pbproc \
+ mac/sar/bridgedma mac/sar/test
+
+sar_mfs_resising_SOURCES = sar_mfs_resising.c
+sar_mfs_resising_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/sar/test mac/pbproc
+
+segmentation_complete_SOURCES = segmentation_complete.c
+segmentation_complete_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/pbproc mac/sar/test
+
+test_crc_error_SOURCES = crc_error.c
+test_crc_error_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/pbproc mac/sar/test
+
+beacon_path_SOURCES = beacon.c
+beacon_path_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/sar/test
+
+test-seg-provide-pb_SOURCES = test-segmentation-provide-pb.c
+test-seg-provide-pb_MODULES = lib mac/sar mac/common mac/sar/bridgedma \
+ mac/sar/test mac/pbproc
+
+mac_pbproc_MODULE_SOURCES = mfs.c
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/mac/sar/test/unit_test/ecos/ecos.ecc.sh b/cesar/mac/sar/test/unit_test/ecos/ecos.ecc.sh
new file mode 100644
index 0000000000..8253d98c9a
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/ecos.ecc.sh
@@ -0,0 +1,5 @@
+config=${1:-ecos-gen.ecc}
+ecosconfig --config=$config new linux default
+cat >> $config <<EOF
+EOF
+ecosconfig --config=$config check
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/beacon.c b/cesar/mac/sar/test/unit_test/ecos/src/beacon.c
new file mode 100644
index 0000000000..bf4fb4895f
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/beacon.c
@@ -0,0 +1,78 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/test/unit_test/ecos/src/beacon.c
+ * \brief Send beacon.
+ * \ingroup sar
+ *
+ * Coverage use only, the function tested is only a path to the mac layer, the
+ * sar only provide the beacon to the pbproc and does nothing with it.
+ */
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+
+#include "lib/test.h"
+
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/sar_context.h"
+
+int
+main (void)
+{
+ test_t test;
+ sar_t *sar;
+ pb_beacon_t *beacon;
+ mfs_tx_t *mfs;
+
+ test_init (test, 0, NULL);
+
+ sar = blk_alloc ();
+ sar->pbproc_ctx = blk_alloc ();
+ beacon = blk_alloc ();
+ mfs = blk_alloc ();
+
+ mfs->beacon = true;
+ mfs->head = NULL;
+ mfs->tail = NULL;
+ sar_beacon_send (sar, beacon, mfs, sar);
+
+ blk_release (sar->pbproc_ctx);
+ blk_release (sar);
+ blk_release (beacon);
+ blk_release (mfs);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
+void
+pbproc_mfs_provide (mfs_tx_t *mfs, uint nb) {return;}
+
+pb_t *
+pbproc_mfs_extract_tail (mfs_tx_t *mfs) {return NULL;}
+
+void
+pbproc_mfs_insert (mfs_tx_t *mfs, pb_t *first, pb_t *last, uint nb, uint cap) {return;}
+
+void
+pbproc_mfs_beacon_prepare (pbproc_t *ctx, mfs_tx_t *mfs, pb_beacon_t *pb,
+ const pbproc_tx_beacon_params_t *params)
+{
+ return;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/crc_error.c b/cesar/mac/sar/test/unit_test/ecos/src/crc_error.c
new file mode 100644
index 0000000000..0c6173a9eb
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/crc_error.c
@@ -0,0 +1,148 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/test/unit_test/ecos/src/crc_error.c
+ * \brief test of the reassembly part
+ * \ingroup mac_sar
+ *
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+
+#include "lib/test.h"
+#include "lib/trace.h"
+
+#include "mac/common/store.h"
+#include "mac/common/ntb.h"
+
+#include "hal/phy/phy.h"
+
+
+#include "mac/sar/sar.h"
+
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+#include "mac/sar/test/inc/ce.h"
+#include "mac/sar/inc/sar_job_mfs.h"
+#include "mac/sar/inc/bridge_dma.h"
+#include "mac/sar/inc/sar_context.h"
+#include "mac/sar/inc/sar.h"
+
+uint cpt;
+test_t test;
+mac_store_t *mac_store;
+sar_t *sar_ctx;
+pbproc_t *pbproc;
+mac_config_t *mac_config;
+ca_t *ca;
+phy_t *phy;
+
+bool bool_test;
+
+void rea_comp_sar_rea_done_with_one_pb (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs)
+{
+ cpt ++;
+}
+
+void rea_comp_sar_rea_done (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs, bool encrypted)
+{
+ if (length != list[cpt] - 10)
+ bool_test = true;
+ cpt ++;
+}
+
+void this_test_init (void)
+{
+ mac_config = blk_alloc ();
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ mac_store = mac_store_init ();
+ pbproc = pbproc_init (mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ bool_test = false;
+ cpt = 0;
+
+ /* Data */
+ mac_store = mac_store_init ();
+ sar_init_data_context (sar_ctx, sar_ctx);
+ sar_init_mme_context (sar_ctx, sar_ctx);
+ sar_init_reassembly_data_cb (sar_ctx, rea_comp_sar_rea_done);
+ sar_init_reassembly_mme_cb (sar_ctx, rea_comp_sar_rea_done);
+ sar_init_measure_context (sar_ctx, sar_ctx);
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ mac_store_sta_add (mac_store, 0x1);
+}
+
+void this_test_uninit (void)
+{
+ sar_uninit (sar_ctx);
+ pbproc_uninit (pbproc);
+ blk_release (mac_config);
+ dbg_check (mac_store_sta_remove (mac_store, 0x1));
+ mac_store_uninit (mac_store);
+ mac_ntb_uninit();
+ blk_release (ca);
+ blk_release (phy);
+}
+
+int main (void)
+{
+ pb_t *pb;
+ sar_job_mfs_t *job;
+ mfs_rx_t *mfs;
+ trace_init ();
+ test_init (test, 0, NULL);
+
+ this_test_init ();
+
+ // Create the job with the PB and the mfs
+ mfs = blk_alloc ();
+ job = blk_alloc ();
+ pb = (pb_t *) blk_alloc_desc ();
+
+ mfs->head = pb;
+ mfs->tail = pb;
+ mfs->common.tx = false;
+ mfs->common.mme = false;
+
+
+ // fill the job.
+ job->job.first_pb_desc = (blk_t *)pb;
+ job->job.crc_error = true;
+ job->mfs = (mfs_t *)mfs;
+ job->job.direction = true;
+ job->pb_quantity = 1;
+
+ // fill the bridgedma list.
+ bridge_dma_add_jobs (&sar_ctx->bridge_dma_jobs, job, job);
+ bridge_dma_free_head (sar_ctx);
+
+ // Process the work -> the buffer use in the job.
+ sar_launch (sar_ctx);
+
+ this_test_uninit ();
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/lib_sar_expiration.c b/cesar/mac/sar/test/unit_test/ecos/src/lib_sar_expiration.c
new file mode 100644
index 0000000000..1ddfc01f74
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/lib_sar_expiration.c
@@ -0,0 +1,644 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib_sar_expiration.c
+ * \brief test the expiration for the SAR
+ * \ingroup mac/sar/
+ *
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+#include <stdio.h>
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/bitstream.h"
+
+#include "mac/common/config.h"
+#include "mac/common/ntb.h"
+#include "mac/ca/ca.h"
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/sar_expiration.h"
+#include "mac/sar/inc/sar_context.h"
+
+
+bool ce_tested;
+
+
+bool ce_measurement (void *user,
+ pbproc_rx_params_t *rx_params, uint pb_nb, blk_t **first,
+ blk_t **last, pb_t *chan_data_first, uint nb_chandata, uint
+ *blk_offset)
+{
+ ce_tested = true;
+ return false;
+}
+
+/**
+ * Get the first work to do by the SAR
+ * Just here cause of the linker.
+ *
+ * \param ctx the sar context.
+ * \return the work message
+ */
+sar_work_message_t* sar_work_get (sar_t *ctx);
+
+/**
+ * Launch the reassembly process to realize reassembly a new mpdu.
+ *
+ * \param ctx the sar context
+ * \param rx the rx data to process
+ */
+void reassembly_run (sar_t *ctx, sar_mpdu_t *rx);
+
+/**
+ * Test the expiration of an entire mpdu.
+ *
+ * \param sar the sar context.
+ */
+void
+this_test_mpdu_expired (sar_t *sar);
+
+
+/**
+ * Launch the expiration process on a mfs in the release state with one pb
+ *
+ * \param exp the expiration ctx
+ * \param tx the kind of mfs
+ */
+void expire_released_mfs (sar_expiration_t exp, bool tx);
+
+/* The call back function used by the SAR when a mfs rx expired and it not a
+ * plid one */
+void mfs_expired (void *user, mfs_t *mfs);
+
+/**
+ * Test the pb expiration process in the MFS
+ * \param exp the expirtion ctx.
+ * \param test the test counter
+ */
+void expire_pbs_first (sar_expiration_t exp, test_t test);
+
+/**
+ * Add some MFS to the expiration mechanism
+ *
+ * \param exp the expiration context
+ * \param test the test context.
+ */
+void expire_mfs (sar_expiration_t exp, test_t test);
+
+/**
+ * Create a MFS which will expire soon and try to get a work message from the
+ * sar mailbox.
+ *
+ * \param sar sar context.
+ */
+void
+sar_mailbox_timeout (sar_t *sar);
+
+test_t test;
+
+int main (void)
+{
+ bool added;
+ mfs_t *mfs;
+ mac_store_t *mac_store;
+ ca_t *ca;
+ sar_t *sar;
+
+ test_init (test, 0, NULL);
+
+ /* Init the mac store */
+ mac_store = mac_store_init ();
+ ca = blk_alloc ();
+ sar = blk_alloc ();
+
+ /* initialize the expiration mechanism */
+ sar_expiration_init (&sar->expiration, ca);
+ sar->expiration.mfs_store = mac_store;
+ sar->expiration.mfs_expiration_cb = mfs_expired;
+
+ /* Launch a first expieration process on no MFS */
+ sar_expiration_mfs (&sar->expiration, 0);
+
+ /* cover the first two condition of the sar_expiration_mfs */
+ expire_released_mfs (sar->expiration, true);
+ expire_released_mfs (sar->expiration, false);
+
+ /* try to expire the pbs first */
+ expire_pbs_first (sar->expiration, test);
+
+ /* try to expire the MFS */
+ expire_mfs (sar->expiration, test);
+
+ /* remove a mfs from the sar expiration */
+ mfs = mac_store_mfs_add (sar->expiration.mfs_store, true, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ sar_expiration_mfs_add (&sar->expiration, mfs);
+ mfs->tx.head = (pb_t *) blk_alloc_desc ();
+ mfs->tx.head->next = NULL;
+ sar_expiration_mfs_remove (&sar->expiration, mfs);
+ sar_expiration_mfs (&sar->expiration, -1);
+
+ blk_release (mfs);
+
+ mfs
+ = mac_store_mfs_add (sar->expiration.mfs_store, false, false, false, 1, 1,
+ &added);
+ dbg_assert (added);
+
+ sar_expiration_mfs_add (&sar->expiration, mfs);
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->next = NULL;
+ sar_expiration_mfs_remove (&sar->expiration, mfs);
+
+ blk_release (mfs);
+
+ /* a mme rx mfs */
+ mfs = mac_store_mfs_add (sar->expiration.mfs_store, false, false, true, MAC_LID_NONE,
+ 1, &added);
+ dbg_assert (added);
+
+ mfs->common.expiration_ntb = 50;
+ mfs->common.expiration_delay_ntb = 30;
+ sar_expiration_mfs_add (&sar->expiration, mfs);
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->expiration_ntb = 70;
+ mfs->rx.head->next = NULL;
+ sar_expiration_mfs (&sar->expiration, 100);
+ sar_expiration_mfs (&sar->expiration, 10000);
+
+ blk_release (mfs);
+
+ /* Uninit the expiration */
+ sar_expiration_uninit (&sar->expiration);
+
+ /* Test the time out of the sar mailbox. */
+ sar_expiration_init (&sar->expiration, ca);
+ sar->expiration.mfs_store = mac_store;
+ sar->expiration.mfs_expiration_cb = mfs_expired;
+
+ sar_mailbox_timeout (sar);
+ dbg_check (mac_store_sta_remove (mac_store, 1));
+
+ /* Test the expiration of an MPDU. */
+ this_test_mpdu_expired (sar);
+
+ mac_store_uninit (mac_store);
+ blk_release (ca);
+ blk_release (sar);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
+/**
+ * Launch the expiration process on a mfs in the release state with one pb
+ *
+ * \param exp the expiration ctx
+ * \param tx the kind of mfs
+ */
+void expire_released_mfs (sar_expiration_t exp, bool tx)
+{
+ mfs_t *mfs;
+ bool added;
+
+ /* add a mfs tx to the store */
+ mfs = mac_store_mfs_add (exp.mfs_store, tx, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ mfs->common.release = true;
+ mfs->common.expiration_ntb = 0;
+ mfs->common.expiration_delay_ntb = 0;
+
+ if (tx)
+ {
+ mfs->tx.head = (pb_t *) blk_alloc_desc ();
+ mfs->tx.head->next = NULL;
+ }
+ else
+ {
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->next = NULL;
+ }
+
+
+ /* add the mfs to the sar expiration mechanism */
+ sar_expiration_mfs_add (&exp, mfs);
+
+ /* remove the reference on the mfs provided on the mac_mfs_add. */
+ blk_release (mfs);
+
+ sar_expiration_mfs (&exp, -1);
+
+ mfs = mac_store_mfs_get (exp.mfs_store, tx, false, false, 1, 1);
+
+ test_case_begin (test, "MFS in release state");
+ test_begin (test, "MFS")
+ {
+ test_fail_if (mfs != NULL, "MFS shall not exist.");
+ }
+ test_end;
+}
+
+/* The call back function used by the SAR when a mfs rx expired and it not a
+ * plid one */
+void mfs_expired (void *user, mfs_t *mfs)
+{
+
+}
+
+/**
+ * Test the pb expiration process in the MFS
+ * \param exp the expirtion ctx.
+ */
+void expire_pbs_first (sar_expiration_t exp, test_t test)
+{
+ bitstream_t bitstream;
+ mfs_tx_t *mfs_tx;
+ mfs_tx_t *mfs_tx_tmp;
+ mfs_rx_t *mfs_rx;
+ bool added;
+
+ uint mft;
+ uint length;
+ uint ats;
+
+ /* TX only */
+ mfs_tx = mac_store_mfs_add_tx (exp.mfs_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ mfs_tx->common.expiration_ntb = 1000;
+ mfs_tx->common.expiration_delay_ntb = 1000;
+
+ mfs_tx->head = (pb_t *) blk_alloc_desc ();
+ mfs_tx->head->next = NULL;
+ mfs_tx->head->expiration_ntb = 0;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs_tx);
+
+ sar_expiration_mfs (&exp, -1);
+
+ test_begin (test, "no pb in MFS")
+ {
+ test_fail_if (mfs_tx->head != NULL, "the mfs should not have any PB");
+ }
+ test_end;
+
+ /* go to a release state */
+ sar_expiration_mfs_remove (&exp, (mfs_t *) mfs_tx);
+
+ test_begin (test, "MFS in a release state")
+ {
+ test_fail_if (mfs_tx->common.release != true, "MFS not in a release state");
+ }
+ test_end;
+
+ /* delete the MFS */
+ sar_expiration_mfs_destroy (&exp, (mfs_t *) mfs_tx);
+ mfs_tx_tmp = mac_store_mfs_get_tx (exp.mfs_store, false, false, 1, 1);
+
+ test_begin (test, "MFs in the store after destroy")
+ {
+ test_fail_if (mfs_tx_tmp != NULL, "Should not exit");
+ }
+ test_end;
+
+ /* remove the reference provided to this function on the mfs creation. */
+ blk_release (mfs_tx);
+
+ /* RX ATS type MFS */
+ mfs_rx = mac_store_mfs_add_rx (exp.mfs_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ mfs_rx->common.expiration_ntb = 28000000;
+ mfs_rx->common.expiration_delay_ntb = 1000;
+ mfs_rx->common.ats = true;
+
+ /* The first PB has a mfbf at offset 0 and an ats */
+ mfs_rx->head = (pb_t *) blk_alloc_desc ();
+ mfs_rx->head->header.ssn = 0;
+ mfs_rx->head->header.mfbf = true;
+ mfs_rx->head->header.mfbo = 0;
+
+ mft = 2;
+ length = 106;
+ ats = 10;
+
+ bitstream_init (&bitstream, mfs_rx->head->data, 6, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &mft, 2);
+ bitstream_access (&bitstream, &length, 14);
+ bitstream_access (&bitstream, &ats, 32);
+ bitstream_finalise (&bitstream);
+
+ mfs_rx->head->expiration_ntb = 20;
+
+ mfs_rx->head->next = (pb_t *) blk_alloc_desc ();
+ mfs_rx->head->next->header.mfbf = false;
+ mfs_rx->head->next->expiration_ntb = 22;
+
+ mfs_rx->head->next->next = (pb_t *) blk_alloc_desc ();
+ mfs_rx->head->next->next->next = NULL;
+ mfs_rx->head->next->next->header.mfbf = false;
+ mfs_rx->head->next->next->expiration_ntb = 200;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs_rx);
+ sar_expiration_mfs (&exp, 27000000);
+
+ test_begin (test, "Expiration of all the PBs")
+ {
+ test_fail_if (mfs_rx->head != NULL, "MFS shall not contain PBs");
+ }
+ test_end;
+
+ sar_expiration_mfs_destroy (&exp, (mfs_t *) mfs_rx);
+
+ /* release the reference on the mfs */
+ blk_release (mfs_rx);
+
+ /* With a not ATS MFS kind */
+ mfs_rx = mac_store_mfs_add_rx (exp.mfs_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ mfs_rx->common.expiration_ntb = 28000000;
+ mfs_rx->common.expiration_delay_ntb = 1000;
+ mfs_rx->common.ats = false;
+
+ mfs_rx->head = (pb_t *) blk_alloc_desc ();
+ mfs_rx->head->next = NULL;
+
+ mfs_rx->head->expiration_ntb = 0;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs_rx);
+ sar_expiration_mfs (&exp, 27000000);
+
+ test_begin (test, "Expiration of PBs in non ATS MFS")
+ {
+ test_fail_if (mfs_rx->head != NULL, "MFS shall not contain any PB");
+ }
+ test_end;
+
+ sar_expiration_mfs_destroy (&exp, (mfs_t *) mfs_rx);
+
+ /* release the reference on the mfs */
+ blk_release (mfs_rx);
+}
+
+/**
+ * Add some MFS to the expiration mechanism
+ *
+ * \param exp the expiration context
+ * \param test the test context.
+ */
+void expire_mfs (sar_expiration_t exp, test_t test)
+{
+ u8 i;
+ bool added;
+ bool tx;
+ mfs_t *mfs [8];
+
+ for (i = 0, tx = false; i < 6; i++, tx = !tx)
+ {
+ mfs[i] = mac_store_mfs_add (exp.mfs_store, tx, false, false, i, 1,
+ &added);
+ dbg_assert (added);
+ }
+
+ /* The last one in the tx is a mme mfs */
+ mfs[6] = (mfs_t *) mac_store_mfs_add_rx (exp.mfs_store, false, true,
+ MAC_LID_NONE, 1, &added);
+ dbg_assert (added);
+
+ /* The last one in the tx is a mme mfs */
+ mfs[7] = (mfs_t *) mac_store_mfs_add_tx (exp.mfs_store, false, true,
+ MAC_LID_NONE, 1, &added);
+ dbg_assert (added);
+
+ /**
+ * The ODD ones are the tx MFS
+ * and the even are the rx MFS.
+ */
+
+ /* Add this MFSs to the sar expiration mechanism in a random way */
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[2]);
+ mfs[2]->common.expiration_ntb = 20;
+ mfs[2]->common.expiration_delay_ntb = 20;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[5]);
+ mfs[5]->common.expiration_ntb = 30;
+ mfs[5]->common.expiration_delay_ntb = 30;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[3]);
+ mfs[3]->common.expiration_ntb = 50;
+ mfs[3]->common.expiration_delay_ntb = 50;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[1]);
+ mfs[1]->common.expiration_ntb = 60;
+ mfs[1]->common.expiration_delay_ntb = 60;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[0]);
+ mfs[0]->common.expiration_ntb = 70;
+ mfs[0]->common.expiration_delay_ntb = 70;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[7]);
+ mfs[7]->common.expiration_ntb = 80;
+ mfs[7]->common.expiration_delay_ntb = 80;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[6]);
+ mfs[6]->common.expiration_ntb = 90;
+ mfs[6]->common.expiration_delay_ntb = 90;
+
+ sar_expiration_mfs_add (&exp, (mfs_t *) mfs[4]);
+ mfs[4]->common.expiration_ntb = 100;
+ mfs[4]->common.expiration_delay_ntb = 0;
+
+ /* Add the pbs to test the coverage of the test */
+ pb_t *pb;
+ for (tx = false, i = 0; i < 8; i++, tx = !tx)
+ {
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->next = NULL;
+ pb->expiration_ntb = 500;
+
+ if (tx)
+ {
+ mfs[i]->tx.head = pb;
+ }
+ else
+ {
+ mfs[i]->rx.head = pb;
+ }
+ }
+
+ /* Do the expiration until the heap in the expiration mechanism is
+ * not empty */
+
+ u32 date;
+ for (date = 0; !heap_empty (&exp.mfs_expiration_heap) && date < 28000000; date
+ += 5)
+ {
+ sar_expiration_mfs (&exp, date);
+ }
+
+ sar_expiration_mfs_remove (&exp, (mfs_t *) mfs[4]);
+
+ for (i = 0; i < 8; i++)
+ {
+ blk_release (mfs[i]);
+ }
+}
+
+/**
+ * Create a MFS which will expire soon and try to get a work message from the
+ * sar mailbox.
+ *
+ * \param sar sar context.
+ */
+void
+sar_mailbox_timeout (sar_t *sar)
+{
+ mfs_t *mfs;
+ bool added;
+ uint delay_computed;
+
+ /* Initialise the mailbox. */
+ cyg_mbox_create (&sar->mailbox_handle, &sar->mailbox);
+
+ mfs = mac_store_mfs_add (sar->expiration.mfs_store, true, false, false, 1, 1,
+ &added);
+
+ sar_expiration_mfs_add (&sar->expiration, mfs);
+
+ mfs->tx.common.expiration_ntb = 1000;
+ mfs->tx.common.expiration_delay_ntb= 1;
+ mfs->tx.head = (pb_t *) blk_alloc_desc ();
+ mfs->tx.head->next = NULL;
+ mfs->tx.tail = mfs->tx.head;
+
+ mfs->tx.head->expiration_ntb = 2;
+
+ delay_computed = cyg_current_time();
+ sar_work_get (sar);
+ delay_computed = cyg_current_time () - delay_computed;
+
+ test_begin (test, "Delay before launching expiration")
+ {
+ test_fail_if (delay_computed < 5, "Error on mailbox timeout");
+ }
+ test_end;
+
+ mfs->tx.common.release = true;
+ sar_expiration_mfs_destroy (&sar->expiration, mfs);
+
+ blk_release (mfs);
+
+
+ /* The same with a rx mfs. */
+ mfs = mac_store_mfs_add (sar->expiration.mfs_store,false, false, false, 1, 1,
+ &added);
+
+ sar_expiration_mfs_add (&sar->expiration, mfs);
+
+ mfs->rx.common.expiration_ntb = 1000;
+ mfs->rx.common.expiration_delay_ntb= 1;
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->next = NULL;
+ mfs->rx.tail = mfs->rx.head;
+
+ mfs->rx.head->expiration_ntb = 2;
+
+ delay_computed = cyg_current_time();
+ sar_work_get (sar);
+ delay_computed = cyg_current_time () - delay_computed;
+
+ test_begin (test, "Delay before launching expiration")
+ {
+ test_fail_if (delay_computed < 5, "Error on mailbox timeout");
+ }
+ test_end;
+
+ mfs->rx.common.release = true;
+ sar_expiration_mfs_destroy (&sar->expiration, (mfs_t *) mfs);
+
+ blk_release (mfs);
+
+}
+
+/**
+ * Test the expiration of an entire mpdu.
+ *
+ * \param sar the sar context.
+ */
+void
+this_test_mpdu_expired (sar_t *sar)
+{
+ pb_t *pb;
+ uint phy;
+ mac_config_t mac_config;
+ sar_mpdu_t mpdu;
+
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->next = NULL;
+
+ phy = 28000000;
+ mac_ntb_init ((phy_t *) &phy, &mac_config);
+
+ /* Just use for the pb_pool_refill function, this pointer will not be
+ * modified. */
+ sar->pbproc_ctx = (pbproc_t *) sar;
+
+ mpdu.chandata = NULL;
+ mpdu.nb_chandata = 0;
+ mpdu.mfs = NULL;
+ mpdu.mme = NULL;
+ mpdu.head = pb;
+ mpdu.tail = pb;
+ mpdu.number = 1;
+ mpdu.expiration_ntb = 0;
+
+ reassembly_run (sar, &mpdu);
+
+ test_begin (test, "MPDU expired")
+ {
+ test_fail_if (mpdu.head != NULL, "PB should be released");
+ }
+ test_end;
+
+ mpdu.number = 0;
+ mpdu.chandata = (pb_t *) blk_alloc_desc ();
+ mpdu.chandata->next = NULL;
+ mpdu.nb_chandata = 1;
+
+ ce_tested = false;
+ sar_init_measure_context (sar, sar);
+ sar_init_measurement_cb (sar, ce_measurement );
+ reassembly_run (sar, &mpdu);
+
+ test_begin (test, "Chandata provided")
+ {
+ test_fail_if (ce_tested == false, "Chandata not provided to the CE");
+ }
+ test_end;
+
+ blk_release_desc ((blk_t *)mpdu.chandata);
+}
+
+u32
+phy_date (phy_t *phy)
+{
+ return *(u32*) phy;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/lib_sar_mfs.c b/cesar/mac/sar/test/unit_test/ecos/src/lib_sar_mfs.c
new file mode 100644
index 0000000000..59edf82aa7
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/lib_sar_mfs.c
@@ -0,0 +1,123 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib_sar_mfs.c
+ * \brief test the sar_mfs library for the SAR
+ * \ingroup mac/sar/
+ *
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "mac/sar/inc/sar_mfs.h"
+
+int
+cyg_user_start (void)
+{
+ test_t test;
+ pb_t *pb_head;
+ pb_t *pb_tail;
+ mfs_rx_t *mfs;
+
+ test_init (test, 0, NULL);
+
+ pb_head = (pb_t *) blk_alloc_desc_range (3, (blk_t **) &pb_tail);
+
+ dbg_assert (pb_head);
+ dbg_assert (pb_tail);
+ pb_tail->next = NULL;
+
+ pb_head->header.ssn = 0;
+ pb_head->header.vpbf = true;
+
+ pb_head->next->header.ssn = 1;
+ pb_head->next->header.vpbf = true;
+
+ pb_head->next->next->header.ssn = 3;
+ pb_head->next->next->header.vpbf = true;
+
+ mfs = blk_alloc ();
+ /* Verify the contiguousity of the MFS */
+ rx_mfs_update_last_contiguous_and_tail (mfs, mfs->head);
+
+ test_begin (test, "Test the contiguously of the MFS")
+ {
+ test_fail_if (mfs->head != NULL, "The first pb is wrong");
+ test_fail_if (mfs->tail != NULL, "The tail pb is wrong");
+ test_fail_if (mfs->last_contiguous != NULL, "The lc pb is wrong");
+ }
+ test_end;
+
+ mfs->head = pb_head;
+ mfs->tail = pb_tail;
+ mfs->last_contiguous = NULL;
+
+ /* Test the contiguously of the chain */
+ rx_mfs_update_last_contiguous_and_tail (mfs, mfs->head);
+
+ test_begin (test, "Test the contiguously of the chain")
+ {
+ test_fail_if (mfs->head->header.ssn != 0, "The first pb is wrong");
+ test_fail_if (mfs->tail->header.ssn != 3, "The tail pb is wrong");
+ test_fail_if (mfs->last_contiguous->header.ssn != 1, "The lc pb is wrong");
+ }
+ test_end;
+
+ /* Get the max of the windows size */
+ mfs->window_size = 18;
+ test_begin (test, "test max ssn ")
+ {
+ test_fail_if (rx_mfs_get_ssn_max(mfs) != 20, "the windows size is wrong");
+ }
+ test_end;
+
+ /* Test the window resize */
+ pb_head->header.ssn = 22;
+ pb_head->next->header.ssn = 23;
+ pb_head->next->next->header.ssn = 24;
+
+ mfs->common.bcast = true;
+
+ rx_mfs_resize_ssn (pb_head, mfs, 3);
+ test_begin (test, "test min ssn")
+ {
+ test_fail_if (mfs->ssn_min != 4, "the ssn min wrong");
+ }
+ test_end;
+
+ /* free two PBs for the last test. */
+ pb_head = pb_free (pb_head);
+ pb_head = pb_free (pb_head);
+ pb_head->header.opsf = true;
+ pb_head->header.ssn = 30;
+
+ mfs->head = pb_head;
+ mfs->tail = pb_head;
+
+ rx_mfs_resize_ssn (pb_head, mfs, 1);
+ test_begin (test, "test min ssn")
+ {
+ test_fail_if (mfs->ssn_min != 31, "the ssn min wrong");
+ }
+ test_end;
+
+ blk_release (mfs);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/msdu-timeout.c b/cesar/mac/sar/test/unit_test/ecos/src/msdu-timeout.c
new file mode 100644
index 0000000000..641071fb00
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/msdu-timeout.c
@@ -0,0 +1,108 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/sar/test/unit_test/ecos/src/msdu-timeout.c
+ * \brief Test the msdu expiration.
+ * \ingroup mac_sar
+ *
+ */
+#include "common/std.h"
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+
+#include "lib/test.h"
+#include "mac/sar/sar.h"
+#include "mac/common/ntb.h"
+
+#include "mac/sar/inc/sar_context.h"
+
+bool expired;
+
+bool tx_msdu_expiration (sar_t *ctx, sar_msdu_t * msdu);
+
+/**
+ * Segmentation process for the SAR module.
+ *
+ * \param ctx the sar context
+ * \param msdu the msdu to process
+ */
+void segmentation_run (sar_t *ctx, sar_msdu_t *msdu);
+
+void
+seg_done (void *user_data, u8 *buffer)
+{
+ expired = true;
+}
+
+int
+main (void)
+{
+ test_t test;
+ sar_t *sar;
+ mac_config_t mac_config;
+ sar_msdu_t msdu_exp;
+ sar_msdu_t msdu;
+
+ test_init (test, 0, NULL);
+ sar = blk_alloc ();
+
+ mac_ntb_init ((phy_t *)sar, &mac_config);
+ sar_init_segmentation_data_cb (sar, seg_done);
+ sar_init_segmentation_mme_cb (sar, seg_done);
+
+ msdu_exp.ats_confounder = 0;
+ msdu.ats_confounder = 26000000;
+ msdu.mfs = blk_alloc ();
+ msdu.mfs->common.mme = true;
+
+ msdu_exp.mfs = msdu.mfs;
+
+ expired = false;
+ segmentation_run (sar, &msdu_exp);
+
+ test_begin (test, "Expired")
+ {
+ test_fail_if (expired != true, "MSDU shall expire : Wrong expiration");
+ }
+ test_end;
+
+ expired = false;
+ msdu_exp.mfs->common.mme = false;
+ segmentation_run (sar, &msdu_exp);
+
+ test_begin (test, "Expired")
+ {
+ test_fail_if (expired != true, "MSDU shall expire : Wrong expiration");
+ }
+ test_end;
+
+
+ test_begin (test, "No Expiration")
+ {
+ test_fail_if (tx_msdu_expiration (sar, &msdu) != false, "MSDU shall not expire");
+ }
+ test_end;
+
+
+ blk_release (sar);
+ blk_release (msdu.mfs);
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+
+}
+
+u32
+phy_date (phy_t * phy)
+{
+ return 25000000;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/reassembly_complete.c b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_complete.c
new file mode 100644
index 0000000000..f3a3bc6bb2
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_complete.c
@@ -0,0 +1,430 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_complete.c
+ * \brief test of the reassembly part
+ * \ingroup mac/sar/test/reassembly_complete/src/
+ *
+ * Program to test all the functions of the reassembly part.
+ * Simulate the reassembly by trying to insert some PBs received from the pr/proc
+ * processing it, trashing it, etc ...
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+
+#include "lib/test.h"
+#include "lib/trace.h"
+#include "lib/read_word.h"
+
+#include "mac/sar/sar.h"
+#include "mac/common/store.h"
+#include "mac/common/ntb.h"
+
+#include "hal/phy/phy.h"
+
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+#include "mac/sar/test/inc/ce.h"
+
+#include "mac/sar/inc/sar_context.h"
+
+uint cpt;
+test_t test;
+mac_store_t *mac_store;
+sar_t *sar_ctx;
+pbproc_t *pbproc;
+mac_config_t *mac_config;
+ca_t *ca;
+phy_t *phy;
+
+bool bool_test;
+
+void rea_comp_sar_rea_done_with_one_pb (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs, bool encrypted)
+{
+ cpt ++;
+}
+
+void rea_comp_sar_rea_done (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs, bool encrypted)
+{
+ if (length != list[cpt])
+ bool_test = true;
+ cpt ++;
+}
+
+void this_test_init (void)
+{
+ mac_config = blk_alloc ();
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ mac_store = mac_store_init ();
+ pbproc = pbproc_init (mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ bool_test = false;
+ cpt = 0;
+
+ /* Data */
+ mac_store = mac_store_init ();
+ sar_init_data_context (sar_ctx, sar_ctx);
+ sar_init_mme_context (sar_ctx, sar_ctx);
+ sar_init_reassembly_data_cb (sar_ctx, rea_comp_sar_rea_done);
+ sar_init_reassembly_mme_cb (sar_ctx, rea_comp_sar_rea_done);
+ sar_init_measure_context (sar_ctx, sar_ctx);
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ mac_store_sta_add (mac_store, 0x1);
+}
+
+void this_test_uninit (void)
+{
+ sar_uninit (sar_ctx);
+ pbproc_uninit (pbproc);
+ blk_release (mac_config);
+ dbg_check (mac_store_sta_remove (mac_store, 0x1));
+ mac_store_uninit (mac_store);
+ mac_ntb_uninit();
+ blk_release (ca);
+ blk_release (phy);
+}
+
+void this_test_data_rx_with_one_pb (void)
+{
+ mfs_rx_t *mfs;
+ pb_t *pb;
+ bool added;
+ pbproc_rx_params_t rx_params;
+ u8 buffer[2048];
+
+ sar_init_reassembly_data_cb (sar_ctx, rea_comp_sar_rea_done_with_one_pb);
+
+ /* add a mfs */
+ mfs = mac_store_mfs_add_rx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->expiration_ntb = 100;
+ pb->header.ssn = 0;
+ pb->header.vpbf = true;
+ pb->header.mmqf = false;
+ pb->header.opsf = false;
+ pb->header.mfbf = true;
+ pb->header.mfbo = 0;
+
+ // MF of 283 bytes => 0x0442 (with type = 2)
+ *(u32 *) pb->data = 0x12340442;
+
+ pb->next = NULL;
+
+ rx_params.lid = 1;
+ rx_params.tei = 1;
+ rx_params.bcast = false;
+
+ sar_mpdu_add (sar_ctx, (mfs_t *) mfs, NULL, &rx_params, pb, pb, 1, NULL, 0);
+
+ sar_mfs_add (sar_ctx, (mfs_t *)mfs);
+
+ // process the mpdu
+ sar_launch (sar_ctx);
+ sar_data_buffer_add (sar_ctx, buffer);
+
+ // add the buffer and launch the bridge dma
+ sar_launch (sar_ctx);
+
+ // launch the bridge dma callback.
+ sar_launch (sar_ctx);
+
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+ mac_store_mfs_remove (mac_store, (mfs_t*) mfs);
+ blk_release (mfs);
+
+ ce_uninit ();
+}
+
+void this_test_data_rx (void)
+{
+ mfs_rx_t *mfs;
+ pb_t *pb_first;
+ pb_t *pb_last;
+ bool added;
+ pbproc_rx_params_t rx_params;
+ u8 buffer[2048];
+ uint i;
+
+ sar_init_reassembly_data_cb (sar_ctx, rea_comp_sar_rea_done);
+
+ /* add a mfs */
+ mfs = mac_store_mfs_add_rx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+ mfs->common.expiration_ntb = 10000;
+ mfs->common.expiration_delay_ntb = 10000;
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ sar_unit_test_generate_pb_list (&pb_first, &pb_last);
+
+ rx_params.lid = 1;
+ rx_params.tei = 1;
+ rx_params.bcast = false;
+
+ sar_mpdu_add (sar_ctx, (mfs_t *) mfs, NULL, &rx_params, pb_first,
+ pb_last, 14, NULL, 0);
+
+ sar_mfs_add (sar_ctx, (mfs_t *)mfs);
+
+ // process the mpdu
+ sar_launch (sar_ctx);
+
+ for (i = 0; i < 11; i++)
+ {
+ sar_data_buffer_add (sar_ctx, buffer);
+
+ // add the buffer and launch the bridge dma
+ sar_launch (sar_ctx);
+
+ // launch the bridge dma callback.
+ sar_launch (sar_ctx);
+ }
+
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+ mac_store_mfs_remove (mac_store, (mfs_t*) mfs);
+ blk_release (mfs);
+
+ ce_uninit ();
+
+ test_begin(test, "rea complete")
+ {
+ test_fail_if (bool_test == true, "wrong size");
+ test_fail_if (cpt != 11, "all the MF had not been caught");
+ }
+ test_end;
+}
+
+void this_test_mme_rx_with_one_pb (void)
+{
+ mfs_rx_t *mfs;
+ pb_t *pb;
+ pbproc_rx_params_t rx_params;
+ u8 buffer[2048];
+ bool added;
+
+ sar_init_reassembly_mme_cb (sar_ctx, rea_comp_sar_rea_done_with_one_pb);
+
+ /* add a mfs */
+ mfs = mac_store_mfs_add_rx (mac_store, false, true, MAC_LID_NONE, 1, &added);
+ dbg_assert (added);
+ mfs->common.expiration_ntb = 10000;
+ mfs->common.expiration_delay_ntb = 10000;
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->expiration_ntb = 100;
+ pb->header.ssn = 0;
+ pb->header.vpbf = true;
+ pb->header.mmqf = true;
+ pb->header.opsf = false;
+ pb->header.mfbf = true;
+ pb->header.mfbo = 0;
+
+ // MF of 283 bytes => 0x0442 (with type = 2)
+ *(u32 *) pb->data = 0x12340442;
+
+ pb->next = NULL;
+
+ rx_params.lid = 1;
+ rx_params.tei = 1;
+ rx_params.bcast = false;
+
+ sar_mpdu_add (sar_ctx, NULL, NULL, &rx_params, pb, pb, 1, NULL, 0);
+
+ // process the mpdu
+ sar_launch (sar_ctx);
+ sar_data_buffer_add (sar_ctx, buffer);
+
+ // add the buffer and launch the bridge dma
+ sar_launch (sar_ctx);
+
+ // launch the bridge dma callback.
+ sar_launch (sar_ctx);
+
+ /* Get the MFS. */
+
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+ mac_store_mfs_remove (mac_store, (mfs_t*) mfs);
+ blk_release (mfs);
+
+ ce_uninit ();
+}
+
+/** This test shall reject all PB cause of the MFT witch does not correspond
+ * to the MFS type.*/
+void this_test_mme_rx_all_error (void)
+{
+ mfs_rx_t *mfs;
+ pb_t *pb_first;
+ pb_t *pb_last;
+ bool added;
+ pbproc_rx_params_t rx_params;
+ pb_t *pb_curr;
+
+ sar_init_reassembly_data_cb (sar_ctx, rea_comp_sar_rea_done);
+
+ /* add a mfs */
+ mfs = mac_store_mfs_add_rx (mac_store, false, true, MAC_LID_NONE, 1,
+ &added);
+ dbg_assert (added);
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ sar_unit_test_generate_pb_list (&pb_first, &pb_last);
+ for (pb_curr = pb_first; pb_curr; pb_curr = pb_curr->next)
+ {
+ pb_curr->header.mmqf = true;
+ }
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ rx_params.lid = 1;
+ rx_params.tei = 1;
+ rx_params.bcast = false;
+
+ sar_mpdu_add (sar_ctx, NULL, (mfs_t *) mfs, &rx_params, pb_first,
+ pb_last, 14, NULL, 0);
+
+ sar_mfs_add (sar_ctx, (mfs_t *)mfs);
+
+ // process the mpdu
+ sar_launch (sar_ctx);
+
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+ mac_store_mfs_remove (mac_store, (mfs_t*) mfs);
+ blk_release (mfs);
+
+ ce_uninit ();
+
+ test_begin(test, "rea complete")
+ {
+ test_fail_if (bool_test == true, "wrong size");
+ test_fail_if (cpt != 0, "NO MF shall be caught");
+ }
+ test_end;
+}
+
+void this_test_mme_rx (void)
+{
+ mfs_rx_t *mfs;
+ pb_t *pb_first;
+ pb_t *pb_last;
+ bool added;
+ pbproc_rx_params_t rx_params;
+ u8 buffer[2048];
+ uint i;
+
+ sar_init_reassembly_data_cb (sar_ctx, rea_comp_sar_rea_done);
+
+ /* add a mfs */
+ mfs = mac_store_mfs_add_rx (mac_store, false, true, MAC_LID_NONE, 1,
+ &added);
+ dbg_assert (added);
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ sar_unit_test_generate_mme_pb_list (&pb_first, &pb_last);
+
+ mfs->head = NULL;
+ mfs->tail = NULL;
+
+ rx_params.lid = 1;
+ rx_params.tei = 1;
+ rx_params.bcast = false;
+
+ sar_mpdu_add (sar_ctx, NULL, (mfs_t *) mfs, &rx_params, pb_first,
+ pb_last, 12, NULL, 0);
+
+ sar_mfs_add (sar_ctx, (mfs_t *)mfs);
+
+ // process the mpdu
+ sar_launch (sar_ctx);
+
+ for (i = 0; i < 11; i++)
+ {
+ sar_mme_buffer_add (sar_ctx, buffer);
+
+ // add the buffer and launch the bridge dma
+ sar_launch (sar_ctx);
+
+ // launch the bridge dma callback.
+ sar_launch (sar_ctx);
+ }
+
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+ mac_store_mfs_remove (mac_store, (mfs_t*) mfs);
+ blk_release (mfs);
+
+ ce_uninit ();
+
+ test_begin(test, "rea complete")
+ {
+ test_fail_if (bool_test == true, "wrong size");
+ test_fail_if (cpt != 11, "all the MF had not been caught");
+ }
+ test_end;
+}
+
+int main (void)
+{
+ trace_init ();
+ test_init (test, 0, NULL);
+
+ this_test_init ();
+ this_test_data_rx_with_one_pb ();
+ this_test_uninit ();
+
+ this_test_init ();
+ this_test_mme_rx_with_one_pb ();
+ this_test_uninit ();
+
+ this_test_init ();
+ this_test_data_rx ();
+ this_test_uninit ();
+
+ this_test_init ();
+ this_test_mme_rx_all_error();
+ this_test_uninit ();
+
+ this_test_init ();
+ this_test_mme_rx ();
+ this_test_uninit ();
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/reassembly_create_mfs.c b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_create_mfs.c
new file mode 100644
index 0000000000..6a9137f69e
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_create_mfs.c
@@ -0,0 +1,149 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_create_mfs.c
+ * \brief function implementations for the reassembly part
+ * \ingroup mac/sar/test/reassembly_create_mfs/src
+ *
+ * Test the creation of the missing MFS associated with the received segments.
+ */
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/kernel/kapi.h>
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+
+#include "mac/sar/sar.h"
+#include "mac/common/store.h"
+#include "mac/common/ntb.h"
+
+#include "hal/phy/phy.h"
+
+#include "mac/sar/inc/sar_pb.h"
+
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+#include "mac/sar/test/inc/ce.h"
+
+#include <stdio.h>
+
+test_t test;
+
+void test_without_mfs (uint lid, bool mme, bool bcast)
+{
+ mfs_rx_t *mfs;
+ pbproc_rx_params_t rx_params;
+ pbproc_t *pbproc;
+ mac_config_t *mac_config;
+ pb_t *pb_first;
+ sar_t *sar_ctx;
+ mac_store_t *mac_store;
+ ca_t *ca;
+ phy_t *phy;
+
+ // init the store and the sar
+ ca = blk_alloc();
+ phy = blk_alloc();
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init(mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ sar_init_measure_context (sar_ctx, &sar_ctx);
+
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ //add a sta to the store
+ mac_store_sta_add (mac_store, 0x1);
+
+ // Second test
+ pb_first = (pb_t *) blk_alloc_desc ();
+ pb_first->header.ssn = 0;
+ pb_first->header.vpbf = true;
+ pb_first->header.mmqf = mme;
+ pb_first->next = NULL;
+
+ rx_params.lid = lid;
+ rx_params.tei = 1;
+ rx_params.bcast = bcast;
+ rx_params.bdf = false;
+
+ sar_mpdu_add (sar_ctx, (mfs_t *) NULL, NULL, &rx_params, pb_first,
+ pb_first, 1, NULL,0);
+
+ sar_launch (sar_ctx);
+
+ // try to get the mfs from the store.
+ mfs = mac_store_mfs_get_rx (mac_store, bcast, mme, lid, 0x1);
+
+ test_begin(test, "mpdu_rx_process")
+ {
+ if (mme)
+ {
+ test_fail_if(mfs == NULL, "MME MFS should exist");
+ blk_release (mfs);
+ }
+ else if (MAC_LID_IS_PLID(lid))
+ {
+ test_fail_if(mfs == NULL, "MFS should exist, mfs is a plid mfs");
+ blk_release (mfs);
+ }
+ else
+ {
+ test_fail_if(mfs != NULL, "MFS should not exist, mfs is not a plid mfs");
+ }
+ }
+ test_end;
+
+ if (mfs)
+ {
+ mac_store_mfs_remove(mac_store, (mfs_t *) mfs);
+ }
+
+ dbg_check(mac_store_sta_remove (mac_store, 0x1));
+ pbproc_uninit(pbproc);
+ mac_ntb_uninit();
+
+ blk_release (phy);
+ blk_release (mac_config);
+ mac_store_uninit(mac_store);
+ sar_uninit (sar_ctx);
+ ce_uninit ();
+ blk_release (ca);
+}
+
+int main (void)
+{
+ test_init (test, 0, NULL);
+ trace_init ();
+
+ // MME mfs
+ test_without_mfs (MAC_LID_NONE, true, false);
+ test_without_mfs (MAC_LID_NONE, true, true);
+
+ // plid mfs
+ test_without_mfs (1, false, true);
+ test_without_mfs (1, false, false);
+
+ // !plid mfs
+ test_without_mfs (MAC_PLID_MAX + 1, false, false);
+ test_without_mfs (MAC_PLID_MAX + 1, false, true);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/reassembly_measurement.c b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_measurement.c
new file mode 100644
index 0000000000..118abc5dc0
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_measurement.c
@@ -0,0 +1,126 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_measurement.c
+ * \brief unit test for the pb measurement transmission.
+ * \ingroup mac/sar/test/reassembly_measurement/src/
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "lib/blk.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+
+#include "mac/sar/sar.h"
+#include "mac/common/store.h"
+#include "mac/common/ntb.h"
+
+#include "hal/phy/phy.h"
+
+#include "mac/sar/test/inc/sar_unit_test_functions.h"
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+#include "mac/sar/test/inc/ce.h"
+
+#define NB_PB 200
+
+int main (void)
+{
+ test_t test;
+
+ uint i, ber;
+ pb_t *pb, *pb_last, *pb_curr;
+ pbproc_rx_params_t rx_params;
+ sar_t *sar_ctx;
+ mac_store_t *mac_store;
+ mac_config_t *mac_config;
+ pbproc_t *pbproc;
+ ca_t *ca;
+ phy_t *phy;
+
+ blk_t *blk_curr;
+ uint blk_offset;
+
+ trace_init ();
+ test_init (test, 0, NULL);
+
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init(mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ sar_init_measure_context (sar_ctx, sar_ctx);
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ pb = (pb_t *) blk_alloc_desc_range (NB_PB, (blk_t **) &pb_last);
+
+ pb_last->next = NULL;
+ pb_curr = pb;
+ for (i = 0; i < NB_PB; i++)
+ {
+ ber = 0x12345 + i;
+ pb_curr->header.vpbf = false;
+ memcpy (&pb_curr->phy_pb.pb_rx.pb_measurement, &ber, 4);
+ pb_curr = pb_curr->next;
+ }
+
+ rx_params.lid = 0x1;
+ rx_params.tei = 0x1;
+ rx_params.bdf = false;
+
+ sar_mpdu_add (sar_ctx, NULL, NULL, &rx_params, pb, pb_last, NB_PB, NULL, 0);
+
+ sar_launch (sar_ctx);
+
+ test_begin(test, "measurement")
+ {
+ blk_curr = ce_ctx.measurement_head;
+ blk_offset = 0;
+ ber = 0x12345;
+
+ for (i = 0; i < NB_PB; i++)
+ {
+ if (blk_offset == (BLK_SIZE >> 2))
+ {
+ blk_curr = blk_curr->next;
+ blk_offset = 0;
+ }
+
+ test_fail_if(*((u32 *)((pb_measurement_t *)blk_curr->data
+ + blk_offset)) != ber + i, "Error");
+ blk_offset ++;
+ }
+ }
+ test_end;
+
+ mac_store_uninit (mac_store);
+ mac_ntb_uninit();
+
+ blk_release (phy);
+ blk_release(mac_config);
+ pbproc_uninit(pbproc);
+ sar_uninit (sar_ctx);
+ ce_uninit ();
+ blk_release (ca);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/reassembly_mfs_update_expiration_date.c b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_mfs_update_expiration_date.c
new file mode 100644
index 0000000000..c6ad9a9030
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_mfs_update_expiration_date.c
@@ -0,0 +1,100 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_mfs_update_expiration_ntb.c
+ * \brief test to verify the mfs update expiration date
+ * \ingroup mac/sar/test/unit_test/reassembly_mfs_update_expiration_ntb/src
+ *
+ */
+
+#include "common/std.h"
+#include "mac/sar/sar.h"
+
+#include "lib/test.h"
+#include "lib/trace.h"
+
+#include "mac/common/config.h"
+#include "mac/common/ntb.h"
+#include "hal/phy/phy.h"
+
+#include "mac/sar/inc/sar_context.h"
+#include "mac/sar/inc/sar.h"
+
+#include "mac/sar/test/inc/sar_unit_test_functions.h"
+
+int main (void)
+{
+ test_t test;
+ sar_mpdu_t *rx;
+ sar_t *sar_ctx;
+ mac_store_t *mac_store;
+ bool added;
+ mac_config_t *mac_config;
+ pbproc_t *pbproc;
+ ca_t *ca;
+ phy_t *phy;
+
+ trace_init ();
+
+ rx = (sar_mpdu_t *) blk_alloc ();
+
+ mac_store = mac_store_init ();
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init (mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ rx->mfs = mac_store_mfs_add_rx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+
+ sar_mfs_add (sar_ctx, (mfs_t *) rx->mfs);
+
+ sar_expiration_mfs_update_date (&sar_ctx->expiration, (mfs_t *) rx->mfs,
+ mac_ntb());
+
+ test_init (test, 0, NULL);
+
+ test_begin (test, "reassembly_mfs_update_expiration_ntb")
+ {
+ test_fail_if (rx->mfs->common.expiration_ntb != 42, "The expiration date had not been modified");
+ }
+ test_end;
+
+ sar_uninit (sar_ctx);
+
+ mac_store_mfs_remove (mac_store, (mfs_t *) rx->mfs);
+
+ dbg_check (mac_store_sta_remove (mac_store, 1));
+ mac_store_uninit (mac_store);
+
+ blk_release (rx->mfs);
+ blk_release (rx);
+ blk_release (mac_config);
+ pbproc_uninit (pbproc);
+
+ mac_ntb_uninit();
+
+ blk_release (phy);
+ blk_release (ca);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/reassembly_two_jobs.c b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_two_jobs.c
new file mode 100644
index 0000000000..b34deaa497
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/reassembly_two_jobs.c
@@ -0,0 +1,236 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file reassembly_two_jobs.c
+ * \brief launch two reassembly process.
+ * \ingroup mac/sar/
+ *
+ * Only use for coverage test.
+ */
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/kernel/kapi.h>
+
+#include "common/std.h"
+#include "lib/blk.h"
+#include "lib/trace.h"
+#include "lib/read_word.h"
+
+#include "mac/sar/sar.h"
+
+#include "hal/phy/phy.h"
+#include "mac/common/config.h"
+#include "mac/common/ntb.h"
+#include "lib/test.h"
+
+#include "mac/sar/inc/trace.h"
+#include "mac/sar/inc/sar_context.h"
+
+#include <stdio.h>
+
+pbproc_rx_params_t *ce_rx_params[3];
+uint ce_rx_params_count = 0;
+
+bool ce_measurement_cb_stub (void *user,
+ pbproc_rx_params_t *rx_params, uint pb_nb, blk_t **first,
+ blk_t **last, pb_t *chan_data_first, uint nb_chandata, uint
+ *blk_offset)
+{
+ ce_rx_params[ce_rx_params_count] = rx_params;
+ ce_rx_params_count ++;
+ *blk_offset = 0;
+ return false;
+}
+
+
+void sar_reassembly_done_stub (void *user, u8* buffer, uint length, mfs_rx_t *mfs, bool encrypted)
+{
+ dbg_assert (user);
+ dbg_assert (buffer);
+ dbg_assert (mfs);
+}
+
+
+void sar_mfs_expired_cb_stub (void *user, mfs_t *mfs)
+{
+ dbg_assert (user);
+ dbg_assert (mfs);
+}
+
+int main (void)
+{
+ sar_t *sar_ctx;
+ mac_store_t *mac_store;
+ pbproc_t *pbproc;
+ ca_t *ca;
+ phy_t *phy;
+
+ test_t test;
+ pbproc_rx_params_t rx_params;
+ mac_config_t mac_config;
+ u8 buffer [2048];
+ u8 buffer_end[2048];
+ uint i;
+
+ pb_t *pb_head;
+ pb_t *pb_tail;
+ mfs_rx_t *mfs;
+
+ ce_rx_params[0] = NULL;
+ ce_rx_params[1] = NULL;
+ ce_rx_params[2] = NULL;
+ trace_init ();
+ test_init (test, 0, NULL);
+
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+ mac_ntb_init (phy, &mac_config);
+ mac_store = mac_store_init();
+ pbproc = pbproc_init(&mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ sar_init_measure_context (sar_ctx, &sar_ctx);
+ sar_init_measurement_cb (sar_ctx, ce_measurement_cb_stub);
+
+ sar_init_data_context (sar_ctx, &sar_ctx);
+ sar_init_mme_context (sar_ctx, &sar_ctx);
+ sar_init_reassembly_data_cb (sar_ctx, sar_reassembly_done_stub);
+ sar_init_reassembly_mme_cb (sar_ctx, sar_reassembly_done_stub);
+
+ sar_init_expiration(sar_ctx, sar_mfs_expired_cb_stub);
+
+
+ // Initialize the buffer with some values
+ buffer[0] = 0xf5;
+ buffer[1] = 0x16;
+ for (i = 2; i < 1518; i++)
+ {
+ buffer[i] = i;
+ }
+
+ // First MPDU.
+ pb_head = (pb_t *) blk_alloc_desc_range (3, (blk_t **) &pb_tail);
+
+ pb_head->header.ssn = 0;
+ pb_head->header.vpbf = true;
+ pb_head->header.mfbf = true;
+ pb_head->header.mfbo = 0;
+
+ memcpy (pb_head->data, buffer, BLK_SIZE);
+
+ pb_head->next->header.ssn = 1;
+ pb_head->next->header.vpbf = true;
+ pb_head->next->header.mfbf = false;
+ pb_head->next->header.mfbo = 0;
+
+ memcpy (pb_head->next->data, buffer + BLK_SIZE, BLK_SIZE);
+
+ pb_tail->next = NULL;
+ pb_tail->header.ssn = 2;
+ pb_tail->header.vpbf = true;
+ pb_tail->header.mfbf = false;
+ pb_tail->header.mfbo = 0;
+
+ memcpy (pb_tail->data, buffer + 2 * BLK_SIZE, BLK_SIZE);
+
+ rx_params.lid = 1;
+ rx_params.tei = 1;
+ rx_params.bcast = false;
+
+ sar_mpdu_add (sar_ctx, NULL, NULL, &rx_params, pb_head, pb_tail, 3, NULL,
+ 0);
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+
+ // Second job
+ pb_head = (pb_t *) blk_alloc_desc_range (3, (blk_t **) &pb_tail);
+
+ pb_head->header.ssn = 3;
+ pb_head->header.vpbf = true;
+ pb_head->header.mfbf = true;
+ pb_head->header.mfbo = 0;
+
+ memcpy (pb_head->data, buffer, BLK_SIZE);
+
+ pb_head->next->header.ssn = 4;
+ pb_head->next->header.vpbf = true;
+ pb_head->next->header.mfbf = false;
+ pb_head->next->header.mfbo = 0;
+
+ memcpy (pb_head->next->data, buffer + BLK_SIZE, BLK_SIZE);
+
+ pb_tail->next = NULL;
+ pb_tail->header.ssn = 5;
+ pb_tail->header.vpbf = true;
+ pb_tail->header.mfbf = false;
+ pb_tail->header.mfbo = 0;
+
+ memcpy (pb_tail->data, buffer + BLK_SIZE, BLK_SIZE);
+ sar_mpdu_add (sar_ctx, NULL, NULL, &rx_params, pb_head, pb_tail, 3, NULL,
+ 0);
+ sar_launch (sar_ctx);
+
+ // ADD a null PB
+ pb_head = (pb_t *) blk_alloc_desc ();
+ pb_head->next = NULL;
+
+ pb_head->header.ssn = 6;
+ pb_head->header.vpbf = true;
+ pb_head->header.mfbf = true;
+ pb_head->header.mfbo = 0;
+ pb_head->data[0] = 0x0;
+
+ sar_mpdu_add (sar_ctx, NULL, NULL, &rx_params, pb_head, pb_head, 1, NULL,
+ 0);
+ sar_launch (sar_ctx);
+
+ sar_buffer_add (sar_ctx, buffer_end, true);
+ sar_buffer_add (sar_ctx, buffer_end, true);
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+
+ mfs = mac_store_mfs_get_rx (mac_store, false, false, 1, 1);
+ dbg_assert (mfs);
+
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+ blk_release (mfs);
+
+ mac_store_sta_remove (mac_store, 0x1);
+
+ sar_trace_print (sar_ctx);
+
+ mac_store_uninit(mac_store);
+ pbproc_uninit(pbproc);
+ sar_uninit (sar_ctx);
+ mac_ntb_uninit();
+
+ blk_release (ca);
+ blk_release (phy);
+
+ trace_uninit();
+
+ for (i= 0; i < 3; i++)
+ {
+ blk_release (ce_rx_params[i]);
+ }
+
+ blk_print_memory();
+
+ test_begin (test, "memory")
+ {
+ test_fail_if (blk_check_memory == false, "Memory not freed");
+ }
+ test_end;
+
+ printf ("End\n");
+ HAL_PLATFORM_EXIT (0);
+ return 0;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/sar_call_back_ul.c b/cesar/mac/sar/test/unit_test/ecos/src/sar_call_back_ul.c
new file mode 100644
index 0000000000..ee2262204d
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/sar_call_back_ul.c
@@ -0,0 +1,179 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_call_back_cl.c
+ * \brief Test the call backs
+ * \ingroup mac/sar/test/sar_call_back_cl/src/
+ *
+ * Unit test to verify the call backs implemetation for the CL communication.
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "mac/sar/sar.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+#include "mac/common/ntb.h"
+#include "hal/phy/phy.h"
+
+#include "mac/sar/inc/sar_context.h"
+#include "mac/sar/inc/sar.h"
+
+sar_t *sar_ctx;
+
+/**
+ * Implementation of the sar_segmentation_done_cb_t call back.
+ * Only used in this test.
+ *
+ * \param user, User data
+ */
+void sar_segmentation_ul_done (void *user, u8* buffer);
+
+/**
+ * Implementation of the sar_reassembly_done_cb_t call back.
+ * Only used in this test.
+ *
+ * \param user, User data
+ */
+void sar_reassembly_ul_done (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs, bool encrypted);
+
+/**
+ * Implementation of the sar_beacon_cb_t call back
+ * Only used in this test.
+ */
+void sar_beacon (void *user, pb_beacon_t *pb,
+ pbproc_rx_beacon_params_t *params);
+
+bool bool_seg_test;
+bool bool_rea_test;
+bool bool_beacon_test;
+test_t test;
+
+int main (void)
+{
+ mac_store_t *mac_store;
+ mac_config_t *mac_config;
+ pbproc_t *pbproc;
+ ca_t *ca;
+ phy_t *phy;
+
+ trace_init ();
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+ phy = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init (mac_config, mac_store);
+ ca = blk_alloc ();
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ sar_init_data_context (sar_ctx, &sar_ctx);
+ sar_init_mme_context (sar_ctx, &sar_ctx);
+
+ sar_init_segmentation_data_cb (sar_ctx, sar_segmentation_ul_done);
+ sar_init_reassembly_data_cb (sar_ctx, sar_reassembly_ul_done);
+ sar_init_beacon_cb (sar_ctx, NULL, sar_beacon);
+
+ bool_seg_test = false;
+ bool_rea_test = false;
+ bool_beacon_test = false;
+ (*sar_ctx->sar_seg_data_done_cb) (sar_ctx->ul_data_ctx, NULL);
+ (*sar_ctx->data_ctx.sar_rea_done) (sar_ctx->ul_data_ctx, NULL, 123, NULL,
+ true);
+
+ test_init (test, 0, NULL);
+ test_begin(test, "sar_call_back_cl")
+ {
+ test_fail_if(bool_seg_test != true, "segmentation call back failed");
+ test_fail_if(bool_rea_test != true, "reassembly call back failed");
+ }
+ test_end;
+
+ bool_seg_test = false;
+ bool_rea_test = false;
+ sar_init_segmentation_mme_cb (sar_ctx, sar_segmentation_ul_done);
+ sar_init_reassembly_mme_cb (sar_ctx, sar_reassembly_ul_done);
+
+ (*sar_ctx->sar_seg_msg_done_cb) (sar_ctx->ul_msg_ctx, NULL);
+ (*sar_ctx->mme_ctx.sar_rea_done) (sar_ctx->ul_msg_ctx, NULL, 123, NULL,
+ true);
+
+ test_begin(test, "sar_call_back_cl")
+ {
+ test_fail_if(bool_seg_test != true, "segmentation call back failed");
+ test_fail_if(bool_rea_test != true, "reassembly call back failed");
+ }
+ test_end;
+
+ bool_beacon_test = false;
+ sar_beacon_add (sar_ctx, blk_alloc (), blk_alloc ());
+ test_begin(test, "sar_beacon_call_back")
+ {
+ test_fail_if (bool_beacon_test != true, "beacon call back failed");
+ }
+ test_end;
+
+ pbproc_uninit (pbproc);
+ sar_uninit (sar_ctx);
+ mac_store_uninit (mac_store);
+ mac_ntb_uninit();
+ blk_release (ca);
+ blk_release (phy);
+ blk_release (mac_config);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
+/**
+ * Implementation of the sar_segmentation_done_cb_t call back.
+ * Only used in this test.
+ *
+ * \param user, User data
+ */
+void sar_segmentation_ul_done (void *user, u8* buffer)
+{
+ bool_seg_test = true;
+ //printf ("sar_segmentation_done\n");
+}
+
+/**
+ * Implementation of the sar_reassembly_done_cb_t call back.
+ * Only used in this test.
+ *
+ * \param user, User data
+ */
+void sar_reassembly_ul_done (void *user, u8* buffer, uint length,
+ mfs_rx_t *mfs, bool encrypted)
+{
+ bool_rea_test = true;
+ //printf ("sar_reassembly_done\n");
+}
+
+/**
+ * Implementation of the sar_beacon_cb_t call back
+ * Only used in this test.
+ */
+void sar_beacon (void *user, pb_beacon_t *pb,
+ pbproc_rx_beacon_params_t *params)
+{
+ dbg_assert (((sar_t *)sar_ctx)->ul_msg_ctx);
+ bool_beacon_test = true;
+ blk_release (pb);
+ blk_release (params);
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/sar_manage_expiration.c b/cesar/mac/sar/test/unit_test/ecos/src/sar_manage_expiration.c
new file mode 100644
index 0000000000..fd75d2c0e8
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/sar_manage_expiration.c
@@ -0,0 +1,808 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file manage_expiration.c
+ * \brief unit test for the managing expiration
+ * \ingroup mac/sar/test/manage_expiration
+ *
+ * All the functions necessary to realize the reassembly of the Mac Frame
+ * receives from a station.
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "lib/rnd.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+#include "lib/bitstream.h"
+
+#include "mac/common/store.h"
+#include "mac/common/ntb.h"
+
+#include "hal/phy/phy.h"
+
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/sar_context.h"
+#include "mac/sar/inc/sar.h"
+#include "mac/sar/inc/sar_expiration.h"
+
+#include "mac/sar/test/inc/sar_unit_test_functions.h"
+
+lib_rnd_t ctx;
+test_t test;
+bool ul_prevent;
+bool seg_done;
+
+sar_t *sar_ctx;
+mac_store_t *mac_store;
+mac_config_t *mac_config;
+pbproc_t *pbproc;
+ca_t *ca;
+phy_t *phy;
+
+void
+sar_segmentation_done (void *user, u8* buffer)
+{
+ seg_done = true;
+}
+
+void sar_mfs_expired_cb (void *user, mfs_t *mfs)
+{
+ ul_prevent = true;
+}
+
+/** first test.
+ * Expiration of a mfs_tx.
+ *
+ * Expiration delay = 10
+ * Expiration date = 100
+ * Release State = False
+ *
+ * At the End the mfs should be in the release state and should not have any
+ * PB.
+ **/
+void mfs_tx_expiration_go_to_release_state (void);
+
+/** Second test.
+ * Expiration of a mfs_tx in a release state.
+ *
+ * Depends on the First TEST. The MFS to destroy is present in the mac store
+ * after the "mfs_tx_expiration_go_to_release_state".
+ *
+ * Release State = True
+ *
+ * At the End the mfs should not exist anymore.
+ **/
+void mfs_tx_in_release_state_go_to_destroy (void);
+
+/** Third Test.
+ * Expiration of a MFS which is not a PLID one.
+ * The Upper layer should be prevent.
+ *
+ * MFS type = TX.
+ * MFS expiration date = 100
+ * MFS expiration delay = 10
+ * MFS lid = 10
+ * MFS head != NULL i.e. contains a PB.
+ *
+ * At the end
+ * - The ul_prevent should be true.
+ * - The MFS should be in a release state.
+ * - The MFS should not contain any PB.
+ */
+void mfs_tx_glid_go_to_release_state (void);
+
+/** Fourth test
+ * Expiration of a MFS (not a plid one) after had been passed in a release state
+ *
+ * Depends of mfs_tx_in_release_state_go_to_destroy test
+ *
+ * At the end the mac store should not contain the MFS.
+ */
+void mfs_tx_glid_to_destroy (void);
+
+/**
+ * Request a remove from the SAR
+ *
+ * MFS type : TX
+ * MFS Release : False
+ * MFS expiration date : 100
+ * MFS expiration delay : 10
+ * MFS head != NULL
+ *
+ * At the end of the test the MFS should be in a release state.
+ */
+void mfs_tx_remove_request (void);
+
+/**
+ * Request a remove from the SAR go to destroy
+ *
+ * Depends on mfs_tx_remove_request test.
+ *
+ * MFS type : TX
+ * MFS Release : True
+ *
+ * At the end of the test the MFS should not be in the mac store.
+ */
+void mfs_tx_remove_request_go_to_destroy (void);
+
+/**
+ * Expiration of a MFS in RX mode
+ *
+ * MFS type : RX
+ * MFS release : false
+ * MFS head != NULL
+ * MFS expiration delay = 10
+ * MFS expiration date = 100
+ * MFS lid : 1
+ *
+ * At the end the MFS should be not exist in the mac store.
+ *
+ * When the MFS is a plid kind, it is directly removed from the SAR and from the
+ * store.
+ */
+void mfs_rx_plid_epiration (void);
+
+/**
+ * Expiration of a MFS in RX mode
+ *
+ * MFS type : RX
+ * MFS release : false
+ * MFS head != NULL
+ * MFS expiration delay = 10
+ * MFS expiration date = 100
+ * MFS lid : 0x80
+ *
+ * At the end
+ *
+ * When the MFS is a not a plid kind, It should be still present in the store
+ * without any PB.
+ */
+void mfs_rx_not_plid_epiration (void);
+
+/**
+ * Expiration of a MFS RX on a ul request.
+ *
+ * MFS type : RX
+ * MFS release : false
+ * MFS head != NULL
+ * MFS expiration delay = 10
+ * MFS expiration date = 100
+ * MFS lid : 0x1
+ *
+ * At the end
+ *
+ * At the end the MFS should be not exist in the mac store.
+ */
+void mfs_rx_expired_on_request (void);
+
+
+/**
+ * Test the expiration of an msdu.
+ * The buffer shall be give back to the buffer list.
+ *
+ * \param phy use to update the date for the expiration.
+ */
+void
+msdu_expiration_test (phy_t *phy);
+
+/**
+ * Test the expiration process with a PB which will expire before the mfs.
+ *
+ * \param phy
+ */
+void
+pb_tx_expire (void);
+
+
+void
+test_expiration_test_init (void)
+{
+ trace_init ();
+
+ // init the sar and the store
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+
+ *(u32*)phy = -1;
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init (mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+ sar_init_mme_context (sar_ctx, &sar_ctx);
+
+ // add a sta to the store.
+ mac_store_sta_add (mac_store, 0x1);
+
+ // init the expiration callback
+ sar_init_expiration (sar_ctx, sar_mfs_expired_cb);
+}
+
+void
+test_expiration_test_uninit (void)
+{
+ sar_uninit (sar_ctx);
+
+ dbg_check (mac_store_sta_remove (mac_store, 1));
+ mac_store_uninit (mac_store);
+ pbproc_uninit (pbproc);
+ mac_ntb_uninit ();
+ blk_release (mac_config);
+ blk_release (ca);
+ blk_release (phy);
+}
+
+
+void
+test_expiration_first_test (void)
+{
+ test_expiration_test_init ();
+
+ //launch the first test.
+ mfs_tx_expiration_go_to_release_state ();
+ mfs_tx_in_release_state_go_to_destroy ();
+
+ test_expiration_test_uninit ();
+}
+
+void
+test_expiration_second_test (void)
+{
+ test_expiration_test_init ();
+
+ // Launch the second Test
+ mfs_tx_glid_go_to_release_state ();
+ mfs_tx_glid_to_destroy ();
+
+ test_expiration_test_uninit ();
+}
+
+void
+test_expiration_third_test (void)
+{
+ test_expiration_test_init ();
+
+ mfs_tx_remove_request ();
+ mfs_tx_remove_request_go_to_destroy ();
+
+ test_expiration_test_uninit ();
+}
+
+void
+test_expiration_fourth_test (void)
+{
+ test_expiration_test_init ();
+
+ mfs_rx_plid_epiration ();
+ mfs_rx_not_plid_epiration ();
+
+ test_expiration_test_uninit ();
+}
+
+
+int cyg_user_start (void)
+{
+ test_init (test, 0, NULL);
+
+ test_expiration_first_test ();
+
+ // Launch the second Test
+ test_expiration_second_test ();
+
+ // Launch the third test
+ test_expiration_third_test ();
+
+ // Launch the fourth test.
+ test_expiration_fourth_test ();
+
+ // test the msdu expiration.
+ msdu_expiration_test (phy);
+
+ // test a PB expiration
+ pb_tx_expire ();
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
+/** first test.
+ * Expiration of a mfs_tx go to a release state.
+ *
+ * Expiration delay = 10
+ * Expiration date = 100
+ * Release State = False
+ *
+ * At the End the mfs should be in the release state and should not have any
+ * PB.
+ **/
+void mfs_tx_expiration_go_to_release_state (void)
+{
+ bool added;
+ mfs_t *mfs;
+
+ // add a tx mfs
+ mfs = mac_store_mfs_add (mac_store, true, false, false, 0x1, 0x1, &added);
+
+ dbg_assert (added);
+
+ mfs->tx.common.expiration_ntb = 100;
+ mfs->tx.common.expiration_delay_ntb = 10;
+ mfs->tx.common.release = false;
+
+ mfs->tx.head = (pb_t *) blk_alloc_desc ();
+ mfs->tx.head->next = NULL;
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, 120);
+
+ test_begin(test, "mfs_tx_expiration_go_to_release_state")
+ {
+ test_fail_if (mfs == NULL, "The MFS had been removed from the mac store.");
+ test_fail_if (mfs->tx.common.release != true,
+ "The expiration on the MFS tx does not work, the MFS should be in the release state.");
+ test_fail_if (mfs->tx.head != NULL,
+ "The expiration of the PBs had not been done");
+ }
+ test_end;
+
+ blk_release (mfs);
+}
+
+/** first test.
+ * Expiration of a mfs_tx in a release state.
+ *
+ * Release State = True
+ *
+ * At the End the mfs should not exist anymore.
+ **/
+void mfs_tx_in_release_state_go_to_destroy (void)
+{
+ mfs_t *mfs;
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, -1);
+
+ mfs = mac_store_mfs_get (mac_store, true, false, false, 0x1, 0x1);
+
+ test_begin(test, "mfs_tx_expiration_destroy_the_mfs")
+ {
+ test_fail_if (mfs != NULL, "The MFS had not been removed from the mac store.");
+ }
+ test_end;
+}
+
+/** Third Test.
+ * Expiration of a MFS which is not a PLID one.
+ * The Upper layer should be prevent.
+ *
+ * MFS type = TX.
+ * MFS expiration date = 100
+ * MFS expiration delay = 10
+ * MFS lid = 10
+ * MFS head != NULL i.e. contains a PB.
+ *
+ * At the end
+ * - The ul_prevent should be true.
+ * - The MFS should be in a release state.
+ * - The MFS should not contain any PB.
+ */
+void mfs_tx_glid_go_to_release_state (void)
+{
+ ul_prevent = false;
+ bool added;
+ mfs_t *mfs;
+
+ // add a tx mfs
+ mfs = mac_store_mfs_add (mac_store, true, false, false, 0xA, 0x1, &added);
+
+ dbg_assert (added);
+
+ mfs->common.tx = true;
+ mfs->tx.common.expiration_ntb = 100;
+ mfs->tx.common.expiration_delay_ntb = 10;
+ mfs->tx.common.release = false;
+
+ mfs->tx.head = (pb_t *) blk_alloc_desc ();
+ mfs->tx.head->next = NULL;
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, mfs);
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, 120);
+
+ test_begin(test, "mfs_tx_glid_go_to_release_state")
+ {
+ test_fail_if (mfs == NULL, "The MFS had been removed from the mac store.");
+ test_fail_if (mfs->tx.common.release != true,
+ "The expiration on the MFS tx does not work, the MFS should be in the release state.");
+ test_fail_if (mfs->tx.head != NULL,
+ "The expiration of the PBs had not been done");
+ test_fail_if (ul_prevent != true, "The upper layer had not been prevent");
+ }
+ test_end;
+
+ blk_release (mfs);
+}
+
+/** Fourth test
+ * Expiration of a MFS (not a plid one) after had been passed in a release state
+ *
+ * Depends of mfs_tx_in_release_state_go_to_destroy test
+ *
+ * At the end the mac store should not contain the MFS.
+ */
+void mfs_tx_glid_to_destroy (void)
+{
+ mfs_t *mfs;
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, -1);
+
+ mfs = mac_store_mfs_get (mac_store, true, false, false, 0xA, 0x1);
+
+ test_begin(test, "mfs_tx_glid_to_destroy")
+ {
+ test_fail_if (mfs != NULL, "The MFS had not been removed from the mac store.");
+ }
+ test_end;
+}
+
+/**
+ * Request a remove from the SAR
+ *
+ * MFS type : TX
+ * MFS Release : False
+ * MFS expiration date : 100
+ * MFS expiration delay : 10
+ * MFS head != NULL
+ *
+ * At the end of the test the MFS should be in a release state.
+ */
+void mfs_tx_remove_request (void)
+{
+ mfs_t *mfs;
+ bool added;
+
+ mfs = mac_store_mfs_add (mac_store, true, false, false, 0x1, 0x1, &added);
+
+ dbg_assert (added);
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, mfs);
+
+ mfs->common.expiration_ntb = 100;
+ mfs->common.expiration_delay_ntb = 10;
+ mfs->tx.head = (pb_t *) blk_alloc_desc ();
+ mfs->tx.head->next = NULL;
+ mfs->tx.common.release = false;
+
+ sar_mfs_remove (sar_ctx, mfs);
+
+ test_begin(test, "mfs_tx_remove_request")
+ {
+ test_fail_if (heap_empty (&sar_ctx->expiration.mfs_expiration_heap), "Expiration Heap Empty");
+ test_fail_if (mfs == NULL, "The MFS had been removed from the mac store.");
+ test_fail_if (mfs->tx.common.release != true,
+ "The expiration on the MFS tx does not work, the MFS should be in the release state.");
+ test_fail_if (mfs->tx.head != NULL,
+ "The expiration of the PBs had not been done");
+ }
+ test_end;
+
+ blk_release (mfs);
+}
+
+/**
+ * Request a remove from the SAR go to destroy
+ *
+ * MFS type : TX
+ * MFS Release : True
+ *
+ * At the end of the test the MFS should not be in the mac store.
+ */
+void mfs_tx_remove_request_go_to_destroy (void)
+{
+ mfs_t *mfs;
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, -1);
+
+ mfs = mac_store_mfs_get (mac_store, true, false, false, 0x1, 0x1);
+
+ test_begin(test, "mfs_tx_remove_request_go_to_destroy")
+ {
+ test_fail_if (mfs != NULL, "The MFS had not been removed from the mac store.");
+ }
+ test_end;
+}
+
+/**
+ * Expiration of a MFS in RX mode
+ *
+ * MFS type : RX
+ * MFS release : false
+ * MFS head != NULL
+ * MFS expiration delay = 10
+ * MFS expiration date = 100
+ *
+ * At the end the MFS should be not exist in the mac store.
+ */
+void mfs_rx_plid_epiration (void)
+{
+ bool added;
+ mfs_t *mfs;
+
+ // add a tx mfs
+ mfs
+ = mac_store_mfs_add (mac_store, false, false, false, 0x1, 0x1,
+ &added);
+
+ dbg_assert (added);
+
+ mfs->rx.common.expiration_ntb = 100;
+ mfs->rx.common.expiration_delay_ntb = 10;
+ mfs->rx.common.release = false;
+
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->next = NULL;
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, mfs);
+
+ // remove the reference provided on the mfs by the store.
+ blk_release (mfs);
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, 120);
+
+ mfs = mac_store_mfs_get (mac_store, false, false, false, 0x1, 0x1);
+
+ test_begin(test, "mfs_rx_epiration_go_to_release_state")
+ {
+ test_fail_if (mfs != NULL, "The MFS had not been removed from the mac store.");
+ }
+ test_end;
+}
+
+/**
+ * Expiration of a MFS in RX mode
+ *
+ * MFS type : RX
+ * MFS release : false
+ * MFS head != NULL
+ * MFS expiration delay = 10
+ * MFS expiration date = 100
+ * MFS lid : 0x80
+ *
+ * At the end
+ *
+ * When the MFS is a not a plid kind, It should be still present in the store
+ * without any PB.
+ */
+void mfs_rx_not_plid_epiration (void)
+{
+ bool added;
+ mfs_t *mfs;
+
+ ul_prevent = false;
+
+ // add a tx mfs
+ mfs = mac_store_mfs_add (mac_store, false, false, false, 0x80, 0x1,
+ &added);
+
+ dbg_assert (added);
+
+ mfs->rx.common.expiration_ntb = 100;
+ mfs->rx.common.expiration_delay_ntb = 10;
+ mfs->rx.common.release = false;
+
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->next = NULL;
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, mfs);
+
+ // remove the reference provided by the store on the mfs.
+ blk_release (mfs);
+
+ // Launch the sar expiration process.
+ sar_expiration_mfs (&sar_ctx->expiration, 120);
+
+ mfs = mac_store_mfs_get (mac_store, false, false, false, 0x1, 0x1);
+
+ test_begin(test, "mfs_rx_not_plid_epiration")
+ {
+ test_fail_if (mfs != NULL, "The MFS had not been removed from the mac store.");
+ test_fail_if (ul_prevent != true, "The upper layers had not been informed");
+ }
+ test_end;
+}
+
+/**
+ * Expiration of a MFS RX on a ul request.
+ *
+ * MFS type : RX
+ * MFS release : false
+ * MFS head != NULL
+ * MFS expiration delay = 10
+ * MFS expiration date = 100
+ * MFS lid : 0x1
+ *
+ * At the end
+ *
+ * At the end the MFS should be not exist in the mac store.
+ */
+void mfs_rx_expired_on_request (void)
+{
+ bool added;
+ mfs_t *mfs;
+
+ // add a tx mfs
+ mfs
+ = mac_store_mfs_add (mac_store, false, false, false, 0x1, 0x1,
+ &added);
+
+ dbg_assert (added);
+
+ mfs->rx.common.expiration_ntb = 100;
+ mfs->rx.common.expiration_delay_ntb = 10;
+ mfs->rx.common.release = false;
+
+ mfs->rx.head = (pb_t *) blk_alloc_desc ();
+ mfs->rx.head->next = NULL;
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, mfs);
+
+ sar_mfs_remove (sar_ctx, mfs);
+
+ mfs = mac_store_mfs_get (mac_store, false, false, false, 0x1, 0x1);
+
+ test_begin(test, "mfs_rx_expired_on_request")
+ {
+ test_fail_if (mfs != NULL, "The MFS had not been removed from the mac store.");
+ }
+ test_end;
+}
+
+/**
+ * Test the expiration of an msdu.
+ * The buffer shall be give back to the buffer list.
+ */
+void
+msdu_expiration_test (phy_t *phy)
+{
+ sar_msdu_t sar_msdu;
+ u8 buffer [2048];
+ mfs_tx_t mfs;
+
+ test_expiration_test_init ();
+
+ sar_msdu.ats_confounder = 0x0;
+ sar_msdu.length = 1400;
+ sar_msdu.buffer_address = buffer;
+ sar_msdu.mfs = &mfs;
+
+
+ *(u32*)phy = -1;
+ seg_done = false;
+
+ sar_init_data_context (sar_ctx, sar_ctx);
+ sar_init_mme_context (sar_ctx, sar_ctx);
+ sar_init_segmentation_data_cb (sar_ctx, sar_segmentation_done);
+ sar_init_segmentation_mme_cb (sar_ctx, sar_segmentation_done);
+ segmentation_run (sar_ctx, &sar_msdu);
+
+ test_begin (test, "MSDU data Expiration")
+ {
+ test_fail_if (seg_done != true, "Expiration not done correctly");
+ }
+ test_end;
+
+ mfs.common.mme = true;
+ segmentation_run (sar_ctx, &sar_msdu);
+
+ test_begin (test, "MSDU MME Expiration")
+ {
+ test_fail_if (seg_done != true, "Expiration not done correctly");
+ }
+ test_end;
+
+
+ test_expiration_test_uninit ();
+}
+
+/**
+ * Test the expiration process with a PB which will expire before the mfs.
+ *
+ */
+void
+pb_tx_expire (void)
+{
+ bitstream_t bitstream;
+ bool added;
+ mfs_tx_t *mfs;
+
+ uint mft;
+ uint length;
+ uint ats;
+
+ test_expiration_test_init ();
+
+ // add a tx mfs
+ mfs = mac_store_mfs_add_tx (mac_store, false, false, 0x1, 0x1,
+ &added);
+
+ dbg_assert (added);
+
+ mfs->common.expiration_ntb = 26000500;
+ mfs->common.expiration_delay_ntb = 10;
+ mfs->common.release = false;
+ mfs->common.ats = true;
+
+ mfs->head = (pb_t *) blk_alloc_desc ();
+ mfs->head->next = NULL;
+ mfs->head->expiration_ntb = 0;
+
+ mft = 2;
+ length = 80;
+ ats = 1;
+ bitstream_init (&bitstream, mfs->head->data, 6, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &mft, 2);
+ bitstream_access (&bitstream, &length, 14);
+ bitstream_access (&bitstream, &ats, 32);
+ bitstream_finalise (&bitstream);
+
+ // Add the mfs in to the sar expiration.
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+ sar_expiration_ajust (&sar_ctx->expiration, (mfs_t *) mfs);
+ sar_expiration_mfs (&sar_ctx->expiration, 25000500);
+
+ test_begin(test, "PB tx expiration process")
+ {
+ test_fail_if (mfs->head != NULL, "The MFS shall not have a pb.");
+ }
+ test_end;
+
+ mfs->common.release = true;
+ sar_expiration_mfs_destroy (&sar_ctx->expiration, (mfs_t *) mfs);
+
+ blk_release (mfs);
+
+ test_expiration_test_uninit ();
+}
+
+
+/**
+ * Create a phy_date weak function to do not have to include the phy on test
+ * when it is not necessary.
+ *
+ * \param phy the phy context.
+ * \return the phy date.
+ */
+u32
+phy_date (phy_t *phy)
+{
+ return *(u32*) phy;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/sar_mf_function_test.c b/cesar/mac/sar/test/unit_test/ecos/src/sar_mf_function_test.c
new file mode 100644
index 0000000000..d386674be8
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/sar_mf_function_test.c
@@ -0,0 +1,148 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mf_function_test.c
+ * \brief unit test for the managing expiration
+ * \ingroup mac/sar/test/manage_expiration
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+#include <stdio.h>
+
+#include "common/std.h"
+#include "mac/sar/inc/sar_mf.h"
+#include "mac/sar/sar.h"
+#include "lib/test.h"
+
+test_t test;
+
+int main (void)
+{
+ bool debug = false;
+ pb_t *pb1;
+ pb_t *pb2;
+
+ uint length;
+ uint type;
+ uint type_length;
+ uint ats;
+
+ type = 2;
+ length = 106 + SAR_MF_ATS_SIZE;
+ ats = 0x1234;
+
+ type_length = type | (length << 2);
+
+ pb1 = (pb_t *) blk_alloc_desc ();
+ pb2 = (pb_t *) blk_alloc_desc ();
+
+ pb1->next = pb2;
+ pb2->next = NULL;
+
+ pb1->header.ssn = 0;
+ pb2->header.ssn = 1;
+
+ *(u32*)pb2->data = type | ((length -1 + SAR_MF_ATS_SIZE) << 2)| (ats << 16);
+
+ if (debug)
+ {
+ printf ("/********** TEST 1 ************/\n");
+ printf ("MF type in pb1 : %d\n", mf_get_type (pb1, 0));
+ printf ("MF length in pb1 : %d\n", mf_get_length (pb1, 0, true));
+ printf ("MF length with header in pb1 : %d\n", mf_get_length (pb1, 0,
+ false));
+
+ printf ("MF ats : %x\n", mf_get_ats (pb1, 0));
+
+ printf ("MF type in pb2 : %d\n", mf_get_type (pb2, 0));
+ printf ("MF length in pb2 : %d\n", mf_get_length (pb2, 0, true));
+ printf ("MF length with header in pb2 : %d\n", mf_get_length (pb2, 0,
+ false));
+ printf ("MF ats : %x\n", mf_get_ats (pb2, 0));
+ }
+
+ test_init (test, 0, NULL);
+ test_begin(test, "test MF 1, offset = 0")
+ {
+ test_fail_if (mf_get_type(pb1, 0) != type, "Type in MF 1 does not correspond");
+ test_fail_if (mf_get_length(pb1, 0, true) != length - SAR_MF_ATS_SIZE, "Payload Length in MF 1 does not correspond");
+ test_fail_if (mf_get_length(pb1, 0, false) != length + SAR_MF_MFH_SIZE + SAR_MF_ICV_SIZE, "Complete Length in MF 1 does not correspond");
+ test_fail_if (mf_get_ats(pb1, 0) != ats, "Ats does not correspond");
+ }
+ test_end;
+
+ test_begin(test, "test MF generated manualy")
+ {
+ test_fail_if (mf_get_type(pb1, 0) != mf_get_type(pb2, 0), "Type in MF 1 does not correspond with MF2 type");
+ test_fail_if (mf_get_length(pb1, 0, true) != mf_get_length(pb2, 0, true), "Length in MF 1 does not correspond with MF2 length");
+ test_fail_if (mf_get_length(pb1, 0, false) != mf_get_length(pb2, 0, false), "Length in MF 1 does not correspond with MF lentgh");
+ test_fail_if (mf_get_ats(pb1, 0) != mf_get_ats(pb1, 0), "Ats does not correspond");
+ }
+ test_end;
+
+ *(pb1->data + 511) = type_length;
+ *(pb2->data) = type_length >> 8;
+ *((u16*)(pb2->data + 1)) = ats;
+
+ test_begin(test, "test MF2, offset = 511")
+ {
+ test_fail_if (mf_get_type(pb1, 511) != 2, "Should be 0");
+ test_fail_if (mf_get_length(pb1, 511, true) != 107, "Should be 0");
+ test_fail_if (mf_get_length(pb1, 511, false) != 117, "Should be 0");
+ }
+ test_end;
+
+ // ANOTHER test.
+ length = 272 + SAR_MF_ATS_SIZE;
+ ats = 0x5678;
+ type = 2;
+
+ // MF of 283 bytes
+ *((u32*)(pb1->data)) = type | (length << 2)| (ats << 16);
+
+ // MF of 241 bytes
+ length = 230 + SAR_MF_ATS_SIZE;
+ *((u32*)(pb1->data + 283)) = type | (length << 2)| (ats << 16);
+
+ if (debug)
+ {
+ u16 offset;
+
+ offset = mf_get_length (pb1, 0, false);
+
+ printf ("/********** TEST 3 ************/\n");
+ printf ("length MF 0 : %d\n", offset);
+ printf ("length MF 2 : %d\n", mf_get_length (pb1, 283, false));
+ }
+
+ test_begin(test, "two MF followed")
+ {
+ test_fail_if (mf_get_type(pb1, 0) != type, "Type Should correspond");
+ test_fail_if (mf_get_length(pb1, 0, true) != length - 3, "Length Should correspond");
+ test_fail_if (mf_get_ats(pb1, 0) != ats, "Ats should correspond");
+
+ test_fail_if (mf_get_type(pb1, 283) != (uint) ((sar_mf_mfh_t *)(pb1->data + 283))->type, "Type Should correspond");
+ test_fail_if (mf_get_length(pb1, 283, true) != (uint) (((sar_mf_mfh_t *)(pb1->data + 283))->length + 1), "Length Should correspond");
+ test_fail_if (mf_get_ats(pb1, 283) != (uint) ((sar_mf_mfh_t *)(pb1->data + 283))->ats, "Ats should correspond");
+ }
+ test_end;
+
+ blk_release_desc ((blk_t *) pb1);
+ blk_release_desc ((blk_t *) pb2);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/sar_mfs_resising.c b/cesar/mac/sar/test/unit_test/ecos/src/sar_mfs_resising.c
new file mode 100644
index 0000000000..c2cb7a5fa5
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/sar_mfs_resising.c
@@ -0,0 +1,268 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file sar_mfs_resising.c
+ * \brief function implementations for the reassembly part
+ * \ingroup mac_sar
+ *
+ */
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+#include "mac/common/ntb.h"
+#include "mac/common/config.h"
+
+#include "mac/sar/sar.h"
+#include "mac/common/store.h"
+
+#include "hal/phy/phy.h"
+
+#include "mac/sar/test/inc/ce.h"
+#include "mac/sar/test/inc/reassembly_unit_test_functions.h"
+
+#include "mac/sar/inc/sar_pb.h"
+
+/**
+ * Test the resising of the MFS when the segment added is alone and it is the
+ * oldest pending segment in the remote STA.
+ * The reception of this one will make the MFS to release all segment it had
+ * and only take the new ones which the ssn is greater than this segment.
+ *
+ * Init :
+ * - The MFS has a ssn initialized to 63000 and is a unicast MFS kind.
+ * - The segment (PB) is initialized with a ssn value equal to 10 and has the
+ * opsf setted.
+ *
+ * Final :
+ * - The MFS should have its ssn min equal to 11, and does not contain any PB.
+ */
+void add_one_pb_to_resize (test_t test);
+
+/**
+ * Modify the window size of the MFS. Update the min ssn with the value of the
+ * ssn of the current segment when its ssn is lesser than the min ssn of the MFS.
+ *
+ * For that the MFS is a non unicast MFS.
+ * The PB is not an oldest pending segment i.e. the opsf is not setted.
+ *
+ * Init :
+ * MFS min ssn = 63000
+ * MFS windows size = 200
+ *
+ * PBs going from 0 to 5.
+ *
+ * Ending :
+ * MFS min ssn = 65536.
+ */
+void add_severals_pb_to_resize (test_t test);
+
+int main (void)
+{
+ test_t test;
+
+ trace_init();
+ test_init (test, 0, NULL);
+
+ add_one_pb_to_resize (test);
+ add_severals_pb_to_resize (test);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
+/**
+ * Test the resising of the MFS when the segment added is alone and it is the
+ * oldest pending segment in the remote STA.
+ * The reception of this one will make the MFS to release all segment it had
+ * and only take the new ones which ssn are greater than this segment.
+ *
+ * Init :
+ * - The MFS has a ssn initialized to 63000 and is not a unicast MFS kind.
+ * - The segment (PB) is initialized with a ssn value equal to 10 and has the
+ * opsf setted.
+ *
+ * Final :
+ * - The MFS should have its ssn min equal to 11, and does not contain any PB.
+ */
+void add_one_pb_to_resize (test_t test)
+{
+ pb_t *pb;
+ pbproc_rx_params_t rx_params;
+ mfs_rx_t *mfs;
+ bool added;
+ sar_t *sar_ctx;
+ mac_store_t *mac_store;
+ mac_config_t *mac_config;
+ pbproc_t *pbproc;
+ ca_t *ca;
+ phy_t *phy;
+
+ mac_store = mac_store_init ();
+ ca = blk_alloc ();
+ mac_config = blk_alloc ();
+ phy = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init (mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+ ce_init ();
+
+ sar_init_measure_context (sar_ctx, &sar_ctx);
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->header.ssn = 10;
+ pb->header.mfbf = 0;
+ pb->header.mfbo = 0;
+ pb->header.vpbf = true;
+ pb->header.opsf = true;
+
+ rx_params.lid = 0x1;
+ rx_params.tei = 0x1;
+
+ mfs = mac_store_mfs_add_rx (mac_store, true, false, 0x1, 0x1, &added);
+ dbg_assert (added);
+
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+
+ mfs->ssn_min = 63000;
+
+ sar_mpdu_add (sar_ctx, (mfs_t *) mfs, NULL, &rx_params, pb, pb, 1, NULL, 0);
+
+ sar_launch (sar_ctx);
+
+ test_begin(test, "add_one_pb_to_resize")
+ {
+ test_fail_if(mfs->ssn_min != 11, "Error on mfs resizing with one PB");
+ test_fail_if(mfs->head != NULL, "Error the mfs still contains PBs");
+ }
+ test_end;
+
+ ce_uninit ();
+
+ // release the mfs from the sar and the store.
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+
+ dbg_check (mac_store_sta_remove (mac_store, 1));
+ mac_store_uninit (mac_store);
+
+ sar_uninit (sar_ctx);
+ pbproc_uninit (pbproc);
+ mac_ntb_uninit ();
+
+ blk_release (ca);
+ blk_release (mac_config);
+ blk_release (phy);
+ blk_release (mfs);
+}
+
+/**
+ * Modify the window size of the MFS. Update the min ssn with the value of the
+ * ssn of the current segment when its ssn is lesser than the min ssn of the MFS.
+ *
+ * For that the MFS is a non unicast MFS.
+ * The PB is not an oldest pending segment i.e. the opsf is not setted.
+ *
+ * Init :
+ * MFS min ssn = 63000
+ * MFS windows size = 200
+ *
+ * PBs going from 0 to 5.
+ *
+ * Ending :
+ * MFS min ssn = 65340.
+ */
+void add_severals_pb_to_resize (test_t test)
+{
+ pb_t *pb;
+ pb_t *first;
+ pb_t *last;
+ pbproc_rx_params_t rx_params;
+ mfs_rx_t *mfs;
+ int i;
+ bool added;
+ sar_t *sar_ctx;
+ mac_store_t *mac_store;
+ mac_config_t *mac_config;
+ pbproc_t *pbproc;
+ ca_t *ca;
+
+ ce_init ();
+
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+ pbproc = pbproc_init (mac_config, mac_store);
+ ca = blk_alloc ();
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ sar_init_measure_context (sar_ctx, &sar_ctx);
+ sar_init_measurement_cb (sar_ctx, ce_measurements);
+
+ first = (pb_t *) blk_alloc_desc_range (5, (blk_t **) &last);
+ last->next = NULL;
+
+ for (pb = first, i = 0; pb != NULL; pb = pb->next, i++)
+ {
+ pb->header.ssn = i;
+ pb->header.mfbf = 0;
+ pb->header.mfbo = 0;
+ pb->header.vpbf = true;
+ pb->header.opsf = false;
+ }
+
+ rx_params.lid = 0x1;
+ rx_params.tei = 0x1;
+
+ mfs = mac_store_mfs_add_rx (mac_store, true, false, 0x1, 0x1, &added);
+ dbg_assert (added);
+
+ sar_mfs_add (sar_ctx, (mfs_t *) mfs);
+
+ mfs->ssn_min = 63000;
+
+ sar_mpdu_add (sar_ctx, (mfs_t *) mfs, NULL, &rx_params, first, last, 5,
+ NULL, 0);
+
+ sar_launch (sar_ctx);
+
+ test_begin(test, "add_severals_pb_to_resize")
+ {
+ test_fail_if(mfs->ssn_min != 65524, "Error on mfs resizing with severals PB");
+ }
+ test_end;
+
+ if (mfs->head)
+ {
+ pb_free_range (mfs->head);
+ mfs->head = NULL;
+ }
+
+ ce_uninit ();
+ /** release the mfs from the sar and the store. */
+ sar_mfs_remove (sar_ctx, (mfs_t *) mfs);
+
+ sar_uninit (sar_ctx);
+ blk_release (mac_config);
+ blk_release (ca);
+ pbproc_uninit (pbproc);
+
+ dbg_assert (mac_store_sta_remove (mac_store, 1));
+ mac_store_uninit (mac_store);
+ blk_release (mfs);
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/segmentation_complete.c b/cesar/mac/sar/test/unit_test/ecos/src/segmentation_complete.c
new file mode 100644
index 0000000000..de605965fa
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/segmentation_complete.c
@@ -0,0 +1,486 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file segmentation_complete.c
+ * \brief test the complete segmentation module
+ * \ingroup mac/sar/test/segementation_complete/src/
+ */
+
+#include "common/std.h"
+#include "mac/sar/sar.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+#include "mac/common/store.h"
+#include "mac/common/ntb.h"
+
+#include "hal/phy/phy.h"
+
+#include "mac/sar/bridgedma/inc/bridge.h"
+#include "mac/sar/test/inc/eth_packets.h"
+#include "mac/sar/inc/sar_pb.h"
+#include "mac/sar/inc/sar_mf.h"
+
+/* Only use to modify the current date of the phy */
+#include "mac/sar/inc/sar_context.h"
+
+void segmentation_complete_init (test_t test);
+void segmentation_complete_exiting (void);
+void segmentation_process (test_t test);
+int verify_test_failed (test_t test);
+
+void sar_segmentation_done (void *user, u8* buffer)
+{
+
+}
+
+sar_t *sar_ctx;
+mac_store_t *mac_store;
+mac_config_t *mac_config;
+pbproc_t *pbproc;
+ca_t *ca;
+phy_t *phy;
+
+void this_test_init (void)
+{
+ mac_store = mac_store_init ();
+ mac_config = blk_alloc ();
+ ca = blk_alloc ();
+ phy = blk_alloc ();
+
+ mac_ntb_init (phy, mac_config);
+ pbproc = pbproc_init (mac_config, mac_store);
+ sar_ctx = sar_init (mac_store, pbproc, ca);
+
+ /* Data */
+ sar_init_data_context (sar_ctx, sar_ctx);
+ sar_init_mme_context (sar_ctx, sar_ctx);
+
+ sar_init_segmentation_data_cb (sar_ctx, sar_segmentation_done);
+ sar_init_segmentation_mme_cb (sar_ctx, sar_segmentation_done);
+
+ mac_store_sta_add (mac_store, 0x1);
+}
+
+void this_test_uninit (void)
+{
+ sar_uninit (sar_ctx);
+ dbg_check (mac_store_sta_remove (mac_store, 0x1));
+ mac_store_uninit (mac_store);
+ pbproc_uninit (pbproc);
+ mac_ntb_uninit();
+ blk_release (mac_config);
+ blk_release (ca);
+ blk_release (phy);
+}
+
+void mfs_type1 (test_t test)
+{
+ mfs_tx_t *data_mfs;
+ bool added;
+ uint cpt;
+ uint pb_nb;
+ uint length;
+
+ this_test_init ();
+
+ /** Add the mfs for the test. */
+ data_mfs = mac_store_mfs_add_tx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ /**The test starts here*/
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) (u8 *) packet3, packet3_len, 0x12345678,
+ data_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ pb_nb = mf_get_quantity_of_pb (data_mfs->head, 0);
+ length = mf_get_length (data_mfs->head, 0, true);
+
+ for (cpt = 0; data_mfs->head; cpt++)
+ {
+ data_mfs->head = pb_free (data_mfs->head);
+ }
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (cpt != pb_nb, "Wrong quantity of PBs");
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) data_mfs);
+
+ blk_release (data_mfs);
+
+ this_test_uninit ();
+}
+
+void mfs_type2 (test_t test)
+{
+ mfs_tx_t *data_mfs;
+ bool added;
+ uint cpt;
+ uint pb_nb;
+ uint length;
+
+ this_test_init ();
+
+ /** Add the mfs for the test. */
+ data_mfs = mac_store_mfs_add_tx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ data_mfs->common.ats = true;
+
+ /**The test starts here*/
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, data_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ pb_nb = mf_get_quantity_of_pb (data_mfs->head, 0);
+ length = mf_get_length (data_mfs->head, 0, true);
+
+ for (cpt = 0; data_mfs->head; cpt++)
+ {
+ data_mfs->head = pb_free (data_mfs->head);
+ }
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (cpt != pb_nb, "Wrong quantity of PBs");
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) data_mfs);
+
+ blk_release (data_mfs);
+
+ this_test_uninit ();
+}
+
+void mfs_type3 (test_t test)
+{
+ mfs_tx_t *mme_mfs;
+ bool added;
+ uint cpt;
+ uint pb_nb;
+ uint length;
+
+ this_test_init ();
+
+ mme_mfs = mac_store_mfs_add_tx (mac_store, false, true, MAC_LID_NONE, 1,
+ &added);
+ dbg_assert (added);
+
+ /**The test starts here*/
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ pb_nb = mf_get_quantity_of_pb (mme_mfs->head, 0);
+ length = mf_get_length (mme_mfs->head, 0, true);
+
+ for (cpt = 0; mme_mfs->head; cpt++)
+ {
+ mme_mfs->head = pb_free (mme_mfs->head);
+ }
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (cpt != pb_nb, "Wrong quantity of PBs");
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) mme_mfs);
+ blk_release (mme_mfs);
+
+ this_test_uninit ();
+}
+
+void mfs_type1_two_MF (test_t test)
+{
+ mfs_tx_t *data_mfs;
+ bool added;
+ uint pb_nb;
+ uint length;
+
+ this_test_init ();
+
+ /** Add the mfs for the test. */
+ data_mfs = mac_store_mfs_add_tx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ /**The test starts here*/
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, data_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, data_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ pb_nb = mf_get_quantity_of_pb (data_mfs->head, 0);
+ length = mf_get_length (data_mfs->head, 0, true);
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ length = mf_get_length (data_mfs->head, 0, true);
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ pb_free_range (data_mfs->head);
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) data_mfs);
+
+ blk_release (data_mfs);
+
+ this_test_uninit ();
+}
+
+void mfs_type2_two_MF (test_t test)
+{
+ mfs_tx_t *data_mfs;
+ bool added;
+ uint length;
+
+ this_test_init ();
+
+ /** Add the mfs for the test. */
+ data_mfs = mac_store_mfs_add_tx (mac_store, false, false, 1, 1, &added);
+ dbg_assert (added);
+
+ data_mfs->common.ats = true;
+
+ /**The test starts here*/
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, data_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, data_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ length = mf_get_length (data_mfs->head, 0, true);
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ length = mf_get_length (data_mfs->head, 0, true);
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ pb_free_range (data_mfs->head);
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) data_mfs);
+
+ blk_release (data_mfs);
+
+ this_test_uninit ();
+}
+
+void mfs_type3_two_MF (test_t test)
+{
+ mfs_tx_t *mme_mfs;
+ bool added;
+ uint length;
+
+ this_test_init ();
+
+ mme_mfs = mac_store_mfs_add_tx (mac_store, false, true, MAC_LID_NONE, 1,
+ &added);
+ dbg_assert (added);
+
+ /**The test starts here*/
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ length = mf_get_length (mme_mfs->head, 0, true);
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ pb_free_range (mme_mfs->head);
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) mme_mfs);
+ blk_release (mme_mfs);
+
+ this_test_uninit ();
+}
+
+/* It will put the last offset processed of the MFS to the BLK_SIZE value. */
+void mfs_type4_three_MF (test_t test)
+{
+ mfs_tx_t *mme_mfs;
+ bool added;
+ uint length;
+
+ this_test_init ();
+
+ mme_mfs = mac_store_mfs_add_tx (mac_store, false, true, MAC_LID_NONE, 1,
+ &added);
+ dbg_assert (added);
+
+ /**The test starts here*/
+ mme_mfs->last_seg_offset = BLK_SIZE;
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+ /** Add the msdu to the sar. */
+ sar_msdu_add (sar_ctx, (u8 *) packet3, packet3_len, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+ sar_msdu_add (sar_ctx, (u8 *) packet3, 60, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+ sar_msdu_add (sar_ctx, (u8 *) packet3, 110, 0x12345678, mme_mfs);
+ /** Launch the sar with this msdu. */
+ sar_launch (sar_ctx);
+
+
+ /** Launch the ending processus for the bridge dma. */
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+ sar_launch (sar_ctx);
+
+ /** Check the mfs state. */
+
+ length = mf_get_length (mme_mfs->head, 0, true);
+
+ test_begin (test, "mfs tx state")
+ {
+ test_fail_if (length != packet3_len, "wrong length");
+ }
+ test_end;
+
+ pb_free_range (mme_mfs->head);
+
+ /** Remove the mfs from the test. */
+ mac_store_mfs_remove (mac_store, (mfs_t *) mme_mfs);
+ blk_release (mme_mfs);
+
+ this_test_uninit ();
+}
+
+int main (void)
+{
+ test_t test;
+
+ trace_init ();
+ test_init (test, 0, NULL);
+
+ mfs_type1 (test);
+ mfs_type2 (test);
+ mfs_type3 (test);
+
+ mfs_type1_two_MF (test);
+ mfs_type2_two_MF (test);
+ mfs_type3_two_MF (test);
+ mfs_type4_three_MF (test);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/test-segmentation-provide-pb.c b/cesar/mac/sar/test/unit_test/ecos/src/test-segmentation-provide-pb.c
new file mode 100644
index 0000000000..23e8b001f1
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/test-segmentation-provide-pb.c
@@ -0,0 +1,129 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test-segmentation-provide-pb.c
+ * \brief Test segmentation.
+ * \ingroup mac_sar
+ *
+ * This test will test the providing of PBs when a segmentation of some frames
+ * are requested in a same MFS.
+ */
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+
+#include "lib/test.h"
+
+#include "mac/common/ntb.h"
+
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/sar_context.h"
+
+void
+sar_seg_done (void *user_data, u8 *buffer)
+{
+}
+
+int
+main (void)
+{
+ test_t test;
+ u8 buffer[2048];
+ uint list[4];
+ uint i;
+
+ mac_config_t mac_config;
+
+ sar_t *sar;
+ pbproc_t *pbproc;
+ ca_t *ca;
+ phy_t *phy;
+
+ mfs_tx_t *mfs;
+ mac_store_t *mac_store;
+
+ test_init (test, 0, NULL);
+
+ mfs = blk_alloc ();
+ phy = blk_alloc ();
+ ca = blk_alloc ();
+
+ mfs_tx_init (mfs, false, false, 1, 1);
+ mfs->common.ats = true;
+
+ mac_config_init (&mac_config);
+ mac_store = mac_store_init ();
+ pbproc = pbproc_init (&mac_config, mac_store);
+ mac_ntb_init (phy, &mac_config);
+ sar = sar_init (mac_store, pbproc, ca);
+
+ sar_init_data_context (sar, NULL);
+ sar_init_segmentation_data_cb (sar, sar_seg_done);
+ sar_init_segmentation_mme_cb (sar, sar_seg_done);
+
+ list[0] = 1024 - 10;
+ list[1] = 224 - 10;
+ list[2] = 700 - 10;
+ list[3] = 1024 - 10;
+
+ test_begin (test, "Verifying the MFS state")
+ {
+ for (i = 0; i < 4; i++)
+ {
+ /* Add a msdu to the sar. */
+ sar_msdu_add (sar, buffer, list[i], 0x12345678, mfs);
+ sar_launch (sar);
+
+ /* Launch the segementation. */
+ sar_launch (sar);
+ sar_launch (sar);
+
+ switch (i)
+ {
+ case 0:
+ test_fail_if (mfs->seg_nb != 3, "Wrong seg nb, shall be 3 and have : %d", mfs->seg_nb);
+ test_fail_if (mfs->pending_seg_nb != 0, "Wrong seg nb pending");
+ break;
+ case 1:
+ test_fail_if (mfs->seg_nb != 3, "Wrong seg nb, shall be 3 and have : %d", mfs->seg_nb);
+ test_fail_if (mfs->pending_seg_nb != 0, "Wrong seg nb pending");
+ break;
+ case 2:
+ test_fail_if (mfs->seg_nb != 4, "Wrong seg nb, shall be 3 and have : %d", mfs->seg_nb);
+ test_fail_if (mfs->pending_seg_nb != 0, "Wrong seg nb pending");
+ break;
+ case 3:
+ test_fail_if (mfs->seg_nb != 6, "Wrong seg nb, shall be 3 and have : %d", mfs->seg_nb);
+ test_fail_if (mfs->pending_seg_nb != 0, "Wrong seg nb pending");
+ break;
+
+ }
+ }
+ }
+ test_end;
+
+ /* Free the PBs in the MFS. */
+ pb_free_range (mfs->head);
+
+ blk_release (mfs);
+ blk_release (phy);
+ blk_release (ca);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/ecos/src/test_store_memory.c b/cesar/mac/sar/test/unit_test/ecos/src/test_store_memory.c
new file mode 100644
index 0000000000..a343e6292a
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/ecos/src/test_store_memory.c
@@ -0,0 +1,46 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file test_store_memory.c
+ * \brief test the store allocation memory
+ * \ingroup mac/common/test
+ *
+ */
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/kernel/kapi.h>
+
+#include "common/std.h"
+#include "mac/common/store.h"
+#include "lib/test.h"
+#include "lib/blk.h"
+
+int cyg_user_start (void)
+{
+ test_t test;
+ mac_store_t *mac_store;
+
+ test_init(test, 0, NULL);
+
+ mac_store = mac_store_init();
+
+ mac_store_sta_add(mac_store, 1);
+
+ dbg_check(mac_store_sta_remove(mac_store, 1));
+ mac_store_uninit(mac_store);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/host/Makefile b/cesar/mac/sar/test/unit_test/host/Makefile
new file mode 100644
index 0000000000..5e1adb893d
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/host/Makefile
@@ -0,0 +1,17 @@
+BASE = ../../../../../
+
+HOST_PROGRAMS = bridgedma_list lib_sar_mf \
+ test_store_memory
+
+test_store_memory_SOURCES = test_store_memory.c phy_stub.c
+test_store_memory_MODULES = lib mac/common
+
+mac_sar_MODULE_SOURCES = bridge_dma.c sar_mf.c
+
+bridgedma_list_SOURCES = bridgedma_list.c phy_stub.c
+bridgedma_list_MODULES = lib mac/sar
+
+lib_sar_mf_SOURCES = lib_sar_mf.c phy_stub.c
+lib_sar_mf_MODULES = lib mac/sar
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/mac/sar/test/unit_test/host/src/bridgedma_list.c b/cesar/mac/sar/test/unit_test/host/src/bridgedma_list.c
new file mode 100644
index 0000000000..81808e9fc0
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/host/src/bridgedma_list.c
@@ -0,0 +1,87 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bridgedma_list.c
+ * \brief Test all the functions of the bridgedma list lib
+ * \ingroup mac/sar/test/unit_test/lib_sar_test
+ *
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+
+#include "mac/sar/inc/bridge_dma.h"
+
+int main (void)
+{
+ sar_bridge_dma_list_t list;
+ sar_job_mfs_t *job;
+ sar_job_mfs_t *job2;
+ test_t test;
+
+ test_init (test, 0, NULL);
+
+ /* Initialize the list */
+ bridge_dma_list_init (&list);
+
+ test_begin (test, "list initialization")
+ {
+ test_fail_if (list.head != NULL, "list not initialized head not null");
+ test_fail_if (list.tail != NULL, "list not initialized tail not null");
+ }
+ test_end;
+
+ /* Add two jobs to the list */
+ job = (sar_job_mfs_t *) blk_alloc ();
+ job->next = NULL;
+ job->mfs = blk_alloc ();
+ job->job.first_pb_desc = blk_alloc_desc ();
+ job->job.first_pb_desc->next = NULL;
+
+ job2 = (sar_job_mfs_t *) blk_alloc ();
+ job2->next = NULL;
+ job2->mfs = blk_alloc ();
+ job2->job.first_pb_desc = blk_alloc_desc ();
+ job2->job.first_pb_desc->next = NULL;
+
+ bridge_dma_add_pending_job (&list, job);
+ bridge_dma_add_pending_job (&list, job2);
+
+ test_begin (test, "list initialization")
+ {
+ test_fail_if (list.head == NULL, "list not initialized head not null");
+ test_fail_if (list.tail == NULL, "list not initialized tail not null");
+ }
+ test_end;
+
+ /* Verify if the list is empty */
+ test_begin (test, "list is empty")
+ {
+ test_fail_if (bridge_dma_list_is_empty (&list) != false, "list is not empty");
+ }
+ test_end;
+
+ /* Free the jobs */
+ bridge_dma_uninit_list (&list);
+
+ test_begin (test, "list uninitialization")
+ {
+ test_fail_if (list.head != NULL, "list not uninitialized head not null");
+ test_fail_if (list.tail != NULL, "list not uninitialized tail not null");
+ }
+ test_end;
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/host/src/lib_buffer_address_list.c b/cesar/mac/sar/test/unit_test/host/src/lib_buffer_address_list.c
new file mode 100644
index 0000000000..39b031386e
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/host/src/lib_buffer_address_list.c
@@ -0,0 +1,123 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file buffer_address_list.c
+ * \brief Test of the buffer address list function for the SAR
+ * \ingroup mac/sar/test/unit_test/lib_sar_test
+ *
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "mac/sar/inc/buffer_address_list.h"
+
+struct test_list
+{
+ buffer_address_list_t list;
+ u8 *list_toto[2];
+};
+typedef struct test_list test_list;
+
+int main (void)
+{
+ test_t test;
+ u8 *addr;
+
+ test_list list;
+
+ test_init (test, 0, NULL);
+
+ /* Init the list */
+ buffer_address_init (&list.list, 2);
+
+ test_begin (test, "list initialization")
+ {
+ test_fail_if (list.list.curr_slot != 0, "list not initialized");
+ test_fail_if (list.list.next_slot != 0, "list not initialized");
+ test_fail_if (list.list.slots[0] != 0, "list not initialized");
+ test_fail_if (list.list.slots[1] != 0, "list not initialized");
+ }
+ test_end;
+
+ /* Add an address to the buffer */
+ buffer_address_list_add (&list.list, (u8*) &list.list, 2);
+
+ test_begin (test, "test a add in the address list.list")
+ {
+ test_fail_if (list.list.curr_slot != 0, "no address was peeked");
+ test_fail_if (list.list.next_slot != 1, "The next slot is not 1");
+ }
+ test_end;
+
+ /* reset the counter */
+ buffer_address_list_add (&list.list, (u8*) &list, 2);
+
+ test_begin (test, "test a add in the address list.list")
+ {
+ test_fail_if (list.list.curr_slot != 0, "no address was peeked");
+ test_fail_if (list.list.next_slot != 0, "the next_slot counter is had not been reseted");
+ }
+ test_end;
+
+ /* peek an address */
+ addr = buffer_address_list_peek (&list.list);
+
+ test_begin (test, "peek an address from the list.list")
+ {
+ test_fail_if (addr != (u8*) &list.list, "The address peeked does not correspond");
+ }
+ test_end;
+
+ /* Get an address */
+ addr = buffer_address_list_get (&list.list, 2);
+
+ test_begin (test, "test get an address from the list.list")
+ {
+ test_fail_if (list.list.curr_slot != 1, "no address was token");
+ test_fail_if (list.list.next_slot != 0, "the next_slot counter had not been reseted");
+ }
+ test_end;
+
+ /* get the second one */
+ addr = buffer_address_list_get (&list.list, 2);
+
+ test_begin (test, "test get an address from the list.list")
+ {
+ test_fail_if (list.list.curr_slot != 0, "no address was token");
+ test_fail_if (list.list.next_slot != 0, "the next_slot counter is had not been reseted");
+ }
+ test_end;
+
+ /* try to get one */
+ addr = buffer_address_list_get (&list.list, 2);
+
+ test_begin(test, "test to get an empty address")
+ {
+ test_fail_if (addr != NULL, "Address took when no one was available");
+ }
+ test_end;
+
+ /* Reinitialize the list.list */
+ buffer_address_init (&list.list, 2);
+
+ test_begin (test, "Try to add more address when list.list is full")
+ {
+ test_fail_if (buffer_address_list_add (&list.list, (u8*) &list.list, 2) != true, "Addr should be added");
+ test_fail_if (buffer_address_list_add (&list.list, (u8*) &list.list, 2) != true, "Addr should be added");
+ test_fail_if (buffer_address_list_add (&list.list, (u8*) &list.list, 2) != false, "Addr should not be added");
+
+ addr = buffer_address_list_get (&list.list, 2);
+ test_fail_if (addr == NULL, "Should take an address");
+ test_fail_if (list.list.slots[list.list.curr_slot-1] != 0x0, "Error value taken without putting a zero value");
+ test_fail_if (buffer_address_list_add (&list.list, (u8*) &list.list, 2) != true, "Addr should be added");
+ }
+ test_end;
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/host/src/lib_sar_mf.c b/cesar/mac/sar/test/unit_test/host/src/lib_sar_mf.c
new file mode 100644
index 0000000000..ca2190e87a
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/host/src/lib_sar_mf.c
@@ -0,0 +1,198 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file lib_sar_mf.c
+ * \brief test the whole sar_mf.c source
+ * \ingroup mac/sar/test/unit_test/lib_sar_test
+ *
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/read_word.h"
+#include "lib/bitstream.h"
+
+#include "mac/sar/inc/sar_mf.h"
+#include <stdio.h>
+#include <string.h>
+
+int main (void)
+{
+ bitstream_t bitstream;
+ test_t test;
+ uint mft;
+ uint length;
+ uint ats;
+ pb_t *pb;
+
+ test_init (test, 0, NULL);
+
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->next = NULL;
+ pb->header.ssn = 0;
+ pb->header.vpbf = true;
+ pb->header.mfbf = true;
+ pb->header.mfbo = 0x10;
+
+ /* fill the pb */
+ mft = 2;
+ length = 105 + SAR_MF_ATS_SIZE;
+ ats = 0x0;
+
+ bitstream_init (&bitstream, pb->data + 0x10, 6, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &mft, 2);
+ bitstream_access (&bitstream, &length, 14);
+ bitstream_access (&bitstream, &ats, 32);
+ bitstream_finalise (&bitstream);
+
+ test_begin (test, "MF")
+ {
+ test_fail_if (mf_get_type(pb, pb->header.mfbo) != 2, "wrong MF type");
+ test_fail_if (mf_get_length(pb, pb->header.mfbo, false) != 116, "wrong length for the complete MF");
+ test_fail_if (mf_get_length(pb, pb->header.mfbo, true) != 106, "wrong length for the payload");
+ test_fail_if (mf_get_quantity_of_pb(pb, pb->header.mfbo) != 1, "wrong quantity of PB");
+ test_fail_if (mf_get_ats (pb, pb->header.mfbo) != 0x0, "wrong ats");
+ }
+ test_end;
+
+ /* fill the pb */
+ mft = 0;
+ length = 0;
+ ats = 0x0;
+
+ bitstream_init (&bitstream, pb->data + 0x10, 6, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &mft, 2);
+ bitstream_access (&bitstream, &length, 14);
+ bitstream_access (&bitstream, &ats, 32);
+ bitstream_finalise (&bitstream);
+
+ test_begin (test, "No MF")
+ {
+ test_fail_if (mf_get_type(pb, pb->header.mfbo) != 0, "wrong MF type");
+ test_fail_if (mf_get_length(pb, pb->header.mfbo, false) != 0, "wrong length for the complete MF");
+ test_fail_if (mf_get_length(pb, pb->header.mfbo, true) != 0, "wrong length for the payload");
+ test_fail_if (mf_get_quantity_of_pb(pb, pb->header.mfbo) != 0, "wrong quantity of PB");
+ test_fail_if (mf_get_ats (pb, pb->header.mfbo) != 0x0, "wrong ats");
+ }
+ test_end;
+
+ /* fill the pb */
+ mft = 1;
+ length = 105;
+ ats = 0x0;
+
+ bitstream_init (&bitstream, pb->data + 0x10, 6, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &mft, 2);
+ bitstream_access (&bitstream, &length, 14);
+ bitstream_access (&bitstream, &ats, 32);
+ bitstream_finalise (&bitstream);
+
+ test_begin (test, "MF of type 1")
+ {
+ test_fail_if (mf_get_type(pb, pb->header.mfbo) != 1, "wrong MF type");
+ test_fail_if (mf_get_length(pb, pb->header.mfbo, false) != 112, "wrong length for the complete MF");
+ test_fail_if (mf_get_length(pb, pb->header.mfbo, true) != 106, "wrong length for the payload");
+ test_fail_if (mf_get_quantity_of_pb(pb, pb->header.mfbo) != 1, "wrong quantity of PB");
+ test_fail_if (mf_get_ats (pb, pb->header.mfbo) != 0x0, "wrong ats");
+ }
+ test_end
+
+ /* test the offset position
+ * try to obtain the ATS from a PB with a MF which starts at 511 */
+ pb->next = (pb_t *) blk_alloc_desc();
+ pb->next->next = NULL;
+
+ *(uint*) (pb->data + 508) = 0xCA000000;
+ *(uint*) (pb->next->data) = 0x34567801;
+ *(uint*) (pb->next->data + 4) = 0x12;
+
+
+ test_begin (test, "get the ATS from the offset 511")
+ {
+ test_fail_if (mf_get_ats(pb, 511) != 0x12345678, "wrong ATS");
+ test_fail_if (mf_get_length(pb, 511, true) != 111, "wrong length");
+ }
+ test_end;
+
+ *(uint*) (pb->data + 500) = 0xCA000000;
+ *(uint*) (pb->data + 504) = 0x34567801;
+ *(uint*) (pb->data + 508) = 0x12;
+
+ test_begin (test, "get the ATS from the offset 511")
+ {
+ test_fail_if (mf_get_ats(pb, 503) != 0x12345678, "wrong ATS");
+ test_fail_if (mf_get_length(pb, 503, true) != 111, "wrong length");
+ }
+ test_end;
+
+ *(uint*) (pb->data + 508) = 0x7801CA00;
+ *(uint*) (pb->next->data) = 0x123456;
+
+
+ test_begin (test, "get the ATS from the offset 511")
+ {
+ test_fail_if (mf_get_ats(pb, 509) != 0x12345678, "wrong ATS");
+ test_fail_if (mf_get_length(pb, 509, true) != 111, "wrong length");
+ }
+ test_end;
+
+ blk_release_desc ((blk_t *) pb->next);
+
+ pb->next = NULL;
+ test_begin (test, "get the ATS from the offset 511 and no more pb available")
+ {
+ test_fail_if (mf_get_ats(pb, 509) != 0, "wrong ATS");
+ test_fail_if (mf_get_length(pb, 509, true) != 111, "wrong length");
+ }
+ test_end;
+
+ test_begin (test, "get no length cause PB is null")
+ {
+ test_fail_if (mf_get_length (pb, 0, true) != 0, "wrong MF type");
+ }
+ test_end;
+
+ test_begin (test, "get no length cause PB is not null and length in two PB")
+ {
+ test_fail_if (mf_get_length (pb, 511, true) != 0, "wrong MF type");
+ }
+ test_end;
+
+ blk_release_desc ((blk_t *) pb);
+
+
+ /* Try to read ats */
+
+ pb = (pb_t *) blk_alloc_desc ();
+ pb->next = (pb_t *) blk_alloc_desc ();
+ pb->next->next = NULL;
+
+ mft = 2;
+ length = 105;
+ ats = 0x12345678;
+
+ bitstream_init (&bitstream, pb->data + 511, 1, BITSTREAM_WRITE);
+ bitstream_access (&bitstream, &mft, 2);
+ bitstream_access (&bitstream, &length, 6);
+ bitstream_finalise (&bitstream);
+
+ bitstream_direct_write (pb->next->data, 6, length, 8);
+
+
+ blk_release_desc ((blk_t *) pb->next);
+ blk_release_desc ((blk_t *) pb);
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/mac/sar/test/unit_test/host/src/phy_stub.c b/cesar/mac/sar/test/unit_test/host/src/phy_stub.c
new file mode 100644
index 0000000000..0141b73f5f
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/host/src/phy_stub.c
@@ -0,0 +1,24 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cl/test/src/phy_stub.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+
+#include "hal/phy/phy.h"
+
+u32
+phy_date (phy_t *ctx)
+{
+ return 42;
+}
+
diff --git a/cesar/mac/sar/test/unit_test/host/src/test_store_memory.c b/cesar/mac/sar/test/unit_test/host/src/test_store_memory.c
new file mode 100644
index 0000000000..948de197a3
--- /dev/null
+++ b/cesar/mac/sar/test/unit_test/host/src/test_store_memory.c
@@ -0,0 +1,44 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file test_store_memory.c
+ * \brief test the store allocation memory
+ * \ingroup mac/common/test
+ *
+ */
+
+#include "common/std.h"
+#include "mac/common/store.h"
+#include "lib/test.h"
+#include "lib/blk.h"
+
+int main (void)
+{
+ test_t test;
+ mac_store_t *mac_store;
+
+ test_init(test, 0, NULL);
+
+ mac_store = mac_store_init();
+
+ mac_store_sta_add(mac_store, 1);
+
+ dbg_assert(mac_store_sta_remove(mac_store, 1));
+ mac_store_uninit(mac_store);
+
+ blk_print_memory();
+
+ test_begin (test, "Memory test")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}