summaryrefslogtreecommitdiff
path: root/cesar/cp2/cl_interf/src/cl_interf.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cp2/cl_interf/src/cl_interf.c')
-rw-r--r--cesar/cp2/cl_interf/src/cl_interf.c442
1 files changed, 278 insertions, 164 deletions
diff --git a/cesar/cp2/cl_interf/src/cl_interf.c b/cesar/cp2/cl_interf/src/cl_interf.c
index 60a580bfd8..99a1d0a4ea 100644
--- a/cesar/cp2/cl_interf/src/cl_interf.c
+++ b/cesar/cp2/cl_interf/src/cl_interf.c
@@ -6,211 +6,325 @@
*
* }}} */
/**
- * \file cp2\cl_interf\src\cl_interf.c
- * \brief « brief description »
- * \ingroup « module »
+ * \file cp2/cl_interf/src/cl_interf.c
+ * \brief Cl Interface source.
+ * \ingroup cp2_cl_interf
*
- * « long description »
*/
-
#include "common/std.h"
-#include "cp2/mme.h"
-#include "cp2/cl_interf/cl_interf.h"
+#include "common/defs/ethernet.h"
+#include "lib/read_word.h"
+#include "lib/blk.h"
+#include "cp2/cp.h"
+#include "cp2/defs.h"
-// mbox for incomming msg
-static cyg_handle_t m_incoming_mbox_handle;
-static cyg_mbox m_incoming_mbox;
-static cp_t *m_cp_ctx = NULL;
+#include "interface/interface.h"
+#include "cp2/cl_interf/cl_interf.h"
+#include "cp2/msg/msg.h"
+
+#include "cp2/inc/context.h"
+#include "cp2/cl_interf/inc/context.h"
+#include "cp2/cl_interf/inc/cl_interf.h"
+#include "cp2/cl_interf/inc/cl_interf_msg.h"
/**
- * initialisation of cp_cl_interf module.
- *
- * \param ctx the cp context
- *
- * register callbacks in DP/CL module,
- * clear buffers etc.
- *
+ * Initialise the module.
+ * \param ctx the module context.
+ *
*/
void
-cp_cl_interf_init(cp_t *ctx)
+cp_cl_interf_init (cp_t *ctx)
{
- cyg_mbox_create( & m_incoming_mbox_handle, & m_incoming_mbox);
- m_cp_ctx = ctx;
+ dbg_assert (ctx);
+
+ // Initialise the circular list.
+ circular_buffer_init (&ctx->cl_interf.buffer_tx_list,
+ ctx->cl_interf.list,
+ CP_CL_INTERF_LIST_SIZE);
+
+ // Create the mailbox.
+ cyg_mbox_create(&ctx->cl_interf.mailbox_handle,
+ &ctx->cl_interf.mme_rx_mailbox);
+
+ // Create the semaphore.
+ cyg_semaphore_init (&ctx->cl_interf.buffer_list_sem, 0);
+
+ // Initialise the call backs.
+ interface_callback_init (ctx->interface,
+ (interface_mme_recv_cb_t) cp_cl_interf_rx_mme,
+ (interface_mme_buffer_add_cb_t)
+ cp_cl_interf_add_buffer_tx,
+ ctx);
}
/**
- * callback for Rx MME.
- *
- * \param ctx the cp context
- * \param payload the mme itself
- * \param payload_size size of the payload
- * \param mfs the receiving mfs
- * \param hardware_encrypted set to true if the mme was hardwarely encrypted
- *
- * !!! this function is executed in the CL context !!!
- * 1) push the message in the MMEs fifo
- * 2) set the flag to unlock the station core
+ * Uninitialise the module.
+ * \param ctx the module context.
+ *
*/
void
-cp_cl_interf_rx_mme(
- void *user,
- mfs_rx_t *mfs,
- u8 *buffer,
- uint length,
- cl_mme_recv_t *mme_recv,
- bool encryption
- )
+cp_cl_interf_uninit (cp_t *ctx)
{
- cp_mme_rx_t *cp_mme_rx = NULL;
-
- dbg_assert(msf);
- dbg_assert(buffer);
- dbg_assert(mme_recv);
-
- // TODO change the malloc with the slab allocator
- cp_mme_rx = malloc(sizeof(cp_mme_rx_t));
- dbg_assert(cp_mme_rx);
-
-
- cp_mme_rx->p_mme = buffer;
- cp_mme_rx->p_frag = NULL;
- cp_mme_rx->length = length;
- cp_mme_rx->mfs = mfs;
- cp_mme_rx->hw_encrypted = encryption;
-
- #if DEBUG
- dbg_assert(cyg_mbox_tryput(m_incoming_mbox_handle, (void *) cp_mme_rx));
- #else
- cyg_mbox_put (m_incoming_mbox_handle, (void *) cp_mme_rx);
- #endif
- // set the event flag for the station
- // TODO use the station's module API
- cyg_flag_setbits (&station_flag, STATION_FLAG_MSG_RCV);
+ cp_cl_interf_t *msg;
+ dbg_assert (ctx);
+
+ while (cyg_mbox_peek (ctx->cl_interf.mailbox_handle))
+ {
+ msg = cyg_mbox_get (ctx->cl_interf.mailbox_handle);
+ blk_release (msg);
+ }
+
+ // Delete the mailbox.
+ cyg_mbox_delete (ctx->cl_interf.mailbox_handle);
+
+ // Delete the semaphore.
+ cyg_semaphore_destroy (&ctx->cl_interf.buffer_list_sem);
}
/**
- * return the last received and completed mme.
- *
- * \param ctx the cp context
- * \return mme_rx_t the mme context (for unit test purpose only)
- *
- * 1) get the last MME from the MMEs fifo
- * 2) read the MME's header and store it in a newly allocated MME Tx context
- * 3) check the ODA, and the MME constants
- * 4) if it is a fragment from a bigger MME
- * - update the MME context
- * - copy the payload in 512 byte blocs
- * 5) if the message is completed, call the msg_dispatch function
+ * Process the MME received.
+ * \param ctx the module context.
+ *
+ * It shall use the MSG function to read the header and get a mme_rx_t
+ * context.
+ * - If the MME is complete, it process it and store the data need in
+ * the mme_rx_t context and call the MSG dispatch function.
+ * - if the MMe is fragmented, it shall verify if the segment has not
+ * already been process.
+ * * if it was process, it shall drop it.
+ * * If not, process it
*/
-cp_mme_rx_t *
-cp_cl_interf_give_last_mme(cp_t *ctx)
+void
+cp_cl_interf_process_mme (cp_t *ctx)
{
- u16 tmp;
- bool check_mme_ok = true;
- cp_mme_rx_t *cp_mme_rx = NULL;
- // 1) get the last MME from the MMEs fifo
- if(cp_mme_rx = cyg_mbox_tryget (m_incoming_mbox_handle)) != NULL )
+ cp_mme_rx_t *mme;
+ cp_cl_interf_msg_t *msg;
+ uint fmi;
+
+ dbg_assert (ctx);
+
+ msg = cyg_mbox_get (ctx->cl_interf.mailbox_handle);
+ dbg_check (msg);
+
+ mme = cp_msg_mme_read_header (msg->buffer, msg->length,
+ msg->mfs->common.tei, &fmi);
+
+ // MME is not formatted correctly.
+ // Release the buffer.
+ if (!mme)
+ interface_mme_recv_done (ctx->interface, msg->cl_data);
+ else
{
- // 2) read the MME's header and store it in a newly allocated MME Tx context
- bitstream_init(cp_mme_rx->bitstream, cp_mme_rx->p_mme, cp_mme_rx->length, read);
-
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.oda, 48);
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.osa, 48);
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.m_type, 16);
- // check if this is the expected m_type
- if(cp_mme_rx->header.m_type != MSG_MTYPE_IEEE_ETHERTYPE)
- {
- // if not, we have a vlan tag
- // so, read and compute the vlan tag
- cp_mme_rx->header.v_lan_tag = cp_mme_rx->header.m_type << 0xFF;
- bitstream_access(cp_mme_rx->bitstream, &tmp, 16);
- cp_mme_rx->header.v_lan_tag |= tmp;
- // and read the ethertype
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.m_type, 16);
- }
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.mmv, 8);
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.mm_type, 16);
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.nf_mi, 4);
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.fn_mi, 4);
- bitstream_access(cp_mme_rx->bitstream, &cp_mme_rx->header.fmsn, 8);
- // 3) check the ODA, and the MME constants
- if(cp_mme_rx->header.oda != cp_sta_own_data_get_mac_address(NULL))
- check_mme_ok = false;
- if(cp_mme_rx->header.m_type != MSG_MTYPE_IEEE_ETHERTYPE)
- check_mme_ok = false;
- if(cp_mme_rx->header.mmv != MSG_MM_VERSION)
- check_mme_ok = false;
- if(check_mme_ok == false)
+ // Verify if the MME is a segmented MME.
+ if (fmi)
{
- // then release the MME and forget it
- // TODO
+ cp_cl_interf_rx_mme_frag (ctx, msg->mfs->common.tei,
+ msg->buffer, msg->length,
+ fmi);
+
+ interface_mme_recv_done (ctx->interface, msg->cl_data);
}
+ // Normal MME call the MSG dispatcher.
else
- {
- // check if the message is complete
- if(cp_mme_rx->header.nf_mi == cp_mme_rx->header.fn_mi)
- {
- // yes, so call the msg_dispatch function
- cp_msg_dispatch(ctx, cp_mme_rx);
- }
- else
- {
- // no, so store the message
- // TODO
- }
- }
+ cp_msg_dispatch (ctx, mme);
}
- return cp_mme_rx;
+
+
+ // Release data.
+ if (msg->mfs)
+ blk_release (msg->mfs);
+ blk_release (msg);
}
+/**
+ * Get the available buffer.
+ * \param ctx the module context.
+ * \return MME TX buffer.
+ *
+ * Return null if no buffers are available
+ */
+u8 *
+cp_cl_interf_get_buffer_tx (cp_t *ctx)
+{
+ cyg_semaphore_wait (&ctx->cl_interf.buffer_list_sem);
+ return circular_buffer_get (&ctx->cl_interf.buffer_tx_list);
+}
/**
- * return the Tx MME buffer.
- *
- * \param ctx the cp context
- * \return mme_rx_t the mme context
- *
- * !!! This function must be thread-safe !!!
- * If the Tx buffer is available, return it.
- * else, wait for it.
- * It can be called either from CP or CE thread, and the Tx buffer is given
- * from the CL environnement.
+ * Send a MME over the PWL or the HLE.
+ * \param ctx the module context.
+ * \param mme The MME to send.
+ *
*/
-mme_tx_t *
-cp_cl_interf_give_tx_buffer(cp_t *ctx);
+void
+cp_cl_interf_mme_send (cp_t *ctx, cp_mme_tx_t * mme)
+{
+ mfs_tx_t *mfs;
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ if (mme->peer.all_sta)
+ {
+ cp_net_t *net;
+ cp_sta_t *sta_current;
+ cp_sta_t *sta_next;
+
+ net = cp_sta_mgr_get_our_avln (ctx);
+ sta_current = cp_net_get_first (net, CP_STA_STATE_ASSOCIATED);
+ while (sta_current)
+ {
+ mfs = mac_store_mfs_get_tx (ctx->mac_store, false /* bcast */,
+ true /* MME */,
+ MAC_LID_NONE /* MME */,
+ cp_sta_get_tei (sta_current));
+
+ // Provide it to the interface.
+ interface_mme_send (ctx->interface, mme->p_mme, mme->length, mfs);
+
+ sta_next = cp_net_get_next_sta (net, sta_current);
+ blk_release (sta_current);
+
+ if (mfs)
+ blk_release (mfs);
+ sta_current = sta_next;
+ }
+ }
+ else
+ {
+ dbg_assert (mme->peer.tei);
+ mfs = mac_store_mfs_get_tx (ctx->mac_store, false /* bcast */,
+ true /* MME */,
+ MAC_LID_NONE /* MME */,
+ mme->peer.tei);
+ // Provide it to the interface.
+ interface_mme_send (ctx->interface, mme->p_mme, mme->length, mfs);
+
+ if (mfs)
+ blk_release (mfs);
+ }
+}
/**
- * will send the MME buffer to the DP.
- *
- * \param ctx the cp context
- * \param mme the mme to send and it context
- *
- * Must retreive the MFS and send the message through this MFS.
- * if necessary, will pad the message to the minimum MME size
+ * Add a buffer to the circular list.
+ * \param ctx the module context.
+ * \param buffer The buffer received.
+ *
*/
void
-cp_cl_interf_mme_send(cp_t *ctx, mme_tx_t *mme);
+cp_cl_interf_add_buffer_tx (cp_t *ctx, u8 * buffer)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+
+ circular_buffer_add (&ctx->cl_interf.buffer_tx_list, buffer);
+ cyg_semaphore_post (&ctx->cl_interf.buffer_list_sem);
+}
/**
- * callback used by the CL to give back the Tx buffer.
- *
- * \param ctx the cp context
- * \param buffer the buffer
- *
- * * !!! this function is executed in the CL context
+ * Remove all oldest MME received.
+ * \param ctx the module context.
+ *
*/
void
-cp_cl_interf_receive_tx_buffer(cp_t *ctx, u8 * buffer);
+cp_cl_interf_garbage_collector (cp_t *ctx){}
+
/**
- * this function will remove expired block of fragmented mme.
- *
- * \param ctx the cp context
- *
- * it is called periodicly, and will check all the currently stored MME
- * fragments. If necessary, release it.
+ * Receive a MME from the PWL or the HLE.
+ * \param ctx the module context.
+ * \param mfs The MFS used to received the MME.
+ * \param buffer The MME buffer containing the MME.
+ * \param length The MME length.
+ * \param cl-data The CL data.
+ * \param hardware_encrypt Indicate if the MME was Phy encrypted or not.
+ *
*/
void
-cp_cl_interf_garbage_collector(cp_t *ctx);
+cp_cl_interf_rx_mme (cp_t *ctx, mfs_rx_t * mfs,
+ u8 * buffer, uint length, void * cl_data,
+ bool hardware_encrypt)
+{
+ cp_cl_interf_msg_t *msg;
+ dbg_assert (ctx);
+ dbg_assert (mfs);
+ dbg_assert (buffer);
+ dbg_assert (length >= ETH_PACKET_MIN_SIZE
+ && length <= ETH_PACKET_MAX_SIZE);
+
+ msg = blk_alloc ();
+ msg->mfs = mfs;
+ blk_addref (msg->mfs);
+ msg->buffer = buffer;
+ msg->length = length;
+ msg->cl_data = cl_data;
+ msg->hard_encrypt = hardware_encrypt;
+
+ // Store the message in the mailbox.
+ cyg_mbox_put (ctx->cl_interf.mailbox_handle, msg);
+
+ // Raise an event in station core.
+}
+
+
+/**
+ * Copy the Fragmented MME into blocks.
+ * \param ctx the cp module context.
+ * \param tei the station source TEI.
+ * \param mme the MME to fragment.
+ * \param length the MME length.
+ * \param fmi the FMI MME data.
+ */
+void
+cp_cl_interf_rx_mme_frag (cp_t *ctx, cp_tei_t tei, u8 *mme, uint length,
+ uint fmi)
+{
+ uint fmi_frag_nbs;
+ uint fmi_frag_nb;
+ uint fmi_frag_ssn;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_reassembly_ctx_blk_t *head;
+ cp_sta_reassembly_ctx_blk_t *tail;
+
+ fmi_frag_nbs = read_u8_from_word ((u8 *) &fmi) >> 4;
+ fmi_frag_nb = read_u8_from_word ((u8 *) &fmi) & 0xF;
+ fmi_frag_ssn = read_u8_from_word (((u8 *) &fmi) + 1);
+
+ net = cp_sta_mgr_get_our_avln (ctx);
+ sta = cp_net_get_sta (net, tei);
+
+ dbg_assert (sta);
+
+ if (sta->reassembly_ctx.last_seg_ssn != fmi_frag_ssn)
+ {
+ uint nb_blk;
+ cp_sta_reassembly_ctx_blk_t *current;
+ uint offset;
+ uint rest;
+
+ sta->reassembly_ctx.last_seg_ssn = fmi_frag_ssn;
+ nb_blk = (length / BLK_SIZE) + 1;
+
+ // Compute the number of blocks.
+ head = (cp_sta_reassembly_ctx_blk_t *)
+ blk_alloc_desc_range (nb_blk, (blk_t **) &tail);
+ tail->next = NULL;
+
+ for (current = head, offset = 0;
+ offset < length && current != NULL;
+ offset += BLK_SIZE, current = current->next)
+ {
+ current->length = ((rest = (length - offset)) > BLK_SIZE)
+ ? BLK_SIZE : rest;
+ current->ssn = fmi_frag_ssn;
+ bitstream_memcpy (current->data, mme + offset,
+ (rest > BLK_SIZE) ? BLK_SIZE : rest);
+ }
+
+ // Chain the blocks.
+ sta->reassembly_ctx.tail->next = head;
+ sta->reassembly_ctx.tail = tail;
+ }
+}