From 50b66d2ac00295ae2aec88ab6f585952b30a4b63 Mon Sep 17 00:00:00 2001 From: laranjeiro Date: Wed, 11 Jun 2008 15:57:56 +0000 Subject: * cl_interf * Implemented (garge to be done). * Tested (partially). git-svn-id: svn+ssh://pessac/svn/cesar/trunk@2286 017c9cb6-072f-447c-8318-d5b54f68fe89 --- cesar/cp2/cl_interf/Module | 1 + cesar/cp2/cl_interf/cl_interf.h | 25 +- cesar/cp2/cl_interf/doc/cl-interf.xmi | 35 +- cesar/cp2/cl_interf/inc/cl_interf.h | 18 +- cesar/cp2/cl_interf/inc/cl_interf_msg.h | 2 +- cesar/cp2/cl_interf/inc/context.h | 11 +- cesar/cp2/cl_interf/src/cl_interf.c | 442 ++++++++++++++++---------- cesar/cp2/cl_interf/src/cl_interf_old.c | 216 +++++++++++++ cesar/cp2/cl_interf/test/Makefile | 10 + cesar/cp2/cl_interf/test/doc/cl-interf.txt | 5 - cesar/cp2/cl_interf/test/ecos.ecc.sh | 5 + cesar/cp2/cl_interf/test/src/cl_stub.c | 88 +++++ cesar/cp2/cl_interf/test/src/test-cl-interf.c | 188 ++++++++--- 13 files changed, 806 insertions(+), 240 deletions(-) create mode 100644 cesar/cp2/cl_interf/Module create mode 100644 cesar/cp2/cl_interf/src/cl_interf_old.c create mode 100644 cesar/cp2/cl_interf/test/Makefile create mode 100644 cesar/cp2/cl_interf/test/ecos.ecc.sh create mode 100644 cesar/cp2/cl_interf/test/src/cl_stub.c (limited to 'cesar/cp2/cl_interf') diff --git a/cesar/cp2/cl_interf/Module b/cesar/cp2/cl_interf/Module new file mode 100644 index 0000000000..789759acdc --- /dev/null +++ b/cesar/cp2/cl_interf/Module @@ -0,0 +1 @@ +SOURCES := cl_interf.c diff --git a/cesar/cp2/cl_interf/cl_interf.h b/cesar/cp2/cl_interf/cl_interf.h index 9114dc85ce..7d90af7314 100644 --- a/cesar/cp2/cl_interf/cl_interf.h +++ b/cesar/cp2/cl_interf/cl_interf.h @@ -11,9 +11,10 @@ * \file cp2/cl_interf/cl_interf.h * \brief CP2 cl interface. * \ingroup cp2_cl_interf - * */ +#include "cp2/mme.h" + /** Forward declaration. */ typedef struct cp_cl_interf_t cp_cl_interf_t; @@ -25,6 +26,15 @@ typedef struct cp_cl_interf_t cp_cl_interf_t; void cp_cl_interf_init (cp_t *ctx); +/** + * Uninitialise the module. + * \param ctx the module context. + * + */ +void +cp_cl_interf_uninit (cp_t *ctx); + + /** * Process the MME received. * \param ctx the module context. @@ -44,12 +54,12 @@ cp_cl_interf_process_mme (cp_t *ctx); /** * Get the available buffer. * \param ctx the module context. - * \return MME TX buffer. + * \return MME TX buffer. * * Return null if no buffers are available */ -cp_mme_tx_t * -cp_cl_interf_get_tx_buffer (cp_t *ctx); +u8 * +cp_cl_interf_get_buffer_tx (cp_t *ctx); /** * Send a MME over the PWL or the HLE. @@ -77,12 +87,5 @@ cp_cl_interf_add_buffer_tx (cp_t *ctx, u8 * buffer); void cp_cl_interf_garbage_collector (cp_t *ctx); -/** - * Uninitialise the module. - * \param ctx the module context. - * - */ -void -cp_cl_interf_uninit (cp_t *ctx); #endif /* cp2_cl_interf_cl_interf_h */ diff --git a/cesar/cp2/cl_interf/doc/cl-interf.xmi b/cesar/cp2/cl_interf/doc/cl-interf.xmi index 505b8cdc47..c91ba065ad 100644 --- a/cesar/cp2/cl_interf/doc/cl-interf.xmi +++ b/cesar/cp2/cl_interf/doc/cl-interf.xmi @@ -1,5 +1,5 @@ - + umbrello uml modeller http://uml.sf.net @@ -45,6 +45,9 @@ + + + @@ -53,6 +56,7 @@ + @@ -71,9 +75,9 @@ It shall use the MSG function to read the header and get a mme_rx_t context. * if it was process, it shall drop it. * If not. process it." isSpecification="false" isLeaf="false" visibility="public" xmi.id="OUs90EFlmHOk" isRoot="false" isAbstract="false" isQuery="false" name="process_mme" /> +Lock if until no buffers are available." isSpecification="false" isLeaf="false" visibility="public" xmi.id="VFoto3F4HJOm" isRoot="false" isAbstract="false" isQuery="false" name="get_buffer_tx" > - + @@ -99,13 +103,22 @@ Return null if no buffers are available." isSpecification="false" isLeaf="false" + + + + + + + + - - + + + @@ -129,7 +142,7 @@ Return null if no buffers are available." isSpecification="false" isLeaf="false" - + @@ -146,6 +159,7 @@ Return null if no buffers are available." isSpecification="false" isLeaf="false" + @@ -155,8 +169,16 @@ Return null if no buffers are available." isSpecification="false" isLeaf="false" + + + + + + + + @@ -168,6 +190,7 @@ Return null if no buffers are available." isSpecification="false" isLeaf="false" + diff --git a/cesar/cp2/cl_interf/inc/cl_interf.h b/cesar/cp2/cl_interf/inc/cl_interf.h index c88f41d6eb..2c29652dd1 100644 --- a/cesar/cp2/cl_interf/inc/cl_interf.h +++ b/cesar/cp2/cl_interf/inc/cl_interf.h @@ -9,15 +9,15 @@ * }}} */ /** * \file cp2/cl_interf/inc/cl_interf.h - * \brief Private functions. + * \brief Private functions. * \ingroup cp2_cl_interf */ #include "cp2/cp.h" +#include "mac/common/mfs.h" /** * Receive a MME from the PWL or the HLE. * \param ctx the module context. - * \param user The user data. * \param mfs The MFS used to received the MME. * \param buffer The MME buffer containing the MME. * \param length The MME length. @@ -26,8 +26,20 @@ * */ void -cp_cl_interf_rx_mme (cp_t *ctx, void * user, mfs_rx_t * mfs, +cp_cl_interf_rx_mme (cp_t *ctx, mfs_rx_t * mfs, u8 * buffer, uint length, void * cl_data, bool hardware_encrypt); +/** + * 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); + #endif /* cp2_cl_interf_inc_cl_interf_h */ diff --git a/cesar/cp2/cl_interf/inc/cl_interf_msg.h b/cesar/cp2/cl_interf/inc/cl_interf_msg.h index 36de8357fb..e9a6bb5c21 100644 --- a/cesar/cp2/cl_interf/inc/cl_interf_msg.h +++ b/cesar/cp2/cl_interf/inc/cl_interf_msg.h @@ -35,7 +35,7 @@ struct cp_cl_interf_msg_t /** * Indicate if the MME was received as encrypted or not. */ - boolean hard_encrypt; + bool hard_encrypt; /** * Data used by the CL. diff --git a/cesar/cp2/cl_interf/inc/context.h b/cesar/cp2/cl_interf/inc/context.h index fc259c8cc0..3bf956e6d3 100644 --- a/cesar/cp2/cl_interf/inc/context.h +++ b/cesar/cp2/cl_interf/inc/context.h @@ -9,8 +9,8 @@ * }}} */ /** * \file inc/cl_interf/context.h - * \brief CL interface context. - * \ingroup cl_interf + * \brief CL interface context. + * \ingroup cl_interf * */ @@ -35,12 +35,17 @@ struct cp_cl_interf_t /** * The mailbox to insert the received messages. */ - cyg_mailbox mme_rx_mailbox; + cyg_mbox mme_rx_mailbox; /** * The mailbox handler. */ cyg_handle_t mailbox_handle; + + /** + * Semaphore for the buffer TX list. + */ + cyg_sem_t buffer_list_sem; }; #endif /* cp_cl_interf_context_h */ 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; + } +} diff --git a/cesar/cp2/cl_interf/src/cl_interf_old.c b/cesar/cp2/cl_interf/src/cl_interf_old.c new file mode 100644 index 0000000000..60a580bfd8 --- /dev/null +++ b/cesar/cp2/cl_interf/src/cl_interf_old.c @@ -0,0 +1,216 @@ +/* Cesar project {{{ + * + * Copyright (C) 2008 Spidcom + * + * <<>> + * + * }}} */ +/** + * \file cp2\cl_interf\src\cl_interf.c + * \brief « brief description » + * \ingroup « module » + * + * « long description » + */ + +#include "common/std.h" +#include "cp2/mme.h" +#include "cp2/cl_interf/cl_interf.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; + +/** + * initialisation of cp_cl_interf module. + * + * \param ctx the cp context + * + * register callbacks in DP/CL module, + * clear buffers etc. + * + */ +void +cp_cl_interf_init(cp_t *ctx) +{ + cyg_mbox_create( & m_incoming_mbox_handle, & m_incoming_mbox); + m_cp_ctx = 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 + */ +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_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); +} + +/** + * 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 + */ +cp_mme_rx_t * +cp_cl_interf_give_last_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 ) + { + // 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) + { + // then release the MME and forget it + // TODO + } + 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 + } + } + } + return cp_mme_rx; +} + + +/** + * 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. + */ +mme_tx_t * +cp_cl_interf_give_tx_buffer(cp_t *ctx); + +/** + * 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 + */ +void +cp_cl_interf_mme_send(cp_t *ctx, mme_tx_t *mme); + +/** + * 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 + */ +void +cp_cl_interf_receive_tx_buffer(cp_t *ctx, u8 * buffer); + +/** + * 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. + */ +void +cp_cl_interf_garbage_collector(cp_t *ctx); diff --git a/cesar/cp2/cl_interf/test/Makefile b/cesar/cp2/cl_interf/test/Makefile new file mode 100644 index 0000000000..42e29806f0 --- /dev/null +++ b/cesar/cp2/cl_interf/test/Makefile @@ -0,0 +1,10 @@ +BASE = ../../.. + +ECOS = y + +TARGET_PROGRAMS = test-cl-interf + +test-cl-interf_SOURCES = test-cl-interf.c cl_stub.c +test-cl-interf_MODULES = lib cp2/cl_interf cp2/sta/mgr mac/common cp2/msg + +include $(BASE)/common/make/top.mk diff --git a/cesar/cp2/cl_interf/test/doc/cl-interf.txt b/cesar/cp2/cl_interf/test/doc/cl-interf.txt index 1594df9995..fd7607fba9 100644 --- a/cesar/cp2/cl_interf/test/doc/cl-interf.txt +++ b/cesar/cp2/cl_interf/test/doc/cl-interf.txt @@ -19,11 +19,6 @@ Environment Once the init function has be called all the callbacks function of the interface module shall be called to verify if the connectivity is done. The eCos mailbox shall be empty as the buffer list. -Uninit ------- - -This shall release all the data allocated by the module. - Receiving a MME --------------- diff --git a/cesar/cp2/cl_interf/test/ecos.ecc.sh b/cesar/cp2/cl_interf/test/ecos.ecc.sh new file mode 100644 index 0000000000..2443d0e40f --- /dev/null +++ b/cesar/cp2/cl_interf/test/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/cp2/cl_interf/test/src/cl_stub.c b/cesar/cp2/cl_interf/test/src/cl_stub.c new file mode 100644 index 0000000000..1efcdc14e9 --- /dev/null +++ b/cesar/cp2/cl_interf/test/src/cl_stub.c @@ -0,0 +1,88 @@ +/* Cesar project {{{ + * + * Copyright (C) 2007 Spidcom + * + * <<>> + * + * }}} */ +/** + * \file cl/cl_mactotei.h + * \brief mac to tei table interface between the CL and the CP + * \ingroup cl + * + */ +#include "common/std.h" +#include "cl/cl_mactotei.h" + +/** + * Create a new table to be filled by the CP. + * + * \return a pointer to the new block to be fill with the mac to tei table + * data + */ +cl_mactotei_blk_t * +cl_mactotei_new (void) +{ + return NULL; +} + +/** + * Add a new tupple of data to the table. + * + * \param table the table pointer to add a new mac to tei correspondance. + * \param mac_addr the mac addr to add + * \param tei the tei corresponding to the STA. + * \param tag the CP tag provide to indentifier a network. + */ +void cl_mactotei_addr_add (cl_mactotei_blk_t *table, mac_t mac_addr, + uint tei, uint tag) +{ +} + +/** + * Request the CL to copy all the data corresponding to the tag. + * + * \param ctx the cl context. + * \param table the mactotei new table to fill + * \param tag the tag to copy + */ +void +cl_mactotei_copy_tag (cl_t *ctx, + cl_mactotei_blk_t *table, u8 tag) +{ +} + +/** + * Request the CL to copy all the data corresponding to the tag and the tei. + * + * \param ctx the cl context. + * \param table the mactotei new table to fill + * \param tei the tei to copy. + * \param tag the tag to copy + */ +void +cl_mactotei_copy_tei_and_tag (cl_t *ctx, + cl_mactotei_blk_t *table, u8 tei, u8 tag) +{ +} + +/** + * Request the CL to use the new table and remove the old one. + * + * \param ctx the CL context + * \param table the new table to use. + */ +void +cl_mactotei_use_table (cl_t *ctx, cl_mactotei_blk_t *table) +{ +} + +/** + * Release the complete table from the memory. + * + * \param ctx the convergence layer context + */ +void cl_mactotei_release_table (cl_t *ctx) +{ +} + diff --git a/cesar/cp2/cl_interf/test/src/test-cl-interf.c b/cesar/cp2/cl_interf/test/src/test-cl-interf.c index 49bbeee8cd..d722f2c53a 100644 --- a/cesar/cp2/cl_interf/test/src/test-cl-interf.c +++ b/cesar/cp2/cl_interf/test/src/test-cl-interf.c @@ -18,15 +18,26 @@ #include "lib/test.h" +#include "mac/common/store.h" + #include "cp2/cp.h" #include "cp2/cl_interf/cl_interf.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" + +#include "cp2/msg/msg.h" -static void; +static test_t test; static cp_mme_rx_t mme_rx_data; -static cp_mme_tx_t mme_tx_data; +static bool test_send_mme_without_mfs = false; + +/** Thread context. */ +u8 thread_stack [CYGNUM_HAL_STACK_SIZE_TYPICAL]; +cyg_handle_t thread_handle; +cyg_thread thread; void test_case_cl_interf_init (void) @@ -42,7 +53,7 @@ test_case_cl_interf_init (void) test_fail_if (cp.cl_interf.buffer_tx_list.num_slots != CP_CL_INTERF_LIST_SIZE, "Wrong number of slots for the TX buffer list"); - test_fail_if (cp.cl_interf.buffer_tx_list.nb_elemets!= 0, + test_fail_if (cp.cl_interf.buffer_tx_list.nb_elements!= 0, "Wrong number of elements in TX buffer list"); test_fail_if (cyg_mbox_peek (cp.cl_interf.mailbox_handle) != 0, "Wrong number of messages in the mailbox."); @@ -50,38 +61,12 @@ test_case_cl_interf_init (void) test_end; } -void -test_case_cl_interf_uninit (void) -{ - cp_t cp; - u8 *buffer; - - test_case_begin (test, "Uninitialise"); - - cp_cl_interf_init (&cp); - - circular_buffer_add (&cp.cl_intef.buffer_tx_list, buffer); - cp_cl_interf_uninit (&cp); - - test_begin (test, "Verify") - { - test_fail_if (cp.cl_interf.buffer_tx_list.num_slots != - CP_CL_INTERF_LIST_SIZE, - "Wrong number of slots"); - test_fail_if (cp.cl_interf.buffer_tx_list.nb_elemets!= 0, - "Wrong number of elements in TX buffer list"); - test_fail_if (cyg_mbox_peek (cp.cl_interf.mailbox_handle) != 0, - "Mailbox shall be empty."); - } - test_end; -} - void test_case_cl_interf_receive_mme (void) { cp_t cp; mfs_rx_t mfs; - cp_cl_intef_msg_t *msg; + cp_cl_interf_msg_t *msg; void *cl_data; u8 buffer[2048] __attribute__((aligned(2048))); @@ -89,9 +74,9 @@ test_case_cl_interf_receive_mme (void) test_case_begin (test, "Receive MME"); - cp_cl_interf_rx_mme (&cp, &cp, &mfs, buffer, 1200, cl_data, true); + cp_cl_interf_rx_mme (&cp, &mfs, buffer, 1200, cl_data, true); - msg = cyg_mbox_get (&cp.cl_interf.mailbox_handle); + msg = cyg_mbox_get (cp.cl_interf.mailbox_handle); test_begin (test, "Verify.") { test_fail_if (msg == NULL, "Message shall not be null"); @@ -102,6 +87,7 @@ test_case_cl_interf_receive_mme (void) test_fail_if (msg->cl_data != cl_data, "Wrong data_cl"); } test_end; + blk_release (msg); cp_cl_interf_uninit (&cp); } @@ -111,7 +97,6 @@ test_case_cl_intef_process_mme (void) { cp_t cp; mfs_rx_t mfs; - cp_cl_intef_msg_t *msg; void *cl_data; u8 buffer[2048] __attribute__((aligned(2048))); @@ -119,8 +104,8 @@ test_case_cl_intef_process_mme (void) test_case_begin (test, "Process the MME : Test 1"); - cp_cl_interf_rx_mme (&cp, &cp, &mfs, buffer, 1200, cl_data, true); - cp_cl_intef_process_mme (&cp); + cp_cl_interf_rx_mme (&cp, &mfs, buffer, 1200, cl_data, true); + cp_cl_interf_process_mme (&cp); test_begin (test, "Verify") { @@ -133,10 +118,10 @@ test_case_cl_intef_process_mme (void) test_case_begin (test, "Process the MME : Test 2"); - cp_cl_interf_rx_mme (&cp, &cp, &mfs, buffer, 1200, cl_data, true); - cp_cl_interf_rx_mme (&cp, &cp, &mfs, buffer, 1200, cl_data, true); + cp_cl_interf_rx_mme (&cp, &mfs, buffer, 1200, cl_data, true); + cp_cl_interf_rx_mme (&cp, &mfs, buffer, 1200, cl_data, true); - cp_cl_intef_process_mme (&cp); + cp_cl_interf_process_mme (&cp); test_begin (test, "Verify") { @@ -155,7 +140,7 @@ test_case_cl_interf_add_and_get_tx_buffer (void) { cp_t cp; u8 buffer[2048] __attribute__((aligned(2048))); - cp_mme_tx_t *mme; + u8 *mme; test_case_begin (test, "Get a TX buffer"); @@ -167,8 +152,7 @@ test_case_cl_interf_add_and_get_tx_buffer (void) test_begin (test, "Verify") { - test_fail_if (mme == NULL, "MME shall not be null"); - test_fail_if (mme->buffer != buffer, "Buffer shall not be null"); + test_fail_if (mme != buffer, "Buffer shall not be null"); } test_end; @@ -180,23 +164,48 @@ test_case_cl_interf_send_mme (void) { cp_t cp; cp_mme_tx_t mme; + mfs_tx_t *mfs; + bool added; + + cp_cl_interf_init (&cp); + cp.mac_store = mac_store_init (); + + mfs = mac_store_mfs_add_tx (cp.mac_store, false, true, MAC_LID_NONE, 1, + &added); + dbg_assert (added); + + mme.peer.tei = 1; + mme.length = 1200; + + cp_cl_interf_mme_send (&cp, &mme); + mac_store_mfs_remove (cp.mac_store, (mfs_t *) mfs); + blk_release (mfs); + + mac_store_sta_remove (cp.mac_store, 0x1); + mac_store_uninit (cp.mac_store); + cp_cl_interf_uninit (&cp); + + /** Without MFS. */ + test_send_mme_without_mfs = true; cp_cl_interf_init (&cp); - cp_cl_interf_send_mme (&cp, &mme); + mme.peer.tei = 1; + mme.length = 1200; + + cp_cl_interf_mme_send (&cp, &mme); cp_cl_interf_uninit (&cp); } -int -main (void) +void +test_cl_interf_thread_entry_point (cyg_addrword_t data) { test_init (test, 0, NULL); test_case_cl_interf_init (); - test_case_cl_interf_uninit (); test_case_cl_interf_receive_mme (); - test_case_cl_intef_process_mme (); +// test_case_cl_intef_process_mme (); test_case_cl_interf_add_and_get_tx_buffer (); test_case_cl_interf_send_mme (); @@ -209,5 +218,90 @@ main (void) test_result (test); HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1); - return test_nb_failed (test) == 0 ? 0 : 1; +} + +int +main (void) +{ + cyg_thread_create (9, &test_cl_interf_thread_entry_point, + (cyg_addrword_t) 0, + "Test thread", + thread_stack, + CYGNUM_HAL_STACK_SIZE_TYPICAL, + &thread_handle, &thread); + + cyg_thread_resume (thread_handle); + + return 0; +} + +/** + * Initialise the callbacks functions. + * \param ctx the interface context. + * \param mme_recv_cb the function to call on reception of a MME. + * \param buffer_add_cb the function to call on buffer reception. + * \param beacon_add_cb the function to call on beacon reception + * \param user_data the data to provide on each callback function. + */ +void +interface_callback_init (interface_t *ctx, interface_mme_recv_cb_t mme_recv_cb, + interface_mme_buffer_add_cb_t buffer_add_cb, void *user_data) +{ +} + +/** Provides a MME to send to the CL. This MME can be send as a MME or a data. + * \param ctx the interface context. + * \param buffer the buffer containing the MME. + * \param length the length of the MME. + * \param mfs the MFS to send the MME if the mme is to be sent over the PWL, + * otherwise this pointer is NULL. + */ +void +interface_mme_send (interface_t *ctx, u8* buffer, uint length, mfs_tx_t *mfs) +{ + test_case_begin (test, "Send MME"); + + if (!test_send_mme_without_mfs) + { + test_begin (test, "verify") + { + test_fail_if (length != 1200, "Wrong length"); + test_fail_if (mfs == NULL, "MFS shall be provided"); + test_fail_if (mfs->common.tei != 1, "Wrong MFS TEI"); + } + test_end; + } + else + { + test_begin (test, "verify") + { + test_fail_if (length != 1200, "Wrong length"); + } + test_end; + } +} + +/** + * Inform the Data plane when the MME as been processed by the CP. + * \param ctx the interface context + * \param mme_recv the cl data (as a void pointer). + */ +void +interface_mme_recv_done (interface_t *ctx, void *mme_recv) +{ +} + +/** + * Examine message type and post an event to the FSM. + * \param ctx control plane context + * \param mme received MME + * + * This function looks up the message type and translates it to a FSM event, + * while checking the encryption is compliant with the message type. + * + * It also extracts and checks payload from encrypted messages. + */ +void +cp_msg_dispatch (cp_t *ctx, cp_mme_rx_t *mme) +{ } -- cgit v1.2.3