summaryrefslogtreecommitdiff
path: root/cesar/cp/av/sta
diff options
context:
space:
mode:
authorThierry Carré2012-04-05 13:59:25 +0200
committerThierry Carré2012-05-10 17:02:57 +0200
commit87f9cac07558b7ba4515dcf7bf93f9778d24bf1c (patch)
treea2a5f9a58772b34894e6306091eab4820a888270 /cesar/cp/av/sta
parentb9816688dcf600e2ac65357691dd2e58ee47435d (diff)
cesar: AV code move to cp/av directory, refs #2928
Diffstat (limited to 'cesar/cp/av/sta')
-rw-r--r--cesar/cp/av/sta/action/Config0
-rw-r--r--cesar/cp/av/sta/action/Module4
-rw-r--r--cesar/cp/av/sta/action/action.h28
-rw-r--r--cesar/cp/av/sta/action/assoc.h489
-rw-r--r--cesar/cp/av/sta/action/drv.h65
-rw-r--r--cesar/cp/av/sta/action/handover.h82
-rw-r--r--cesar/cp/av/sta/action/inc/action.h38
-rw-r--r--cesar/cp/av/sta/action/info.h53
-rw-r--r--cesar/cp/av/sta/action/misc.h41
-rw-r--r--cesar/cp/av/sta/action/poweron.h240
-rw-r--r--cesar/cp/av/sta/action/sc.h217
-rw-r--r--cesar/cp/av/sta/action/src/action.c122
-rw-r--r--cesar/cp/av/sta/action/src/assoc.c815
-rw-r--r--cesar/cp/av/sta/action/src/drv.c182
-rw-r--r--cesar/cp/av/sta/action/src/handover.c220
-rw-r--r--cesar/cp/av/sta/action/src/info.c115
-rw-r--r--cesar/cp/av/sta/action/src/key.c122
-rw-r--r--cesar/cp/av/sta/action/src/misc.c172
-rw-r--r--cesar/cp/av/sta/action/src/poweron.c390
-rw-r--r--cesar/cp/av/sta/action/src/sc.c580
-rw-r--r--cesar/cp/av/sta/action/test/utest/Config1
-rw-r--r--cesar/cp/av/sta/action/test/utest/Makefile26
-rw-r--r--cesar/cp/av/sta/action/test/utest/inc/scenario_defs.h890
-rw-r--r--cesar/cp/av/sta/action/test/utest/inc/test_sta_action.h70
-rw-r--r--cesar/cp/av/sta/action/test/utest/override/cp/inc/context.h78
-rw-r--r--cesar/cp/av/sta/action/test/utest/override/cp/sta/core/core.h38
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/assoc.c1344
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/beacon_stub.c102
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/bridge.c497
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/cco_stub.c166
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/ce_stub.c24
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/core_stub.c42
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/cp_stub.c29
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/dataplane_stub.c140
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/drv.c855
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/fsm_stub.c58
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/handover.c289
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/info.c675
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/key.c80
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/mac_sar_interface_stub.c35
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/misc.c2074
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/msg_stub.c669
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/poweron.c765
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/sc.c1815
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/sc_test.c64
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/scenario_actions.c268
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/test_sta_action.c116
-rw-r--r--cesar/cp/av/sta/action/test/utest/src/vs.c988
-rw-r--r--cesar/cp/av/sta/mgr/Module3
-rw-r--r--cesar/cp/av/sta/mgr/src/sta_mgr.c388
-rw-r--r--cesar/cp/av/sta/mgr/src/sta_own_data.c87
-rw-r--r--cesar/cp/av/sta/mgr/sta_mgr.h35
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/Config3
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/Makefile15
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/doc/Makefile20
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/doc/net.txt191
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/doc/net_list.txt117
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/doc/sta.txt44
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/doc/sta_mgr.txt14
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/doc/sta_own_data.txt111
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/override/cp/cco/action/inc/context.h26
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/override/cp/inc/context.h57
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/override/cp/sta/core/core.h21
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/override/mac/sar/inc/context.h23
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/core_stub.c23
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/net_test.c225
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/sar_stub.c56
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/sta-test.c688
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/sta_mgr.c1745
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/station_test.c431
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/src/test_sta_mgr.c72
-rw-r--r--cesar/cp/av/sta/mgr/test/utest/test_sta_mgr.h54
72 files changed, 20622 insertions, 0 deletions
diff --git a/cesar/cp/av/sta/action/Config b/cesar/cp/av/sta/action/Config
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/cesar/cp/av/sta/action/Config
diff --git a/cesar/cp/av/sta/action/Module b/cesar/cp/av/sta/action/Module
new file mode 100644
index 0000000000..79370ecb2e
--- /dev/null
+++ b/cesar/cp/av/sta/action/Module
@@ -0,0 +1,4 @@
+SOURCES := sc.c drv.c misc.c handover.c poweron.c action.c assoc.c info.c \
+ key.c
+
+MODULES := cp/sta/action
diff --git a/cesar/cp/av/sta/action/action.h b/cesar/cp/av/sta/action/action.h
new file mode 100644
index 0000000000..c230025749
--- /dev/null
+++ b/cesar/cp/av/sta/action/action.h
@@ -0,0 +1,28 @@
+#ifndef cp_av_sta_action_action_h
+#define cp_av_sta_action_action_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/action.h
+ * \brief AV_STA action.
+ * \ingroup cp_av_sta_action
+ *
+ */
+#include "cp/types.h"
+#include "cp/mme.h"
+#include "cp/sta/action/action.h"
+
+#include "cp/av/sta/action/sc.h"
+#include "cp/av/sta/action/handover.h"
+#include "cp/av/sta/action/poweron.h"
+#include "cp/av/sta/action/misc.h"
+#include "cp/av/sta/action/assoc.h"
+#include "cp/av/sta/action/info.h"
+#include "cp/av/sta/action/drv.h"
+
+#endif /* cp_av_sta_action_action_h */
diff --git a/cesar/cp/av/sta/action/assoc.h b/cesar/cp/av/sta/action/assoc.h
new file mode 100644
index 0000000000..d06fe01e3a
--- /dev/null
+++ b/cesar/cp/av/sta/action/assoc.h
@@ -0,0 +1,489 @@
+#ifndef cp_av_sta_action_assoc_h
+#define cp_av_sta_action_assoc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/action/assoc.h
+ * \brief STA action, association related definitions.
+ * \ingroup cp_sta_action
+ *
+ * Association/disassociation
+ * ==========================
+ *
+ * This part relates to association and disassociation for a STA. A state
+ * machine is used to handle the association status of the station:
+ *
+ * \image html assoc.png "Association state machine"
+ *
+ * - (1) send CC_ASSOC.REQ
+ * - (2) send CM_GET_KEY.REQ
+ * - (3) send CC_ASSOC.REQ for renewal
+ * - (4) send CM_SET_KEY.CNF
+ * - (5) send CC_LEAVE.REQ
+ * - (6) send CC_LEAVE.RSP
+ * - (7) clear beacon not received counter if our beacon
+ * - (8) cleanup data plane
+ *
+ * For the moment, only one association scheme is supported: association with
+ * matching NID, without proxy network.
+ *
+ * Related: 7.3.2, 7.3.3, 7.3.4.1, 7.3.5.1, 7.3.6.
+ *
+ *
+ * Association
+ * -----------
+ *
+ * When the station wants to associate, it set the association parameters and
+ * trigger the "to assoc" event. This will send the CC_ASSOC.REQ message to
+ * the CCo and wait for response.
+ *
+ * If no response is received, retry. Retry is needed because we are not
+ * associated and broadcast is used.
+ *
+ * If a negative response is received, association has failed, this is
+ * remembered in order not to try to associate too often to the same CCo.
+ *
+ * If a positive response is received, go to associated state.
+ *
+ *
+ * Authentication
+ * --------------
+ *
+ * When entering this state, send a payload encrypted CM_GET_KEY.REQ to
+ * request the NEK.
+ *
+ * Once the station is authenticated, CC_SET_TEI_MAP.IND messages can be
+ * received.
+ *
+ * As unicast transmissions are used, a timeout will directly break the
+ * association sequence.
+ *
+ * If a negative response is received, association has failed, the CCo is
+ * using a different NMK. This is remembered in order not to associate with
+ * this CCo again (until keys are changed).
+ *
+ * If a positive response is received, the station is authenticated.
+ *
+ * Once authenticated, the CCo can change the NEK periodically.
+ *
+ *
+ * Lease renewal
+ * -------------
+ *
+ * Association is granted for a given time. When the station is associated,
+ * program a timer to renew the association. When this timer expires, send a
+ * CC_ASSOC.REQ for renewal and set the timer for a second chance.
+ *
+ * The station will not leave the AVLN by itself due to lease expiration. It
+ * will wait an eventual CC_LEAVE.IND message to do so.
+ *
+ * When the CCo confirms the renewal, the renew timer is reset to the value
+ * given in its confirmation message. Ignore renewal failure, will wait for
+ * the CC_LEAVE.IND message.
+ *
+ *
+ * Leaving
+ * -------
+ *
+ * If the request comes from the STA, trigger the "to leave" event. This will
+ * send the CC_LEAVE.REQ message to the CCo and wait for response. If no
+ * response cames for three beacon periods, resend and go to the "leave wait"
+ * state.
+ *
+ * If the request comes from the CCo (CC_LEAVE.IND), send a response and go to
+ * the "leave wait" state.
+ *
+ * The "leave wait" state is there to give time to the data plane to send the
+ * MME. After a fixed timer, go back to unassociated state and cleanup the
+ * data plane from all AVLN related parameters.
+ *
+ *
+ * Beacon monitoring
+ * -----------------
+ *
+ * If the central beacon is not received for several beacon period, this is a
+ * AVLN failure. The "avln failure" event is triggered and the station is
+ * unassociated.
+ *
+ * On each beacon reception, the beacon loss counter is reseted.
+ *
+ *
+ * Events
+ * ------
+ *
+ * When the authenticated state is entered, the join event is triggered.
+ *
+ * On AVLN failure, the "avln failure" event is triggered.
+ *
+ * When the unassociated state is entered, the left event is triggered. This
+ * event means that the station has left the AVLN or that the association
+ * request failed.
+ */
+#include "cp/sta/mgr/net.h"
+
+BEGIN_DECLS
+
+/**
+ * Start a association procedure.
+ * \param ctx control plane context
+ * \param cco_net AVLN of the CCo to associate with
+ * \param cco CCo to associate with
+ *
+ * Trigger TO_ASSOC event.
+ *
+ * Need:
+ * - CCo to associate to (MAC, TEI, NID).
+ * - our CCo cap and proxy network cap.
+ */
+void
+cp_av_sta_action_assoc_start (cp_t *ctx, cp_net_t *cco_net, cp_sta_t *cco);
+
+/**
+ * Start an Simple Connect association procedure.
+ * \param ctx control plane context
+ * \param cco_net AVLN of the CCo to associate with
+ * \param cco CCo to associate with
+ * \param sc_peer the peer with which we are doing the SC procedure.
+ *
+ * Trigger TO_SC_ASSOC event.
+ */
+void
+cp_av_sta_action_sc_assoc_start (cp_t *ctx, cp_net_t *cco_net, cp_sta_t *cco);
+
+/**
+ * Request to leave the current AVLN.
+ * \param ctx control plane context
+ *
+ * Trigger a TO_LEAVE event.
+ */
+void
+cp_av_sta_action_assoc_leave (cp_t *ctx);
+
+/**
+ * Handle entering UNASSOCIATED.
+ * \param ctx control plane context
+ *
+ * Trigger a LEFT event.
+ */
+void
+cp_av_sta_action_assoc__unassociated__enter (cp_t *ctx);
+
+/**
+ * Handle UNASSOCIATED => (TO_ASSOC or TO_SC_ASSOC) events.
+ * \param ctx control plane context
+ *
+ * Send a CC_ASSOC.REQ to the CCo.
+ * \note the transition is the same if we are in the SC procedure or not
+ * because the CC_ASSOC.REQ is sent to the CCo (in the SC procedure, the peer
+ * STA will act as the CCo).
+ */
+void
+cp_av_sta_action_assoc__unassociated__to_assoc (cp_t *ctx);
+
+/**
+ * Common handle (WAIT_ASSOC_CONF or SC_WAIT_ASSOC_CONF) => CC_ASSOC.CNF.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ * \param sc true if we are in simple connect procedure.
+ * \
+ *
+ * If the CCo accepted our association and update association information.
+ * If we are not in SC procedure, send the CM_GET_KEY.REQ and go to the
+ * ASSOCIATED state. If we are in SC, do nothing and go to SC_ASSOCIATED.
+ * If the CCo refused, go back to UNASSOCIATED state and update the CCo
+ * information to remember the failure.
+ *
+ * Update:
+ * - our TEI.
+ * - our TEI lease time (update lease timer).
+ * - our AVLN.
+ * - our AVLN SNID.
+ * - CCo failure info.
+ */
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__cc_assoc_cnf__common (cp_t *ctx,
+ cp_mme_rx_t *mme,
+ bool sc);
+
+/**
+ * Handle WAIT_ASSOC_CONF => CC_ASSOC.CNF.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ */
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__cc_assoc_cnf (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle SC_WAIT_ASSOC_CONF => CC_ASSOC.CNF.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ */
+void
+cp_av_sta_action_assoc__sc_wait_assoc_cnf__cc_assoc_cnf (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Common handle for {SC_,}WAIT_ASSOC_CONF => TIMEOUT.
+ * \param ctx control plane context.
+ * \param sc true if we are in simple connect procedure.
+ *
+ * If retry count is not zero, resend the CC_ASSOC.REQ.
+ *
+ * If retry count is zero, go back to UNASSOCIATED state.
+ */
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__timeout_common (cp_t *ctx, bool sc);
+
+/**
+ * Handle WAIT_ASSOC_CONF => TIMEOUT.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__timeout (cp_t *ctx);
+
+/**
+ * Handle SC_WAIT_ASSOC_CONF => TIMEOUT.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_assoc__sc_wait_assoc_cnf__timeout (cp_t *ctx);
+
+/**
+ * Common handle for ASSOCIATED or SC_NMK_EXCHANGED => CM_GET_KEY.CNF (PID=[0,3]).
+ * \param ctx control plane context
+ * \param mme received MME handle
+ * \param sc true if we are in simple connect procedure.
+ *
+ * If this is a success, go to AUTHENTICATED state, trigger JOINED event and
+ * update station status.
+ *
+ * If authentication has failed, remember this and go back to UNASSOCIATED
+ * state.
+ *
+ * Update:
+ * - authenticated status.
+ * - NEK.
+ * - CCo failure info.
+ */
+
+void
+cp_av_sta_action_assoc__cm_get_key_cnf__common (cp_t *ctx, cp_mme_rx_t
+ *mme, bool sc);
+
+/**
+ * Handle SC_NMK_EXCHANGED => CM_GET_KYE.CNF (PID=0)
+ * \param ctx control plane context.
+ * \param mme received MME to handle.
+ */
+void
+cp_av_sta_action_assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0 (cp_t *ctx,
+ cp_mme_rx_t *
+ mme);
+
+/**
+ * Handle ASSOCIATED => CM_GET_KEY.CNF (PID=0).
+ * \param ctx control plane context
+ * \param mme received MME handle
+ */
+void
+cp_av_sta_action_assoc__associated__cm_get_key_cnf_pid_0 (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle AUTHENTICATED => CM_GET_KEY.CNF (PID=1).
+ * \param ctx control plane context
+ * \param mme received MME handle
+ */
+void
+cp_av_sta_action_assoc__authenticated__cm_get_key_cnf_pid_1 (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle ASSOCIATED => TIMEOUT.
+ * \param ctx control plane context
+ *
+ * Authentication failed, go back to UNASSOCIATED and update the CCo
+ * information to remember the failure.
+ *
+ * Stop lease timer.
+ */
+void
+cp_av_sta_action_assoc__associated__timeout (cp_t *ctx);
+
+/**
+ * Handle ASSOCIATED => TO_LEAVE.
+ * \param ctx control plane context
+ *
+ * Stop lease timer.
+ */
+void
+cp_av_sta_action_assoc__associated__to_leave (cp_t *ctx);
+
+/**
+ * Handle AUTHENTICATED => nek_request.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_assoc__authenticated__nek_request (cp_t *ctx);
+
+/**
+ * Handle SC_ASSOCIATED => CM_GET_KEY.REQ (PID=3).
+ * \param ctx control plane context.
+ * \param mme received MME to handle.
+ */
+void
+cp_av_sta_action_assoc__sc_associated__cm_get_key_req_pid_3 (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle SC_TEK_EXCHANGED => CM_SET_KEY.REQ (PID=3).
+ * \param ctx control plane context.
+ * \param mme received MME to handle.
+ */
+void
+cp_av_sta_action_assoc__sc_tek_exchanged__cm_set_key_req_pid_3 (cp_t *ctx,
+ cp_mme_rx_t *
+ mme);
+
+/**
+ * Handle leaving AUTHENTICATED.
+ * \param ctx control plane context
+ *
+ * Stop lease timer.
+ */
+void
+cp_av_sta_action_assoc__authenticated__leave (cp_t *ctx);
+
+/**
+ * Handle AUTHENTICATED => RENEW.
+ * \param ctx control plane context
+ *
+ * Time to renew our lease. Send a CC_ASSOC.REQ.
+ */
+void
+cp_av_sta_action_assoc__authenticated__renew (cp_t *ctx);
+
+/**
+ * Handle AUTHENTICATED => CC_ASSOC.CNF.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ *
+ * Update:
+ * - our TEI lease time (update lease timer).
+ */
+void
+cp_av_sta_action_assoc__authenticated__cc_assoc_cnf (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle AUTHENTICATED => CM_SET_KEY.REQ (PID=1), NEK renewal.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ *
+ * Sent periodically by the CCo to change the NEK.
+ *
+ * Update:
+ * - NEK.
+ */
+void
+cp_av_sta_action_assoc__authenticated__cm_set_key_req_pid_1 (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle AUTHENTICATED => TO_LEAVE.
+ * \param ctx control plane context
+ *
+ * Send the CC_LEAVE.REQ message to the CCo. Set a timeout in three beacon
+ * periods.
+ */
+void
+cp_av_sta_action_assoc__authenticated__to_leave (cp_t *ctx);
+
+/**
+ * Handle AUTHENTICATED => CC_LEAVE.IND.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ *
+ * The CCo request us to leave the AVLN. Send a response and go to LEAVE_WAIT
+ * event.
+ */
+void
+cp_av_sta_action_assoc__authenticated__cc_leave_ind (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle AUTHENTICATED => BEACON.
+ * \param ctx control plane context
+ * \param beacon received beacon
+ * \param net STA net
+ * \param sta STA emitting the beacon
+ *
+ * If the beacon is ours, reset the "beacon not received" counter.
+ */
+void
+cp_av_sta_action_assoc__authenticated__beacon (cp_t *ctx,
+ bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle AUTHENTICATED => BEACON NOT RECEIVED.
+ * \param ctx control plane context
+ *
+ * Increment the "beacon not received" counter. If it reaches the limit,
+ * this is a AVLN failure.
+ */
+void
+cp_av_sta_action_assoc__authenticated__beacon_not_received (cp_t *ctx);
+
+/**
+ * Handle LEAVING => CC_LEAVE.CNF.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ *
+ * Leave the AVLN and cleanup data plane.
+ */
+void
+cp_av_sta_action_assoc__leaving__cc_leave_cnf (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle LEAVING => TIMEOUT.
+ * \param ctx control plane context
+ *
+ * Send a CC_LEAVE.REQ again.
+ */
+void
+cp_av_sta_action_assoc__leaving__timeout (cp_t *ctx);
+
+/**
+ * Handle entering LEAVE_WAIT.
+ * \param ctx control plane context
+ */
+void
+cp_av_sta_action_assoc__leave_wait__enter (cp_t *ctx);
+
+/**
+ * Handle LEAVE_WAIT => TIMEOUT.
+ * \param ctx control plane context
+ *
+ * Leave the AVLN and cleanup data plane.
+ */
+void
+cp_av_sta_action_assoc__leave_wait__timeout (cp_t *ctx);
+
+/**
+ * Enter in Unassociating state.
+ * \param ctx the module context.
+ * Update the BSU to act as STA.
+ */
+void
+cp_av_sta_action_unassoc__unassoc__enter (cp_t *ctx);
+
+END_DECLS
+
+#endif /* cp_av_sta_action_assoc_h */
diff --git a/cesar/cp/av/sta/action/drv.h b/cesar/cp/av/sta/action/drv.h
new file mode 100644
index 0000000000..08d8b59bd5
--- /dev/null
+++ b/cesar/cp/av/sta/action/drv.h
@@ -0,0 +1,65 @@
+#ifndef cp_av_sta_action_drv_h
+#define cp_av_sta_action_drv_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/drv.h
+ * \brief STA action, driver related definitions.
+ * \ingroup cp_av_sta_action
+ *
+ */
+
+#include "cp/sta/action/drv.h"
+
+BEGIN_DECLS
+
+/**
+ * Handle USTA => DRV_STA_SC.
+ * \param ctx control plane context.
+ * \param mme the MME to handle.
+ */
+void
+cp_av_sta_action_drv__usta__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle UCCO => DRV_STA_SC.
+ * \param ctx control plane context.
+ * \param mme the MME to handle.
+ */
+void
+cp_av_sta_action_drv__ucco__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle CCO => DRV_STA_SC.
+ * \param ctx control plane context.
+ * \param mme the MME to handle.
+ */
+void
+cp_av_sta_action_drv__cco__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle STA => DRV_STA_SC.
+ * \param ctx control plane context.
+ * \param mme the MME to handle.
+ */
+void
+cp_av_sta_action_drv__sta__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle many => DRV_STA_SC (failure).
+ * \param ctx control plane context.
+ * \param mme the MME received.
+ *
+ * Disable DRV_STA_SC, but reply to say it to the host.
+ */
+void
+cp_av_sta_action_drv__many__drv_sta_sc__failure (cp_t *ctx, cp_mme_rx_t *mme);
+
+END_DECLS
+
+#endif /* cp_sta_action_drv_h */
diff --git a/cesar/cp/av/sta/action/handover.h b/cesar/cp/av/sta/action/handover.h
new file mode 100644
index 0000000000..06396e5ab6
--- /dev/null
+++ b/cesar/cp/av/sta/action/handover.h
@@ -0,0 +1,82 @@
+#ifndef cp_sta_action_handover_h
+#define cp_sta_action_handover_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/action/handover.h
+ * \brief STA action Handover
+ * \ingroup cp_sta_action
+ *
+ * All the function to handover.
+ */
+#include "cp/types.h"
+#include "cp/mme.h"
+
+BEGIN_DECLS
+
+/**
+ * Starts the handover process.
+ * \param ctx control plane context
+ * \param mme the MMe received.
+ *
+ * This is called by the FSM on a cc_handover_req MME.
+ */
+void
+cp_av_sta_action_handover__handover (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Starts the handover process.
+ * \param ctx control plane context
+ * \param mme the MMe received.
+ */
+void
+cp_av_sta_action_handover__start (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Received the cc_handover_info_ind MME.
+ * \param ctx control plane context.
+ * \param mme the MMe received.
+ *
+ * The handover procedure is done, now wait the expiration countdown in the
+ * central beacon to become CCo.
+ */
+void
+cp_av_sta_action_handover__handover_info_ind_receive (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * The countdown handover in the central beacon ended.
+ * \param ctx control plane context.
+ *
+ * The station is shall now start acting as CCo.
+ */
+void
+cp_av_sta_action_handover__handover_ended (cp_t *ctx);
+
+/**
+ * The countdown handover in the central beacon ended.
+ * \param ctx control plane context.
+ * \param net our network.
+ * \param sta the New CCo.
+ *
+ * The new CCo took its functionalities.
+ */
+void
+cp_av_sta_action_handover__sta_handover (cp_t *ctx, cp_net_t *net,
+ cp_sta_t *sta);
+
+/**
+ * The handover procedure failed.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_handover__failure (cp_t *ctx);
+
+END_DECLS
+
+#endif /* cp_sta_action_handover_h */
diff --git a/cesar/cp/av/sta/action/inc/action.h b/cesar/cp/av/sta/action/inc/action.h
new file mode 100644
index 0000000000..61df44842f
--- /dev/null
+++ b/cesar/cp/av/sta/action/inc/action.h
@@ -0,0 +1,38 @@
+#ifndef cp_sta_action_inc_action_h
+#define cp_sta_action_inc_action_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/action/inc/action.h
+ * \brief Private functions.
+ * \ingroup cp_sta_action
+ *
+ */
+
+BEGIN_DECLS
+
+/**
+ * Common handling of MATCH and JOIN AVLN.
+ * \param ctx control plane context
+ * \param beacon received beacon
+ * \param net STA net
+ * \param sta STA emitting the beacon
+ * \param sc true if in simple connect.
+ * \param branch_match branch taken if NID match
+ * \param branch_no_match branch taken in other cases
+ */
+void
+cp_av_sta_action_beacon_match_and_join (cp_t *ctx,
+ bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta, bool sc,
+ cp_fsm_branch_t branch_match,
+ cp_fsm_branch_t branch_no_match);
+
+END_DECLS
+
+#endif /* cp_sta_action_inc_action_h */
diff --git a/cesar/cp/av/sta/action/info.h b/cesar/cp/av/sta/action/info.h
new file mode 100644
index 0000000000..b1fdfe03c9
--- /dev/null
+++ b/cesar/cp/av/sta/action/info.h
@@ -0,0 +1,53 @@
+#ifndef cp_av_sta_action_info_h
+#define cp_av_sta_action_info_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/info.h
+ * \brief STA action, information gathering definitions.
+ * \ingroup cp_av_sta_action
+ *
+ * Information gathering
+ * =====================
+ *
+ * Gather information from other stations. Use CM_UNASSOCIATED_STA.IND,
+ * beacons, TEI maps...
+ */
+
+BEGIN_DECLS
+
+/**
+ * Process a CC_SET_TEI_MAP.IND, 11.2.35.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ *
+ * The CCo send an update of the AVLN list of STA. According to the mode,
+ * update the whole list, add or remove a STA.
+ *
+ * Update:
+ * - STA mgr.
+ */
+void
+cp_av_sta_action_process_cc_set_tei_map_ind (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Process a CM_UNASSOCIATED_STA.IND, 11.5.1.
+ * \param ctx control plane context
+ * \param mme received MME handle
+ *
+ * Update the STA list.
+ *
+ * Update:
+ * - STA mgr.
+ */
+void
+cp_av_sta_action_process_cm_unassociated_sta_ind (cp_t *ctx, cp_mme_rx_t *mme);
+
+END_DECLS
+
+#endif /* cp_av_sta_action_info_h */
diff --git a/cesar/cp/av/sta/action/misc.h b/cesar/cp/av/sta/action/misc.h
new file mode 100644
index 0000000000..c5095132d9
--- /dev/null
+++ b/cesar/cp/av/sta/action/misc.h
@@ -0,0 +1,41 @@
+#ifndef cp_av_sta_action_misc_h
+#define cp_av_sta_action_misc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/misc.h
+ * \brief STA action, miscellaneous definitions.
+ * \ingroup cp_av_sta_action
+ *
+ */
+#include "cp/sta/action/misc.h"
+
+BEGIN_DECLS
+
+void
+cp_av_sta_action_process_cc_discover_list_req (cp_t *ctx, cp_mme_rx_t *rx_mme);
+
+/**
+ * Join timeout expires or SC failed common function.
+ * \param ctx the module context.
+ * \param branch_no_sta_no_avln the branch to follow when no STA and no AVLN
+ * is present.
+ * \param branch_no_sta_avln the branch to follow when no STA is present but
+ * an AVLN exists.
+ * \param branch_sta the branch to follow when a STA is present.
+ */
+void
+cp_av_sta_action_poweron__cco__join_timeout_sc_failed (
+ cp_t *ctx,
+ cp_fsm_branch_t branch_no_sta_no_avln,
+ cp_fsm_branch_t branch_no_sta_avln,
+ cp_fsm_branch_t branch_sta);
+
+END_DECLS
+
+#endif /* cp_sta_action_misc_h */
diff --git a/cesar/cp/av/sta/action/poweron.h b/cesar/cp/av/sta/action/poweron.h
new file mode 100644
index 0000000000..158c7430de
--- /dev/null
+++ b/cesar/cp/av/sta/action/poweron.h
@@ -0,0 +1,240 @@
+#ifndef cp_av_sta_action_poweron_h
+#define cp_av_sta_action_poweron_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/poweron.h
+ * \brief STA action, power on procedure related definitions.
+ * \ingroup cp_av_sta_action
+ *
+ * Power-on procedure
+ * ==================
+ *
+ * This part handle power-on procedure, neighbourhood discovery and
+ * association decision. A state machine is used to handle the different
+ * states:
+ *
+ * \image html poweron.png "Power-on state machine"
+ *
+ * - (1) send CM_UNASSOCIATED_STA.IND
+ * - (2) select an AVLN to track
+ * - (3) restart join timer
+ *
+ * Related: 7.1.
+ */
+
+BEGIN_DECLS
+
+/**
+ * Handle entering POWERON.
+ * \param ctx control plane context
+ *
+ * Start the BTT and USTT timers.
+ */
+void
+cp_av_sta_action_poweron__poweron__enter (cp_t *ctx);
+
+/**
+ * Handle leaving POWERON.
+ * \param ctx control plane context
+ *
+ * Stop BTT and USTT timers.
+ */
+void
+cp_av_sta_action_poweron__poweron__leave (cp_t *ctx);
+
+/**
+ * Handle POWERON => USTT TIMEOUT.
+ * \param ctx control plane context
+ *
+ * If there is at least one AVLN in the discovered list, send a
+ * CM_UNASSOCIATED_STA.IND, then restart the USTT timer with a random value
+ * (in the right range).
+ */
+void
+cp_av_sta_action_poweron__poweron__ustt_timeout (cp_t *ctx);
+
+/**
+ * Handle POWERON => BTT TIMEOUT.
+ * \param ctx control plane context
+ *
+ * No beacon has been received during the BTT timer. Look in the discovered
+ * STA list to see if there is a NID match. If a NID match and the station
+ * should become CCo, go to CCO state.
+ *
+ * In other cases, if there is at least one AVLN in the discovered list, go to
+ * USTA state. If there is no AVLN discovered, go to UCCO state.
+ */
+void
+cp_av_sta_action_poweron__poweron__btt_timeout (cp_t *ctx);
+
+/**
+ * Handle POWERON => BEACON.
+ * \param ctx control plane context
+ * \param beacon received beacon
+ * \param net STA net
+ * \param sta STA emitting the beacon
+ *
+ * When a beacon is received, if NID matches, go to corresponding JOINING
+ * states and start the association procedure. In the other case, select an
+ * AVLN to track in the list of discovered AVLN and continue searching.
+ */
+void
+cp_av_sta_action_poweron__poweron__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle POWERON_JOINING => LEFT.
+ * \param ctx control plane context
+ *
+ * Select an AVLN to track and continue searching.
+ */
+void
+cp_av_sta_action_poweron__poweron_joining__left (cp_t *ctx);
+
+/**
+ * Handle POWERON_JOINING, USTA_JOINING => TO_STOP.
+ * \param ctx control plane context
+ */
+void
+cp_av_sta_action_poweron__joining__to_stop (cp_t *ctx);
+
+/**
+ * Handle entering USTA.
+ * \param ctx control plane context
+ *
+ * Start the USTT timer.
+ */
+void
+cp_av_sta_action_poweron__usta__enter (cp_t *ctx);
+
+/**
+ * Handle entering USTA_JOINING.
+ * \param ctx control plane context
+ */
+void
+cp_av_sta_action_poweron__usta_joining__enter (cp_t *ctx);
+
+/**
+ * Handle leaving USTA.
+ * \param ctx control plane context
+ *
+ * Stop the USTT timer.
+ */
+void
+cp_av_sta_action_poweron__usta__leave (cp_t *ctx);
+
+/**
+ * Handle USTA => USTT TIMEOUT.
+ * \param ctx control plane context
+ *
+ * If there is at least one AVLN in the discovered list, send a
+ * CM_UNASSOCIATED_STA.IND, then restart the USTT timer with a random value
+ * (in the right range).
+ */
+void
+cp_av_sta_action_poweron__usta__ustt_timeout (cp_t *ctx);
+
+/**
+ * Handle USTA => BEACON.
+ * \param ctx control plane context
+ * \param beacon received beacon
+ * \param net STA net
+ * \param sta STA emitting the beacon
+ *
+ * When a beacon is received, if NID matches, go to corresponding JOINING
+ * states and start the association procedure. In the other case, select an
+ * AVLN to track in the list of discovered AVLN and continue searching.
+ */
+void
+cp_av_sta_action_poweron__usta__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle USTA => USTA IND.
+ * \param ctx control plane context
+ * \param net STA net
+ * \param sta STA emitting CM_UNASSOCIATED_STA.IND
+ *
+ * If the NID match and the station should become CCo go to CCO state.
+ */
+void
+cp_av_sta_action_poweron__usta__usta_ind (cp_t *ctx, cp_net_t *net,
+ cp_sta_t *sta);
+
+/**
+ * Handle USTA_JOINING => LEFT.
+ * \param ctx control plane context
+ *
+ * Select an AVLN to track and continue searching.
+ */
+void
+cp_av_sta_action_poweron__usta_joining__left (cp_t *ctx);
+
+/**
+ * Handle UCCO => BEACON.
+ * \param ctx control plane context
+ * \param beacon received beacon
+ * \param net STA net
+ * \param sta STA emitting the beacon
+ *
+ * Disable discover beacon emission.
+ */
+void
+cp_av_sta_action_poweron__ucco__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle STA => TO_STOP.
+ * \param ctx control plane context
+ */
+void
+cp_av_sta_action_poweron__sta__to_stop (cp_t *ctx);
+
+/**
+ * Handle entering CCO.
+ * \param ctx control plane context
+ *
+ * Start join timer.
+ */
+void
+cp_av_sta_action_poweron_cco__enter (cp_t *ctx);
+
+/**
+ * Handle leaving CCO.
+ * \param ctx control plane context
+ *
+ * Stop join timer.
+ */
+void
+cp_av_sta_action_poweron_cco__leave (cp_t *ctx);
+
+/**
+ * Handle CCO => JOIN TIMEOUT.
+ * \param ctx control plane context
+ *
+ * If there is no associated STA, stop being a CCo. In this case, if there is
+ * at least one discovered AVLN, go to USTA state. Else, go to UCCO state.
+ */
+void
+cp_av_sta_action_poweron__cco__join_timeout (cp_t *ctx);
+
+void
+cp_av_sta_action_poweron__idle__enter (cp_t *ctx);
+
+/**
+ * Initialise poweron part.
+ * \param ctx control plane context
+ */
+void
+cp_av_sta_action_poweron_init (cp_t *ctx);
+
+
+END_DECLS
+
+#endif /* cp_av_sta_action_poweron_h */
diff --git a/cesar/cp/av/sta/action/sc.h b/cesar/cp/av/sta/action/sc.h
new file mode 100644
index 0000000000..261a497bfc
--- /dev/null
+++ b/cesar/cp/av/sta/action/sc.h
@@ -0,0 +1,217 @@
+#ifndef cp_av_sta_action_sc_h
+#define cp_av_sta_action_sc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/action/sc.h
+ * \brief STA action, Simple Connect procedure functions declarations.
+ * \ingroup cp_sta_action
+ */
+
+/**
+ * SC FSM is a sub FSM of the CP FSM.
+ * It handles the Simple Connect procedure (association of a STA when it does
+ * not have the NMK of the AVLN.
+ *
+ * The communication between this FSM and the main one, is handled by posting
+ * event. Basically, this FSM starts when you use the
+ * cp_av_sta_action_sc__start_sc_join or cp_av_sta_action_sc__start_sc_add which
+ * posts the event sc_start_add or sc_start_join.
+ */
+
+#include "cp/sta/mgr/sta_mgr.h"
+
+BEGIN_DECLS
+
+/**
+ * Start the SC FSM in SC_JOIN.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__start_sc_join (cp_t *ctx);
+
+/**
+ * Start the SC FSM in SC_ADD.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__start_sc_add (cp_t *ctx);
+
+/**
+ * SC_IDLE enter function.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__sc_idle__enter (cp_t *ctx);
+
+/**
+ * SC_IDLE leave function.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__sc_idle__leave (cp_t *ctx);
+
+/**
+ * SC_JOIN enter function.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__sc_join__enter (cp_t *ctx);
+
+/**
+ * SC_JOIN leave function.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__sc_join__leave (cp_t *ctx);
+
+/**
+ * Handle * => SC_TIMEOUT.
+ * \param ctx control plane context.
+ *
+ * SC Procedure is aborted, tell it to the CP FSM and stop association FSM.
+ */
+void
+cp_av_sta_action_sc__sc_timeout (cp_t *ctx);
+
+/**
+ * Handle SC_ADD => SC_TIMEOUT.
+ * \param ctx control plane context.
+ *
+ * SC Procedure is aborded, tell it to the CP FSM but not to the association
+ * FSM.
+ */
+void
+cp_av_sta_action_sc_add__sc_timeout (cp_t *ctx);
+
+/**
+ * Handle SC_ADD => CM_SC_JOIN.REQ.
+ * \param ctx control plane context.
+ *
+ * If CM_SC_JOIN.REQ is ok, become CCo if we are not on AVLN, send a
+ * CM_SC_JOIN.CNF. Otherwise stay in this state.
+ */
+void
+cp_av_sta_action_sc__sc_add__cm_sc_join_req (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Common handle anywhere => TO_STOP.
+ * \param ctx control plane context.
+ *
+ * Stop timer.
+ */
+void
+cp_av_sta_action_sc__to_stop (cp_t *ctx);
+
+/**
+ * Handle SC_WAIT_PEER_ASSOCIATED => NEW_STA_ASSOCIATED.
+ * \param ctx control plane context.
+ * \param net the network of the newly associated STA.
+ * \param sta the newly associated STA.
+ *
+ * If STA is part of our AVLN, begin UKE, otherwise, stay here.
+ */
+void
+cp_av_sta_action_sc__sc_wait_peer_associated__new_sta_associated (cp_t *ctx,
+ cp_net_t *net,
+ cp_sta_t *sta);
+
+/**
+ * Handle SC_JOIN => CM_SC_JOIN.REQ.
+ * \param ctx control plane context.
+ * \param mme the MME handle.
+ */
+void
+cp_av_sta_action_sc__sc_join__cm_sc_join_req (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle SC_JOIN => CM_SC_JOIN.CNF
+ * \param ctx control plane context.
+ * \param mme the MME handle.
+ */
+void
+cp_av_sta_action_sc__sc_join__cm_sc_join_cnf (cp_t *ctx, cp_mme_rx_t *mme);
+
+/**
+ * Handle SC_JOIN => SC_JOIN_REQ_TIMEOUT.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__sc_join__sc_join_req_timeout (cp_t *ctx);
+
+/**
+ * Handle SC_WAIT_BEACON => BEACON.
+ * \param ctx control plane context.
+ * \param beacon received beacon.
+ * \param net STA net.
+ * \param sta STA emitting the beacon.
+ */
+void
+cp_av_sta_action_sc__sc_wait_beacon__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle SC_BUILDING_TEK => CM_GET_KEY.CNF (PID3)
+ * \param ctx control plane context.
+ * \param mme the MME handle.
+ */
+void
+cp_av_sta_action_sc__sc_building_tek__cm_get_key_cnf_pid3 (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle SC_NMK_EXCHANGE => CM_SET_KEY.CNF (PID3).
+ * \param ctx control plane context.
+ * \param mme the MME handle.
+ */
+void
+cp_av_sta_action_sc__sc_nmk_exchange__cm_set_key_cnf_pid3 (cp_t *ctx,
+ cp_mme_rx_t *mme);
+
+/**
+ * Handle SC_USTA => BEACON.
+ * \param ctx control plane context.
+ * \param beacon received beacon.
+ * \param net STA net.
+ * \param sta STA emitting the beacon.
+ *
+ * Track the AVLN if it is better to track this one.
+ */
+void
+cp_av_sta_action_sc__sc_usta_track_beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle SC_UCCO => BEACON.
+ * \param ctx control plane context
+ * \param beacon received beacon
+ * \param net STA net
+ * \param sta STA emitting the beacon
+ *
+ * Disable discover beacon emission and track the AVLN if it is better to
+ * track this one.
+ */
+void
+cp_av_sta_action_sc__sc_ucco_track_beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta);
+
+/**
+ * Handle SC_STA => avln_failure.
+ * \param ctx controle plane context.
+ *
+ * Emit event "to stop" to stop SC FSM.
+ */
+void
+cp_av_sta_action_sc__sc_sta__avln_failure (cp_t *ctx);
+
+void
+cp_av_sta_action_sc__sc_cco__sc_failed (cp_t *ctx);
+
+END_DECLS
+
+#endif /* cp_av_sta_action_sc_h */
diff --git a/cesar/cp/av/sta/action/src/action.c b/cesar/cp/av/sta/action/src/action.c
new file mode 100644
index 0000000000..f9f44be797
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/action.c
@@ -0,0 +1,122 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/action.c
+ * \brief STA action.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+
+#include "action.h"
+#include "cp/sta/action/action.h"
+
+#include "cp/inc/context.h" // cp_t
+#include "cp/av/cco/bw/bw.h"
+#include "cp/av/sta/mgr/sta_mgr.h"
+#include "ce/tx/tx.h"
+#include "cp/fsm/fsm.h"
+#include "cp/beacon/beacon.h"
+
+/** Delay after the one, the NET is considered worth than an other one.
+ * This delay should be added to the last beacon reception date from the CCo
+ * on the net. */
+#define CP_STA_ACTION_TRACK_EXPIRED_MS 400
+
+void
+cp_av_sta_action_beacon_match_and_join (cp_t *ctx,
+ bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta, bool sc,
+ cp_fsm_branch_t branch_match,
+ cp_fsm_branch_t branch_no_match)
+{
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (ctx);
+ cp_nid_t our_nid = cp_sta_own_data_get_nid (ctx);
+ cp_nid_t its_nid = cp_net_get_nid (ctx, net);
+ u8 its_snid = cp_net_get_snid (ctx, net);
+ /* Does not support proxy networking for the moment, only handle CCo
+ * beacon. */
+ if (cp_sta_get_cco_status (sta))
+ {
+ cp_net_t *net_tracking =
+ cp_sta_mgr_get_avln (ctx, cp_sta_own_data_get_snid (ctx),
+ own_data->nid_track);
+ /* Should we track this beacon? */
+ if (!net_tracking /* Net tracking no more present. */
+ || (its_nid == our_nid /* New net nid match our nid. */
+ && !net->blacklisted /* New net is not blacklisted. */
+ && (own_data->nid_track != our_nid /* Not our nid.*/
+ || net_tracking->blacklisted
+ || less_mod2p32 (
+ net_tracking->beacon_recv_date
+ + MAC_MS_TO_TCK (CP_STA_ACTION_TRACK_EXPIRED_MS),
+ phy_date ()))
+ )
+ )
+ {
+ cp_av_sta_mgr_set_tracking (ctx, its_snid, its_nid);
+ cp_beacon_process_tracked_avln (ctx, beacon, net);
+ }
+ /* The CCo has changed. */
+ else if (net_tracking == net
+ && !beacon->bmis.change_snid.present
+ && cp_net_get_slot_id (ctx, net) == beacon->vf.slotid)
+ {
+ /* station manager stores MAC_BROADCAST if the mac address is
+ * unknown, the tracking system store MAC_ZERO if it does not
+ * track a CCo, so we need to adapt the station's MAC address to
+ * the tracked one. */
+ mac_t cco_mac = cp_sta_get_mac_address (sta) == MAC_BROADCAST ?
+ MAC_ZERO : cp_sta_get_mac_address (sta);
+ if (cco_mac != own_data->cco_mac_addr_track)
+ {
+ /* We can assume this CCo is the new one. */
+ cp_net_set_cco (ctx, net, cp_sta_get_tei (sta));
+ cp_beacon_process_tracked_avln (ctx, beacon, net);
+ }
+ }
+ /* Should we associate? */
+ if (its_nid == our_nid
+ && its_snid == cp_sta_own_data_get_snid (ctx)
+ && !net->blacklisted
+ && cp_beacon_synchronised (ctx))
+ {
+ if (!sc)
+ cp_av_sta_action_assoc_start (ctx, net, sta);
+ else
+ {
+ /* Start assoc procedure. */
+ cp_av_sta_action_sc_assoc_start (ctx, net, sta);
+ /* Inform main FSM we have start SC association procedure. */
+ cp_fsm_trigger_new_event (ctx, bare, sc_succeed);
+ }
+ cp_fsm_branch_ (ctx, branch_match);
+ }
+ else
+ {
+ cp_fsm_branch_ (ctx, branch_no_match);
+ }
+ }
+ else
+ {
+ cp_fsm_branch_ (ctx, branch_no_match);
+ }
+}
+
+void
+cp_av_sta_action_init (cp_t *ctx)
+{
+ cp_sta_action_assoc_init (ctx);
+ /* Initialize the STA action bridge module. */
+ cp_sta_action_bridge_init (ctx);
+ /* Initialize the STA action misc module. */
+ cp_sta_action_misc_init (ctx);
+ /* Create the default allocation schedules. */
+ cp_av_cco_bw_schedules_default (ctx);
+ /* Initialize the STA action poweron module. */
+ cp_av_sta_action_poweron_init (ctx);
+}
diff --git a/cesar/cp/av/sta/action/src/assoc.c b/cesar/cp/av/sta/action/src/assoc.c
new file mode 100644
index 0000000000..8d9cc7c7a0
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/assoc.c
@@ -0,0 +1,815 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/assoc.c
+ * \brief STA action, association related definitions.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+
+#include "action.h"
+#include "cp/sta/action/action.h"
+
+#include "cp/inc/context.h"
+#include "cp/fsm/fsm.h"
+#include "cp/msg/msg.h"
+#include "cp/beacon/beacon.h"
+#include "lib/rnd.h"
+#include "cp/secu/defs.h"
+#include "cp/beacon/beacon.h"
+#include "bsu/bsu.h"
+
+#define RETRY_TIMEOUT_MS 1000
+#define RENEW_MARGIN_MS (5 * 60 * 1000)
+#define LEAVING_TIMEOUT_MS (40 * 3)
+#define LEAVE_WAIT_TIMEOUT_MS 1000
+
+void
+cp_av_sta_action_assoc_init (cp_t *ctx)
+{
+ dbg_assert (ctx);
+}
+
+void
+cp_av_sta_action_sc_assoc_start (cp_t *ctx, cp_net_t *cco_net, cp_sta_t *cco)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (cco_net);
+ /* cco can be NULL. */
+
+ /* Check NID. */
+ dbg_assert (cp_sta_own_data_get_nid (ctx)
+ == cp_net_get_nid (ctx, cco_net));
+
+ /* Do we know the CCo? */
+ if (cco)
+ /* Store CCo peer. */
+ cp_sta_get_peer (cco, &ctx->sta_action.assoc.peer);
+ else
+ {
+ /* Let's try to find the CCo from the net. */
+ cp_sta_t *cco_from_net = cp_net_get_cco (ctx, cco_net);
+ if (cco_from_net)
+ {
+ /* Get peer CCo. */
+ cp_sta_get_peer (cco_from_net, &ctx->sta_action.assoc.peer);
+ /* Release. */
+ slab_release (cco_from_net);
+ }
+ else
+ {
+ /* We do not know the CCo, broadcast to all STA. */
+ ctx->sta_action.assoc.peer = CP_MME_PEER (MAC_BROADCAST,
+ MAC_TEI_UNASSOCIATED);
+ }
+ }
+ ctx->sta_action.assoc.snid = cp_net_get_snid (ctx, cco_net);
+ ctx->sta_action.assoc.retry = 3;
+ /* Trigger to_sc_assoc event. */
+ cp_fsm_trigger_new_event (ctx, bare, to_sc_assoc);
+}
+
+void
+cp_av_sta_action_assoc_start (cp_t *ctx, cp_net_t *cco_net, cp_sta_t *cco)
+{
+ dbg_assert (ctx);
+ dbg_assert (cco_net);
+ dbg_assert (cco);
+ /* Remember CCo to associate with. */
+ dbg_assert (cp_sta_own_data_get_nid (ctx)
+ == cp_net_get_nid (ctx, cco_net));
+ cp_sta_get_peer (cco, &ctx->sta_action.assoc.peer);
+ ctx->sta_action.assoc.snid = cp_net_get_snid (ctx, cco_net);
+ ctx->sta_action.assoc.retry = 3;
+ /* Trigger to_assoc event. */
+ cp_fsm_trigger_new_event (ctx, bare, to_assoc);
+}
+
+void
+cp_av_sta_action_assoc_leave (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Trigger to_leave event. */
+ cp_fsm_trigger_new_event (ctx, bare, to_leave);
+}
+
+void
+cp_av_sta_action_assoc__unassociated__enter (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_sta_own_data_set_authenticated_status (ctx, false);
+ cp_sta_mgr_set_our_avln (ctx, NULL);
+ cp_sta_own_data_set_tei (ctx, 0);
+ cp_fsm_trigger_new_event (ctx, bare, left);
+ /* Reset some parts. */
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (ctx);
+ own->hybrid_mode = MAC_COEXISTENCE_HYBRID_DELIMITERS_MODE;
+}
+
+void
+cp_av_sta_action_assoc__unassociated__to_assoc (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Send association request. */
+ cp_msg_cc_assoc_req_t data = {
+ CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ cp_sta_own_data_get_nid (ctx),
+ CP_CCO_LEVEL,
+ CP_PCO_CAP
+ };
+ cp_msg_cc_assoc_req_send (ctx, &ctx->sta_action.assoc.peer, &data);
+}
+
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__cc_assoc_cnf__common (cp_t *ctx,
+ cp_mme_rx_t *mme,
+ bool sc)
+{
+ cp_msg_cc_assoc_cnf_t cnf;
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ /* Check response. */
+ if ((mme->peer.mac != ctx->sta_action.assoc.peer.mac
+ && ctx->sta_action.assoc.peer.mac != MAC_BROADCAST)
+ || !cp_msg_cc_assoc_cnf_receive (ctx, mme, &cnf)
+ || cnf.nid != cp_sta_own_data_get_nid (ctx)
+ || cnf.snid != ctx->sta_action.assoc.snid)
+ {
+ /* Unrelated message, drop. */
+ if (!sc)
+ cp_fsm_branch (ctx, WAIT_ASSOC_CONF, CC_ASSOC_CNF, unrelated);
+ else
+ cp_fsm_branch (ctx, SC_WAIT_ASSOC_CONF, CC_ASSOC_CNF, unrelated);
+ }
+ else if (cnf.result != CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS)
+ {
+ /* Failure indication. */
+ if (!sc)
+ cp_fsm_branch (ctx, WAIT_ASSOC_CONF, CC_ASSOC_CNF, nok);
+ else
+ cp_fsm_branch (ctx, SC_WAIT_ASSOC_CONF, CC_ASSOC_CNF, nok);
+ }
+ else
+ {
+ cp_net_t *our_net;
+ /* Start lease timer, it can not expire before we go to authenticated
+ * state because authentication timeout is shorter. */
+ int lease_time_ms = cnf.lease_time_min * 60 * 1000 - RENEW_MARGIN_MS;
+ if (lease_time_ms > 0)
+ {
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_renew);
+ cp_sta_core_gen_timed_event (ctx,
+ &ctx->sta_action.assoc.lease_timer,
+ event, lease_time_ms);
+ }
+ /* Update state. */
+ cp_sta_own_data_set_tei (ctx, cnf.sta_tei);
+ our_net = cp_sta_mgr_add_avln (ctx, cnf.snid, cnf.nid);
+ cp_sta_t *cco =
+ cp_sta_mgr_sta_add (ctx, our_net, mme->peer.tei, mme->peer.mac);
+ cp_net_set_cco (ctx, our_net, mme->peer.tei);
+ slab_release (cco);
+ ctx->sta_action.assoc.peer = mme->peer;
+ ctx->sta_action.assoc.snid = cnf.snid;
+ cp_sta_mgr_set_our_avln (ctx, our_net);
+ /* Not in SC procedure. */
+ if (!sc)
+ {
+ /* Send get key request. */
+ cp_msg_cm_get_key_req_t get_key = {
+ .relayed = false, .key_type = CP_MSG_KEY_NEK,
+ .nid = cp_sta_own_data_get_nid (ctx) };
+ cp_secu_protocol_run_new (&ctx->sta_action.assoc.prun, 0,
+ &ctx->rnd);
+ cp_msg_cm_get_key_req_send (ctx, &mme->peer, CP_MME_PEKS_NMK,
+ &ctx->sta_action.assoc.prun, &get_key);
+ /* Change state. */
+ cp_fsm_branch (ctx, WAIT_ASSOC_CONF, CC_ASSOC_CNF, ok);
+ }
+ else
+ {
+ /* In SC procedure. */
+ /* Ensure SC peer is correct, so let's copy it back (to handle TEI
+ * change (UCCO to CCO) and/or MAC change (broadcast). */
+ ctx->sta_action.sc.peer = mme->peer;
+ /* Nothing to send. */
+ /* Change state. */
+ cp_fsm_branch (ctx, SC_WAIT_ASSOC_CONF, CC_ASSOC_CNF, ok);
+ }
+ }
+}
+
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__cc_assoc_cnf (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ cp_av_sta_action_assoc__wait_assoc_cnf__cc_assoc_cnf__common (ctx, mme,
+ false);
+}
+
+void
+cp_av_sta_action_assoc__sc_wait_assoc_cnf__cc_assoc_cnf (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ cp_av_sta_action_assoc__wait_assoc_cnf__cc_assoc_cnf__common (ctx, mme,
+ true);
+}
+
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__timeout_common (cp_t *ctx, bool sc)
+{
+ dbg_assert (ctx);
+ ctx->sta_action.assoc.retry--;
+ if (ctx->sta_action.assoc.retry)
+ {
+ /* Restart timer. */
+ cp_sta_action_assoc__start_retry_timer (ctx);
+ /* Resend association request. */
+
+ cp_av_sta_action_assoc__unassociated__to_assoc (ctx);
+ if (!sc)
+ cp_fsm_branch (ctx, WAIT_ASSOC_CONF, assoc_timeout, retry);
+ else
+ cp_fsm_branch (ctx, SC_WAIT_ASSOC_CONF, assoc_timeout, retry);
+ }
+ else
+ {
+ /* Give up. */
+ if (!sc)
+ cp_fsm_branch (ctx, WAIT_ASSOC_CONF, assoc_timeout, no_retry);
+ else
+ cp_fsm_branch (ctx, SC_WAIT_ASSOC_CONF, assoc_timeout, no_retry);
+ /* Black list the net. */
+ cp_sta_t *sta =
+ cp_sta_mgr_sta_get_from_mac (
+ ctx, ctx->sta_action.assoc.peer.mac);
+ if (sta)
+ {
+ cp_net_t *net = cp_sta_get_net (sta);
+ slab_release (sta);
+ cp_net_blacklisted_status_set (ctx, net, true);
+ }
+ }
+}
+
+void
+cp_av_sta_action_assoc__wait_assoc_cnf__timeout (cp_t *ctx)
+{
+ cp_av_sta_action_assoc__wait_assoc_cnf__timeout_common (ctx, false);
+}
+
+void
+cp_av_sta_action_assoc__sc_wait_assoc_cnf__timeout (cp_t *ctx)
+{
+ cp_av_sta_action_assoc__wait_assoc_cnf__timeout_common (ctx, true);
+}
+
+void
+cp_av_sta_action_assoc__cm_get_key_cnf__common (cp_t *ctx, cp_mme_rx_t
+ *mme, bool sc)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ cp_msg_cm_get_key_cnf_t cnf;
+ /* Check response. */
+ if (!cp_mme_peer_cmp (&mme->peer, &ctx->sta_action.assoc.peer)
+ || !cp_msg_cm_get_key_cnf_receive (ctx, mme, &cnf)
+ || (!cp_secu_protocol_check
+ (&ctx->sta_action.assoc.prun, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_LAST))
+ || cnf.nid != cp_sta_own_data_get_nid (ctx)
+ || cnf.key_type != CP_MSG_KEY_NEK
+ || (sc && mme->peks != CP_MME_PEKS_NMK))
+ {
+ /* Unrelated message, drop. */
+ if (!sc)
+ cp_fsm_branch (ctx, ASSOCIATED, CM_GET_KEY_CNF_PID0, unrelated);
+ else
+ cp_fsm_branch (ctx, SC_NMK_EXCHANGED, CM_GET_KEY_CNF_PID0, unrelated);
+ }
+ else if (cnf.result != CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED)
+ {
+ /* Failure indication. */
+ if (!sc)
+ cp_fsm_branch (ctx, ASSOCIATED, CM_GET_KEY_CNF_PID0, nok);
+ else
+ cp_fsm_branch (ctx, SC_NMK_EXCHANGED, CM_GET_KEY_CNF_PID0, nok);
+ /* Black list the net. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_net_blacklisted_status_set (ctx, our_net, true);
+ }
+ else
+ {
+ /* Use the new key. */
+ cp_sta_own_data_set_authenticated_status (ctx, true);
+ cp_beacon_change_nek (ctx, cnf.eks, cnf.key, true);
+ /* Signal joined state. */
+ cp_fsm_trigger_new_event (ctx, bare, joined);
+ /* Reset beacon loss counter. */
+ ctx->sta_action.assoc.beacon_loss = 0;
+ if (!sc)
+ cp_fsm_branch (ctx, ASSOCIATED, CM_GET_KEY_CNF_PID0, ok);
+ else
+ cp_fsm_branch (ctx, SC_NMK_EXCHANGED, CM_GET_KEY_CNF_PID0, ok);
+ }
+}
+
+void
+cp_av_sta_action_assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0 (cp_t *ctx,
+ cp_mme_rx_t *
+ mme)
+{
+ cp_av_sta_action_assoc__cm_get_key_cnf__common (ctx, mme, true);
+}
+
+void
+cp_av_sta_action_assoc__authenticated__cm_get_key_cnf_pid_1 (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ cp_msg_cm_get_key_cnf_t cnf;
+
+ /* Get our cco peer. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+
+ /* Check response. */
+ if (cp_mme_peer_cmp (&mme->peer, &peer)
+ && cp_msg_cm_get_key_cnf_receive (ctx, mme, &cnf)
+ && (cp_secu_protocol_check
+ (&ctx->sta_action.nek_prun, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_LAST))
+ && cnf.nid == cp_sta_own_data_get_nid (ctx)
+ && cnf.key_type == CP_MSG_KEY_NEK
+ && mme->peks == CP_MME_PEKS_NMK
+ && cnf.result == CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED)
+ {
+ /* Use the new key. */
+ cp_beacon_change_nek (ctx, cnf.eks, cnf.key, false);
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__nek_request (cp_t *ctx)
+{
+ cp_msg_cm_get_key_req_t get_key = {
+ .relayed = false, .key_type = CP_MSG_KEY_NEK,
+ .nid = cp_sta_own_data_get_nid (ctx) };
+ cp_mme_peer_t cco_peer;
+ cp_net_get_cco_peer (ctx, cp_sta_mgr_get_our_avln (ctx),
+ &cco_peer);
+ cp_secu_protocol_run_new (&ctx->sta_action.nek_prun,
+ 1, &ctx->rnd);
+
+ cp_msg_cm_get_key_req_send (ctx, &cco_peer,
+ CP_MME_PEKS_NMK,
+ &ctx->sta_action.nek_prun,
+ &get_key);
+}
+
+void
+cp_av_sta_action_assoc__associated__cm_get_key_cnf_pid_0 (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ cp_av_sta_action_assoc__cm_get_key_cnf__common (ctx, mme, false);
+}
+
+void
+cp_av_sta_action_assoc__associated__timeout (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Stop lease timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.assoc.lease_timer);
+}
+
+void
+cp_av_sta_action_assoc__associated__to_leave (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Stop lease timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.assoc.lease_timer);
+}
+
+void
+cp_av_sta_action_assoc__sc_associated__cm_get_key_req_pid_3 (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ cp_msg_cm_get_key_req_t req;
+ /* Check response (note, the MME should be sent by the STA with which are
+ * doing the SC (it can be different from the CCo); */
+ if (!cp_mme_peer_cmp (&mme->peer, &ctx->sta_action.sc.peer)
+ || !cp_msg_cm_get_key_req_receive (ctx, mme, &req)
+ || (!cp_secu_protocol_check
+ (NULL, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEW))
+ || (req.nid != cp_sta_own_data_get_nid (ctx))
+ || (req.key_type != CP_MSG_KEY_HASH_KEY)
+ || (mme->peks != CP_MME_PEKS_SPC_NOT_EMBEDDED)
+ )
+ {
+ /* Unrelated message, drop it. */
+ cp_fsm_branch (ctx, SC_ASSOCIATED, CM_GET_KEY_REQ_PID3, unrelated);
+ }
+ else
+ {
+ /* Message is valid, reply. */
+ /* Copy security protocol run for authentication. */
+ ctx->sta_action.assoc.prun = mme->prun;
+ /* Prepare message. */
+ cp_msg_cm_get_key_cnf_t cnf;
+ cnf.result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED;
+ cnf.key_type = CP_MSG_KEY_HASH_KEY;
+ cnf.nid = cp_sta_own_data_get_nid (ctx);
+ cnf.eks = CP_MME_PEKS_TEK_MIN;
+ /* Generate an hash key. */
+ cp_secu_generate_hash (ctx, lib_rnd32 (&ctx->rnd), (u8 *) cnf.hash_key,
+ CP_SECU_HASH_KEY_FOR_TEK_SIZE);
+ /* Generate TEK with hash key from CM_HET_KEY REQ and CNF. */
+ cp_secu_tek_gen (req.hash_key, cnf.hash_key,
+ &ctx->sta_action.sc.tek);
+ /* Send CM_GET_KEY.CNF. */
+ cp_secu_protocol_next (&ctx->sta_action.assoc.prun, &ctx->rnd, false);
+ cp_msg_cm_get_key_cnf_send (ctx, &ctx->sta_action.sc.peer,
+ CP_MME_PEKS_SPC_NOT_EMBEDDED,
+ &ctx->sta_action.assoc.prun,
+ &cnf);
+ /* Set TEK for encryption/decryption of cm_encrypted payload. */
+ cp_sta_own_data_set_tek (ctx, ctx->sta_action.sc.tek);
+ cp_fsm_branch (ctx, SC_ASSOCIATED, CM_GET_KEY_REQ_PID3, ok);
+ }
+}
+
+void
+cp_av_sta_action_assoc__sc_tek_exchanged__cm_set_key_req_pid_3 (cp_t *ctx,
+ cp_mme_rx_t
+ *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ cp_msg_cm_set_key_req_t req;
+ /* Check response (note, the MME should be sent by the STA with which are
+ * doing the SC (it can be different from the CCo); */
+ if (!cp_mme_peer_cmp (&mme->peer, &ctx->sta_action.sc.peer)
+ || !cp_msg_cm_set_key_req_receive (ctx, mme, &req)
+ || (!cp_secu_protocol_check
+ (&ctx->sta_action.assoc.prun, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEXT))
+ || (req.nid != cp_sta_own_data_get_nid (ctx))
+ || (req.key_type != CP_MSG_KEY_NMK)
+ )
+ {
+ /* Unrelated message, drop it. */
+ cp_fsm_branch (ctx, SC_TEK_EXCHANGED, CM_SET_KEY_REQ_PID3, unrelated);
+ }
+ else
+ {
+ /* Message is valid. */
+ /* Set NMK. */
+ cp_sta_own_data_set_nmk (
+ ctx,
+ req.new_key,
+ CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_SECURITY_LEVEL);
+ /* Copy security protocol run for authentication. */
+ ctx->sta_action.assoc.prun = mme->prun;
+ /* Prepare message for reply. */
+ cp_msg_cm_set_key_cnf_t cnf;
+ cnf.result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS;
+ cnf.cco_cap = CP_CCO_LEVEL;
+ /* Send CM_SET_KEY.CNF. */
+ cp_secu_protocol_next (&ctx->sta_action.assoc.prun, &ctx->rnd, true);
+ cp_msg_cm_set_key_cnf_send (ctx, &ctx->sta_action.sc.peer,
+ CP_MME_PEKS_NMK,
+ &ctx->sta_action.assoc.prun,
+ &cnf);
+ /* Start authentication. */
+ cp_msg_cm_get_key_req_t get_key = {
+ .relayed = false, .key_type = CP_MSG_KEY_NEK,
+ .nid = cp_sta_own_data_get_nid (ctx) };
+ cp_secu_protocol_run_new (&ctx->sta_action.assoc.prun, 0,
+ &ctx->rnd);
+ cp_msg_cm_get_key_req_send (ctx, &ctx->sta_action.assoc.peer,
+ CP_MME_PEKS_NMK,
+ &ctx->sta_action.assoc.prun, &get_key);
+ cp_fsm_branch (ctx, SC_TEK_EXCHANGED, CM_SET_KEY_REQ_PID3, ok);
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__leave (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Stop lease timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.assoc.lease_timer);
+}
+
+void
+cp_av_sta_action_assoc__authenticated__renew (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Restart timer. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_renew);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.assoc.lease_timer,
+ event, RENEW_MARGIN_MS / 2);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+ /* Send CC_ASSOC.REQ to renew lease. */
+ cp_msg_cc_assoc_req_t req = {
+ CP_MSG_CC_ASSOC_REQ_TYPE_RENEW,
+ cp_sta_own_data_get_nid (ctx),
+ CP_CCO_LEVEL, CP_PCO_CAP
+ };
+ cp_msg_cc_assoc_req_send (ctx, &peer, &req);
+}
+
+void
+cp_av_sta_action_assoc__authenticated__cc_assoc_cnf (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+ /* Check received message. */
+ cp_msg_cc_assoc_cnf_t cnf;
+ if (cp_mme_peer_cmp (&mme->peer, &peer)
+ && cp_msg_cc_assoc_cnf_receive (ctx, mme, &cnf)
+ && cnf.result == CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS
+ && cnf.nid == cp_sta_own_data_get_nid (ctx))
+ {
+ /* Update lease. */
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.assoc.lease_timer);
+ int lease_time_ms = cnf.lease_time_min * 60 * 1000 - RENEW_MARGIN_MS;
+ if (lease_time_ms > 0)
+ {
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_renew);
+ cp_sta_core_gen_timed_event (ctx,
+ &ctx->sta_action.assoc.lease_timer,
+ event, lease_time_ms);
+ }
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__cm_set_key_req_pid_1 (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+ /* Check received message. */
+ cp_msg_cm_set_key_req_t req;
+
+ if (cp_mme_peer_cmp (&mme->peer, &peer)
+ && cp_msg_cm_set_key_req_receive (ctx, mme, &req)
+ && req.nid == cp_sta_own_data_get_nid (ctx))
+ {
+ if ((req.key_type == CP_MSG_KEY_NEK)
+ && (mme->peks == CP_MME_PEKS_NMK)
+ && (cp_secu_protocol_check
+ (&ctx->sta_action.nek_prun, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEXT)))
+ {
+ ctx->sta_action.nek_prun = mme->prun;
+ /* Send response. */
+ cp_msg_cm_set_key_cnf_t cnf = {
+ CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ CP_CCO_LEVEL };
+ cp_secu_protocol_next (&ctx->sta_action.nek_prun, &ctx->rnd,
+ true);
+ cp_msg_cm_set_key_cnf_send (ctx, &peer, CP_MME_PEKS_NMK,
+ &ctx->sta_action.nek_prun,
+ &cnf);
+ /* Update NEK. */
+ cp_beacon_change_nek (ctx, req.new_eks, req.new_key, false);
+ }
+ else if ((req.key_type == CP_MSG_KEY_NONCE_ONLY)
+ && (mme->peks == CP_MME_PEKS_SPC_NOT_EMBEDDED
+ || mme->peks == CP_MME_PEKS_NONE)
+ && (cp_secu_protocol_check
+ (NULL, &mme->prun, CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEW)))
+ {
+ /* Send response. */
+ cp_msg_cm_set_key_cnf_t cnf = {
+ CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ CP_CCO_LEVEL };
+
+ ctx->sta_action.nek_prun = mme->prun;
+ cp_secu_protocol_next (&ctx->sta_action.nek_prun, &ctx->rnd,
+ false);
+ ctx->sta_action.nek_prun.my_nonce = lib_rnd32 (&ctx->rnd);
+ cp_msg_cm_set_key_cnf_send (ctx, &peer, mme->peks,
+ &ctx->sta_action.nek_prun,
+ &cnf);
+ }
+ }
+ else
+ {
+ /* Send response. */
+ cp_msg_cm_set_key_cnf_t cnf = {
+ CP_MSG_CM_SET_KEY_CNF_RESULT_FAILURE,
+ CP_CCO_LEVEL };
+ cp_secu_protocol_run_t prun = mme->prun;
+ prun.my_nonce = lib_rnd32 (&ctx->rnd);
+ cp_secu_protocol_next (&prun, &ctx->rnd, true);
+ cp_msg_cm_set_key_cnf_send (ctx, &peer, CP_MME_PEKS_NONE, &prun,
+ &cnf);
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__to_leave (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ /* If we were the CCo and we cannot provide the CCo role to another
+ * station (Handover failure because no station were authenticated in the
+ * AVLN) we must not send any MME to the CCo. */
+ cp_sta_t *cco = cp_net_get_cco (ctx, our_net);
+ if (cco)
+ {
+ cp_mme_peer_t peer;
+ cp_sta_get_peer (cco, &peer);
+ /* Start timer. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_assoc_timeout);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.assoc.timer, event,
+ LEAVING_TIMEOUT_MS);
+ /* Send leave request. */
+ cp_msg_cc_leave_req_send (ctx, &peer,
+ CP_MSG_CC_LEAVE_REQ_REASON_USER_REQUEST);
+ slab_release (cco);
+ /* Branch to the LEAVING state. */
+ cp_fsm_branch (ctx, AUTHENTICATED, to_leave, cco);
+ }
+ else
+ {
+ /* Branch to the UNASSOCIATED state. */
+ cp_fsm_branch (ctx, AUTHENTICATED, to_leave, no_cco);
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__cc_leave_ind (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+ /* Check received message. */
+ enum cp_msg_cc_leave_ind_reason_t reason;
+ cp_nid_t nid;
+ if (cp_mme_peer_cmp (&mme->peer, &peer)
+ && cp_msg_cc_leave_ind_receive (ctx, mme, &reason, &nid)
+ && nid == cp_sta_own_data_get_nid (ctx))
+ {
+ cp_msg_cc_leave_rsp_send (ctx, &mme->peer);
+ cp_fsm_branch (ctx, AUTHENTICATED, CC_LEAVE_IND, ok);
+ }
+ else
+ {
+ cp_fsm_branch (ctx, AUTHENTICATED, CC_LEAVE_IND, nok);
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__beacon (cp_t *ctx,
+ bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ if (cp_net_get_nid (ctx, net) == cp_sta_own_data_get_nid (ctx)
+ && cp_net_get_snid (ctx, net) == cp_sta_own_data_get_snid (ctx))
+ {
+ /* Only on central beacon, no support for proxy networking. */
+ if (cp_sta_get_cco_status (sta))
+ {
+ ctx->sta_action.assoc.beacon_loss = 0;
+ }
+ }
+}
+
+void
+cp_av_sta_action_assoc__authenticated__beacon_not_received (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ ctx->sta_action.assoc.beacon_loss++;
+ if (ctx->sta_action.assoc.beacon_loss > CP_MAX_NO_BEACON)
+ {
+ cp_fsm_trigger_new_event (ctx, bare, avln_failure);
+ cp_fsm_branch (ctx, AUTHENTICATED, BEACON_NOT_RECEIVED, avln_failure);
+ }
+ else
+ cp_fsm_branch (ctx, AUTHENTICATED, BEACON_NOT_RECEIVED, else);
+}
+
+void
+cp_av_sta_action_assoc__leaving__cc_leave_cnf (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+ /* Check received message. */
+ if (cp_mme_peer_cmp (&mme->peer, &peer))
+ {
+ /* Ignore bad MME (confirmation is sufficient, we do not expect any
+ * parameter). */
+ cp_msg_cc_leave_cnf_receive (ctx, mme);
+ /* Stop timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.assoc.timer);
+ cp_fsm_branch (ctx, LEAVING, CC_LEAVE_CNF, ok);
+ }
+ else
+ {
+ cp_fsm_branch (ctx, LEAVING, CC_LEAVE_CNF, unrelated);
+ }
+}
+
+void
+cp_av_sta_action_assoc__leaving__timeout (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Get our CCo. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_mme_peer_t peer;
+ cp_net_get_cco_peer (ctx, our_net, &peer);
+ /* Send leave request again. */
+ cp_msg_cc_leave_req_send (ctx, &peer,
+ CP_MSG_CC_LEAVE_REQ_REASON_USER_REQUEST);
+}
+
+void
+cp_av_sta_action_assoc__leave_wait__enter (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Start timer. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_assoc_timeout);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.assoc.timer, event,
+ LEAVE_WAIT_TIMEOUT_MS);
+}
+
+void
+cp_av_sta_action_assoc__leave_wait__timeout (cp_t *ctx)
+{
+ dbg_assert (ctx);
+}
+
+void
+cp_av_sta_action_unassoc__unassoc__enter (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ bsu_beacon_t beacon;
+ /* Update the BSU. */
+ cp_beacon_fill (ctx, &beacon);
+ bsu_update (ctx->bsu, &beacon, BSU_UPDATE_STA_TYPE_STA);
+}
+
+void
+cp_av_sta_action_assoc__start_retry_timer (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_assoc_timeout);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.assoc.timer, event,
+ RETRY_TIMEOUT_MS);
+}
+
diff --git a/cesar/cp/av/sta/action/src/drv.c b/cesar/cp/av/sta/action/src/drv.c
new file mode 100644
index 0000000000..739c04568d
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/drv.c
@@ -0,0 +1,182 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/drv.c
+ * \brief STA action, driver related definitions.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+
+#include "cp/inc/context.h"
+#include "cp/msg/msg.h"
+#include "cp/fsm/fsm.h"
+
+#include "cp/av/sta/action/sc.h"
+#include "cp/sta/action/drv.h"
+#include "cp/av/sta/action/drv.h"
+
+void
+cp_av_sta_action_drv__usta__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ bool sc_join;
+
+ /* Decode driver MME. */
+ cp_sta_action_drv__drv_sta_sc_common (ctx, mme, true, &sc_join);
+ if (sc_join)
+ {
+ /* Start SC JOIN procedure. */
+ cp_av_sta_action_sc__start_sc_join (ctx);
+ }
+ else
+ {
+ /* Start SC ADD procedure. */
+ cp_av_sta_action_sc__start_sc_add (ctx);
+ }
+}
+
+void
+cp_av_sta_action_drv__ucco__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ bool sc_join;
+
+ /* Decode driver MME. */
+ cp_sta_action_drv__drv_sta_sc_common (ctx, mme, true, &sc_join);
+ if (sc_join)
+ {
+ /* Start SC JOIN procedure. */
+ cp_av_sta_action_sc__start_sc_join (ctx);
+ }
+ else
+ {
+ /* Start SC ADD procedure. */
+ cp_av_sta_action_sc__start_sc_add (ctx);
+ }
+}
+
+void
+cp_av_sta_action_drv__cco__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ bool sc_join;
+
+ /* Decode driver MME. */
+ cp_sta_action_drv__drv_sta_sc_common (ctx, mme, false, &sc_join);
+ if (!sc_join)
+ {
+ /* Start SC ADD procedure. */
+ cp_av_sta_action_sc__start_sc_add (ctx);
+ cp_fsm_branch (ctx, CCO, DRV_STA_SC_REQ, sc_add);
+ }
+ else
+ {
+ /* SC JOIN disabled. */
+ cp_fsm_branch (ctx, CCO, DRV_STA_SC_REQ, sc_join);
+ }
+}
+
+void
+cp_av_sta_action_drv__sta__drv_sta_sc (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ bool sc_join;
+
+ cp_sta_action_drv__drv_sta_sc_common (ctx, mme, false, &sc_join);
+ if (!sc_join)
+ {
+ /* Start SC ADD procedure. */
+ cp_av_sta_action_sc__start_sc_add (ctx);
+ cp_fsm_branch (ctx, STA, DRV_STA_SC_REQ, sc_add);
+ }
+ else
+ {
+ /* SC JOIN disabled. */
+ cp_fsm_branch (ctx, STA, DRV_STA_SC_REQ, sc_join);
+ }
+}
+
+void
+cp_av_sta_action_drv__many__drv_sta_sc__failure (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ cp_msg_drv_any_cnf_send (ctx, &mme->peer, DRV_STA_SC_CNF,
+ CP_MSG_DRV_RESULT_FAILURE);
+}
+
+void
+cp_av_sta_action_drv__stopped__drv_sta_set_tonemask_req (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ u32 tonemask[PHY_TONEMASK_WORDS];
+ bool ok = cp_msg_drv_sta_set_tonemask_req_receive (ctx, mme, tonemask);
+ if (ok)
+ {
+ /* Commit to mac configuration and update tonemask informations. */
+ memcpy (ctx->mac_config->tonemask_info.tonemask, tonemask,
+ sizeof (tonemask));
+ tonemask_update (&ctx->mac_config->tonemask_info);
+ /* Tonemask will be programmed once the PBProc is activated. */
+ }
+ cp_msg_drv_any_cnf_send (ctx, &mme->peer, DRV_STA_SET_TONEMASK_CNF,
+ ok ? CP_MSG_DRV_RESULT_SUCCESS
+ : CP_MSG_DRV_RESULT_FAILURE);
+}
+
+void
+cp_av_sta_action_drv__stopped__drv_sta_set_key_req (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ cp_key_t nmk;
+ enum cp_msg_drv_sta_set_key_type_t type;
+ cp_nid_t nid;
+ cp_security_level_t sl;
+
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ /* Try to decode the DRV MME. */
+ if (cp_msg_drv_sta_set_key_req_receive (ctx, mme, &nmk, &type, &nid, &sl))
+ {
+ /* We need to have a NID; let's build it if we do not have one. */
+ if (type == CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_SECURITY_LEVEL)
+ {
+ /* Build NID from SL and NMK. */
+ nid = cp_secu_nmk2nid (ctx, nmk, sl);
+ }
+
+ /* Set the NMK. */
+ uint i;
+ cp_key_t current_key = cp_sta_own_data_get_nmk (ctx);
+
+ for (i = 0; i < COUNT(nmk.key) ;i++)
+ if (nmk.key[i] != current_key.key[i])
+ break;
+
+ if ((i < COUNT(nmk.key)) || (nid != cp_sta_own_data_get_nid (ctx)))
+ {
+ /** save parameters as new ones. */
+ ctx->sta_action.poweron.enter.need_set = true;
+ ctx->sta_action.poweron.enter.nmk = nmk;
+ ctx->sta_action.poweron.enter.type = type;
+ ctx->sta_action.poweron.enter.nid = nid;
+
+ /* Leave current avln to restart association. */
+ cp_fsm_trigger_new_event (ctx, bare, to_stop);
+ }
+
+ /* Reply with success. */
+ cp_msg_drv_any_cnf_send (ctx, &mme->peer, DRV_STA_SET_KEY_CNF,
+ CP_MSG_DRV_RESULT_SUCCESS);
+ }
+ else
+ {
+ /* Error in decoding, let's reply with an error. */
+ cp_msg_drv_any_cnf_send (ctx, &mme->peer, DRV_STA_SET_KEY_CNF,
+ CP_MSG_DRV_RESULT_FAILURE);
+ }
+}
diff --git a/cesar/cp/av/sta/action/src/handover.c b/cesar/cp/av/sta/action/src/handover.c
new file mode 100644
index 0000000000..222f5ac983
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/handover.c
@@ -0,0 +1,220 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/handover.c
+ * \brief Handover functions.
+ * \ingroup cp_av_sta_action
+ *
+ */
+#include "common/std.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/sta/core/core.h"
+#include "cp/msg/msg.h"
+#include "cp/fsm/fsm.h"
+#include "cp/defs.h"
+
+#include "cp/inc/context.h"
+#include "cp/cco/action/cco_action.h"
+#include "cp/sta/action/inc/context.h"
+#include "cp/av/sta/action/handover.h"
+#include "cp/av/sta/action/assoc.h"
+#include "cp/av/beacon/beacon.h"
+#include "cp/av/cco/action/cco_action.h"
+
+void
+cp_av_sta_action_handover__handover (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ cp_net_t *net;
+ cp_sta_t *sta;
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ net = cp_sta_mgr_get_our_avln (ctx);
+ sta = cp_sta_mgr_sta_add (ctx, net, mme->peer.tei, mme->peer.mac);
+ cp_sta_set_authenticated (ctx, sta, true);
+ cp_net_set_cco (ctx, net, mme->peer.tei);
+
+ slab_release (sta);
+
+ cp_fsm_trigger_new_event (ctx, mme, STA_HANDOVER_START, mme);
+}
+
+void
+cp_av_sta_action_handover__start (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ cp_msg_cc_handover_req_soft_hard_t soft_hard = 0;
+ cp_msg_cc_handover_req_reason_t reason = 0;
+ cp_msg_cc_handover_cnf_result_t result = 0;
+ cp_sta_own_data_t *own = NULL;
+
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ if (cp_msg_cc_handover_req_receive (ctx, mme, &soft_hard, &reason))
+ {
+ if ((soft_hard == CP_MSG_CC_HANDOVER_REQ_HANDOVER_SOFT)
+ && (CP_CCO_LEVEL == 0))
+ {
+ result = CP_MSG_CC_HANDOVER_CNF_RESULT_REJECT_SOFT_HANDOVER;
+ }
+ else if (soft_hard == CP_MSG_CC_HANDOVER_REQ_HANDOVER_HARD)
+ {
+ /* Store in the context. */
+ switch (reason)
+ {
+ case CP_MSG_CC_HANDOVER_REQ_REASON_CCO_LEAVING:
+ ctx->handover.reason = CP_HANDOVER_REASON_CCO_LEAVING;
+ break;
+ case CP_MSG_CC_HANDOVER_REQ_REASON_USER_APPOINT:
+ ctx->handover.reason = CP_HANDOVER_REASON_USER_APPOINT;
+ break;
+ case CP_MSG_CC_HANDOVER_REQ_REASON_CCO_SELECTION:
+ ctx->handover.reason = CP_HANDOVER_REASON_CCO_SELECTION;
+ break;
+ default:
+ dbg_assert_default ();
+ }
+
+ /* Go to the handover hard branch. */
+ result = CP_MSG_CC_HANDOVER_CNF_RESULT_ACCEPT;
+
+ if (reason != CP_MSG_CC_HANDOVER_REQ_REASON_USER_APPOINT)
+ {
+ cp_fsm_event_t *event;
+ cp_fsm_branch (ctx, STA_HANDOVER_IDLE, STA_HANDOVER_START, hard);
+
+ /* Program the timer for the timeout. */
+ event = cp_fsm_event_bare_new (ctx,
+ CP_FSM_EVENT_TYPE_HANDOVER_TIMEOUT);
+ cp_sta_core_gen_timed_event (ctx,
+ &ctx->handover.handover_timeout,
+ event,
+ CP_TIMEOUT_MS);
+ }
+ else
+ {
+ own = cp_sta_mgr_get_sta_own_data (ctx);
+ own->cco_prefered = true;
+ }
+ }
+
+ cp_msg_cc_handover_cnf_send (ctx, &mme->peer, result);
+ }
+ else
+ {
+ cp_msg_cc_handover_cnf_send (ctx, &mme->peer,
+ CP_MSG_CC_HANDOVER_CNF_RESULT_REJECT_ANY_HANDOVER);
+ }
+}
+
+void
+cp_av_sta_action_handover__handover_info_ind_receive (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ cp_msg_cc_handover_info_ind_rsc_t rsc;
+ cp_tei_t bcco;
+ uint num_sta;
+ bool res;
+
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ cp_sta_core_stop_timed_or_cyclic_event (ctx,
+ &ctx->handover.handover_timeout);
+ res = cp_msg_cc_handover_info_ind_receive_begin (ctx, mme, &rsc, &bcco,
+ &num_sta);
+
+ if (res && (rsc == CP_MSG_CC_HANDOVER_INFO_IND_RSC_HOIP))
+ {
+ cp_tei_t tei;
+ mac_t mac_addr;
+ uint status;
+ cp_tei_t ptei;
+ cp_sta_t *sta;
+ cp_net_t *net;
+
+ net = cp_sta_mgr_get_our_avln (ctx);
+
+ /* TODO: Store the backup CCO. */
+ for (; num_sta; num_sta --)
+ {
+ res = cp_msg_cc_handover_info_ind_receive (ctx, mme, &tei,
+ &mac_addr, &status,
+ &ptei);
+ if (res)
+ {
+ sta = cp_sta_mgr_sta_add (ctx, net, tei, mac_addr);
+ cp_sta_set_authenticated (ctx, sta, status);
+ sta->pco = ptei;
+ sta->tei_lease_date_ms = cp_sta_core_get_date_ms (ctx) +
+ MAC_SEC_TO_MS (CP_LEASE_ASSOC_MIN * 60);
+ cp_av_cco_action_tei_in_use (ctx, tei);
+
+ slab_release (sta);
+ }
+ }
+
+ res = cp_msg_cc_handover_info_ind_receive_end (ctx, mme);
+
+ if (res)
+ {
+ cp_av_cco_action_tei_in_use (ctx, cp_sta_own_data_get_tei (ctx));
+ /* Send the confirmation. */
+ cp_msg_cc_handover_info_rsp_send (ctx, &mme->peer);
+ }
+ }
+}
+
+void
+cp_av_sta_action_handover__handover_ended (cp_t *ctx)
+{
+ cp_net_t *net;
+ cp_sta_t *old_cco;
+ dbg_assert (ctx);
+ net = cp_sta_mgr_get_our_avln (ctx);
+ old_cco = cp_net_get_cco (ctx, net);
+ cp_net_set_cco (ctx, net, MAC_TEI_UNASSOCIATED);
+ /* Reset the handover flag in the central beacon. */
+ cp_av_beacon_handover_hoipflag (ctx, CP_BEACON_HOIP_FALSE);
+ cp_av_cco_action_cco__assoc_start (ctx);
+ /* Stop the lease timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (ctx,
+ &ctx->sta_action.assoc.lease_timer);
+ if (ctx->handover.reason == CP_HANDOVER_REASON_CCO_LEAVING)
+ {
+ cp_av_cco_action_cco_sta_leave_send_tei_map (ctx, old_cco);
+ cp_sta_mgr_release_station (ctx, cp_sta_get_tei (old_cco));
+ }
+ cp_fsm_trigger_new_event (ctx, bare, HANDOVER_SUCCESS);
+ slab_release (old_cco);
+}
+
+void
+cp_av_sta_action_handover__sta_handover (cp_t *ctx, cp_net_t *net, cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (net);
+
+ if (sta)
+ {
+ cp_beacon_update_tracking (ctx, sta);
+ cp_av_sta_action_assoc__authenticated__renew (ctx);
+ }
+}
+
+void
+cp_av_sta_action_handover__failure (cp_t *ctx)
+{
+ dbg_assert (ctx);
+
+ /* cancel the timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (ctx, &ctx->handover.handover_timeout);
+
+ cp_fsm_trigger_new_event (ctx, bare, HANDOVER_FAILURE);
+}
+
diff --git a/cesar/cp/av/sta/action/src/info.c b/cesar/cp/av/sta/action/src/info.c
new file mode 100644
index 0000000000..d0b9c2d56b
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/info.c
@@ -0,0 +1,115 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/info.c
+ * \brief STA action, information gathering definitions.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+
+#include "action.h"
+#include "cp/sta/action/action.h"
+
+#include "cp/msg/msg.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/fsm/fsm.h"
+#include "lib/slab.h"
+
+void
+cp_av_sta_action_process_cc_set_tei_map_ind (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ enum cp_msg_cc_set_tei_map_ind_mode_t mode;
+ uint i, sta_nb;
+ cp_net_t *our_net;
+ if (cp_msg_cc_set_tei_map_ind_receive_begin (ctx, mme, &mode, &sta_nb))
+ {
+ bool ok = true;
+ our_net = cp_sta_mgr_get_our_avln (ctx);
+ cp_tei_t our_tei = cp_sta_own_data_get_tei (ctx);
+ /* Setup a bit array to remember added station. */
+ u32 added[256 / 32];
+ memset (added, 0, sizeof (added));
+ added[0] = 1; /* 0 is not a valid TEI. */
+ /* Loop for each received station. */
+ for (i = 0; i < sta_nb; i++)
+ {
+ /* Read the station. */
+ cp_tei_t tei;
+ mac_t mac;
+ enum cp_msg_cc_set_tei_map_ind_status_t status;
+ ok = cp_msg_cc_set_tei_map_ind_receive_sta (ctx, mme, &tei, &mac,
+ &status);
+ if (!ok)
+ break;
+ /* Ignore our station. */
+ if (tei != our_tei)
+ {
+ /* Add or remove. */
+ if (mode != CP_MSG_CC_SET_TEI_MAP_IND_MODE_DELETE)
+ {
+ cp_sta_t *sta;
+ sta = cp_sta_mgr_sta_add (ctx, our_net, tei, mac);
+ cp_sta_set_authenticated (
+ ctx, sta,
+ status == CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED);
+ if (mode == CP_MSG_CC_SET_TEI_MAP_IND_MODE_ADD)
+ {
+ /* A new STA has joined an AVLN for the first time, generate an
+ * event. */
+ cp_fsm_event_t *event = cp_fsm_event_sta_new
+ (ctx, CP_FSM_EVENT_TYPE_new_sta_associated, our_net,
+ (cp_sta_t *) sta);
+ cp_fsm_post (ctx, event);
+ }
+ slab_release (sta);
+ added[tei / 32] |= 1 << (tei % 32);
+ }
+ else
+ cp_sta_mgr_sta_remove_assoc (ctx, our_net, tei);
+ }
+ }
+ if (ok)
+ {
+ /* Remove unseen station if update. */
+ if (mode == CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE)
+ {
+ u32 w = 0;
+ for (i = 0; i < 255; i++)
+ {
+ if (i % 32 == 0)
+ w = added[i / 32];
+ if (!(w & 1))
+ cp_sta_mgr_sta_remove_assoc (ctx, our_net, i);
+ w >>= 1;
+ }
+ }
+ cp_msg_cc_set_tei_map_ind_receive_end (ctx, mme);
+ }
+ cp_sta_mgr_commit_to_dataplane (ctx);
+ }
+}
+
+void
+cp_av_sta_action_process_cm_unassociated_sta_ind (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ cp_nid_t nid;
+ u8 cco_cap;
+ if (cp_msg_cm_unassociated_sta_ind_receive (ctx, mme, &nid, &cco_cap))
+ {
+ cp_net_t *net = cp_sta_mgr_add_avln (ctx, 0, nid);
+ if (net)
+ {
+ cp_sta_t *sta = cp_sta_mgr_sta_add (ctx, net, 0, mme->peer.mac);
+ sta->cco_cap = cco_cap;
+ cp_fsm_event_t *event = cp_fsm_event_sta_new
+ (ctx, CP_FSM_EVENT_TYPE_usta_ind, net, sta);
+ cp_fsm_trigger (ctx, event);
+ slab_release (sta);
+ }
+ }
+}
diff --git a/cesar/cp/av/sta/action/src/key.c b/cesar/cp/av/sta/action/src/key.c
new file mode 100644
index 0000000000..716fc722b9
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/key.c
@@ -0,0 +1,122 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/key.c
+ * \brief STA action, key exchange messages.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+
+#include "action.h"
+#include "cp/sta/action/action.h"
+
+#include "cp/fsm/fsm.h"
+#include "cp/msg/inc/msg_cm.h"
+
+void
+cp_av_sta_action_process_cm_set_key_req (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ u8 pid;
+ if (mme->peks == CP_MME_PEKS_SPC_NOT_EMBEDDED)
+ {
+ if (!cp_msg_cm_set_key_get_pid (ctx, mme, &pid))
+ return;
+ }
+ else
+ pid = mme->prun.pid;
+ switch (pid)
+ {
+ case 1:
+ cp_fsm_trigger_new_event (ctx, mme, CM_SET_KEY_REQ_PID1, mme);
+ break;
+ case 3:
+ cp_fsm_trigger_new_event (ctx, mme, CM_SET_KEY_REQ_PID3, mme);
+ break;
+ }
+}
+
+void
+cp_av_sta_action_process_cm_set_key_cnf (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ u8 pid;
+ if (mme->peks == CP_MME_PEKS_SPC_NOT_EMBEDDED)
+ {
+ if (!cp_msg_cm_set_key_get_pid (ctx, mme, &pid))
+ return;
+ }
+ else
+ pid = mme->prun.pid;
+ switch (pid)
+ {
+ case 1:
+ cp_fsm_trigger_new_event (ctx, mme, CM_SET_KEY_CNF_PID1, mme);
+ break;
+ case 3:
+ cp_fsm_trigger_new_event (ctx, mme, CM_SET_KEY_CNF_PID3, mme);
+ break;
+ }
+}
+
+void
+cp_av_sta_action_process_cm_get_key_req (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ u8 pid;
+ if (mme->peks == CP_MME_PEKS_SPC_NOT_EMBEDDED)
+ {
+ if (!cp_msg_cm_get_key_req_get_pid (ctx, mme, &pid))
+ return;
+ }
+ else
+ pid = mme->prun.pid;
+ switch (pid)
+ {
+ case 0:
+ cp_fsm_trigger_new_event (ctx, mme, CM_GET_KEY_REQ_PID0, mme);
+ break;
+ case 1:
+ cp_fsm_trigger_new_event (ctx, mme, CM_GET_KEY_REQ_PID1, mme);
+ break;
+ case 3:
+ cp_fsm_trigger_new_event (ctx, mme, CM_GET_KEY_REQ_PID3, mme);
+ break;
+ }
+}
+
+void
+cp_av_sta_action_process_cm_get_key_cnf (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (mme);
+ u8 pid;
+ if (mme->peks == CP_MME_PEKS_SPC_NOT_EMBEDDED)
+ {
+ if (!cp_msg_cm_get_key_cnf_get_pid (ctx, mme, &pid))
+ return;
+ }
+ else
+ pid = mme->prun.pid;
+ switch (pid)
+ {
+ case 0:
+ cp_fsm_trigger_new_event (ctx, mme, CM_GET_KEY_CNF_PID0, mme);
+ break;
+ case 1:
+ cp_fsm_trigger_new_event (ctx, mme, CM_GET_KEY_CNF_PID1, mme);
+ break;
+ case 3:
+ cp_fsm_trigger_new_event (ctx, mme, CM_GET_KEY_CNF_PID3, mme);
+ break;
+ }
+}
+
diff --git a/cesar/cp/av/sta/action/src/misc.c b/cesar/cp/av/sta/action/src/misc.c
new file mode 100644
index 0000000000..be065dd428
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/misc.c
@@ -0,0 +1,172 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/misc.c
+ * \brief STA action, miscellaneous definitions.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+#include "mac/common/store.h"
+
+#include "cp/inc/context.h"
+#include "cp/inc/trace.h"
+#include "cp/msg/msg.h"
+
+#include "hal/arch/arch.h" // for dsr lock and unlock
+
+#include "common/defs/spidcom.h"
+#include "mac/common/timings.h"
+#include "cp/fsm/fsm.h"
+#include "cp/cco/action/cco_action.h"
+#include "cp/av/sta/action/misc.h"
+#include "cp/av/cco/action/cco_action.h"
+
+void
+cp_av_sta_action_process_cc_discover_list_req (cp_t *ctx, cp_mme_rx_t *rx_mme)
+{
+ dbg_assert (ctx);
+ dbg_assert (rx_mme);
+
+ if (cp_msg_cc_discover_list_req_receive (ctx, rx_mme))
+ {
+ cp_mme_tx_t *tx_mme;
+ cp_msg_cc_discover_list_ctx_t disc_ctx;
+ cp_net_t *our_net = NULL;
+
+ /* Check if our station is associated in a network. */
+ if (cp_sta_own_data_get_tei (ctx) != MAC_TEI_UNASSOCIATED)
+ {
+ our_net = cp_sta_mgr_get_our_avln(ctx);
+ }
+
+ /* Prepare CC_DISCOVER_LIST.CNF */
+ tx_mme = cp_msg_cc_discover_list_cnf_send_begin (ctx, &rx_mme->peer,
+ cp_sta_mgr_get_num_discovered_stas (ctx),
+ cp_sta_mgr_get_num_discovered_net (ctx),
+ &disc_ctx);
+
+ /* Send NumStation */
+ cp_msg_cc_discover_list_cnf_send_stations_begin (ctx, tx_mme,
+ &disc_ctx);
+
+ /* Get stations informations for each existing network. */
+ cp_net_t *net;
+ for (net = cp_sta_mgr_get_first_avln (ctx); net;
+ net = cp_sta_mgr_get_next_avln (ctx, net))
+ {
+ /* Collect info valid for all stations of this net. */
+ cp_msg_cc_discover_list_sta_t list;
+
+ list.snid = cp_net_get_snid (ctx, net);
+ list.access = cp_net_get_access (ctx, net);
+
+ /* For all kind of association states we seek stations. */
+ cp_net_sta_status_t assoc;
+
+ for (assoc = 0; assoc < CP_NET_STA_NB; assoc++)
+ {
+ /* Check association. */
+ if ((assoc == CP_NET_STA_ASSOC) && (net == our_net))
+ list.same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK;
+ else
+ list.same_network = CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK;
+
+ cp_sta_t *cp_sta;
+
+ for (cp_sta = cp_net_sta_get_first (ctx, net, assoc);
+ cp_sta;
+ cp_sta = cp_net_sta_get_next (ctx, net, cp_sta))
+ {
+ list.mac_addr = cp_sta_get_mac_address (cp_sta);
+ list.tei = cp_sta_get_tei (cp_sta);
+ list.cco_cap = cp_sta->cco_cap;
+ list.proxy_cap = cp_sta->pco_cap;
+ list.backup_cco_cap = cp_sta->backup_cco_cap;
+ list.cco_status = cp_sta_get_cco_status (cp_sta);
+ list.pco_status = cp_sta_get_pco_status (cp_sta);
+ list.backup_cco_status = cp_sta->is_backup_cco;
+ list.signal_level = 0x00;
+
+ /** Compute average ble of the sta. */
+ if (list.same_network == CC_DISCOVER_LIST_NET_SAME_NETWORK)
+ list.average_ble =
+ cp_sta_action_get_average_ble (ctx, list.tei, true,
+ true);
+ else
+ list.average_ble = 0;
+
+ cp_msg_cc_discover_list_cnf_send_station (ctx, tx_mme,
+ &list);
+ }
+ }
+ }
+
+ /* Send NumNetwork */
+ cp_msg_cc_discover_list_cnf_send_net_begin (ctx, tx_mme, &disc_ctx);
+
+ /* For each present network but our network if we have one. */
+ for (net = cp_sta_mgr_get_first_avln (ctx); net;
+ net = cp_sta_mgr_get_next_avln (ctx, net))
+ {
+ if (our_net != net)
+ {
+ /* Collect info for all valid net */
+ cp_msg_cc_discover_list_net_t data;
+
+ data.nid = cp_net_get_nid (ctx, net);
+ data.snid = cp_net_get_snid (ctx, net);
+ data.access = cp_net_get_access (ctx, net);
+ data.hm = net->hm;
+ data.numslots = net->avln_num_slots;
+
+ if (net->network_mode == MAC_NM_COORDINATED)
+ /* Unsupported. */
+ data.coordinated_status =
+ CC_DISCOVER_LIST_COORD_COORDINATED_GROUP_UNKNOWN;
+ else
+ data.coordinated_status =
+ CC_DISCOVER_LIST_COORD_NON_COORDINATED;
+ data.offset = 0;
+
+ cp_msg_cc_discover_list_cnf_send_net (ctx, tx_mme, &data);
+ }
+ }
+
+ cp_msg_cc_discover_list_cnf_send_end (ctx, tx_mme);
+ }
+}
+
+void
+cp_av_sta_action_poweron__cco__join_timeout_sc_failed (
+ cp_t *ctx,
+ cp_fsm_branch_t branch_no_sta_no_avln,
+ cp_fsm_branch_t branch_no_sta_avln,
+ cp_fsm_branch_t branch_sta)
+{
+ dbg_assert (ctx);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ if (cp_net_is_empty (ctx, our_net))
+ {
+ if (cp_sta_mgr_net_list_is_empty (ctx))
+ {
+ cp_av_cco_action_cco__to_ucco (ctx);
+ cp_fsm_branch_ (ctx, branch_no_sta_no_avln);
+ }
+ else
+ {
+ /* Leave CCo role. */
+ cp_av_cco_action_cco__unassoc_stop (ctx);
+ cp_fsm_branch_ (ctx, branch_no_sta_avln);
+ }
+ }
+ else
+ {
+ /* Ok, stay CCo. */
+ cp_fsm_branch_ (ctx, branch_sta);
+ }
+}
diff --git a/cesar/cp/av/sta/action/src/poweron.c b/cesar/cp/av/sta/action/src/poweron.c
new file mode 100644
index 0000000000..91a270cc6d
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/poweron.c
@@ -0,0 +1,390 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/poweron.c
+ * \brief STA action, power on procedure related definitions.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+
+#include "action.h"
+
+#include "cp/defs.h"
+#include "cp/msg/msg.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/fsm/fsm.h"
+#include "cp/beacon/beacon.h"
+#include "cp/cco/action/cco_action.h"
+#include "bsu/bsu.h"
+#include "lib/slab.h"
+#include "cp/inc/context.h"
+
+#include "cp/av/beacon/discover.h"
+#include "cp/av/sta/action/inc/action.h"
+#include "cp/av/cco/action/cco_action.h"
+
+#define ALL_STA_LEAVED_TIMEOUT_MS 1000
+
+void
+cp_av_sta_action_poweron_init (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ ctx->sta_action.poweron.enter.need_set = false;
+}
+
+void
+cp_av_sta_action_poweron__many__to_idle (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Cleanup. */
+ pbproc_activate (ctx->pbproc, false);
+ sar_activate (ctx->sar, false);
+ sar_cleanup (ctx->sar);
+ bsu_activate (ctx->bsu, false);
+ cp_beacon_deactivate (ctx);
+ /* Signal station is stopped. */
+ cp_fsm_trigger_new_event (ctx, bare, stopped);
+}
+
+void
+cp_av_sta_action_poweron__idle__to_poweron (cp_t *ctx)
+{
+ cp_beacon_poweron_init (ctx);
+ bsu_power_on (ctx->bsu, cp_sta_own_data_get_snid (ctx));
+ /* Update beacon data program a timer is a wrong values beacon ACLF is
+ * still not initialised.*/
+ bsu_activate (ctx->bsu, true);
+ cp_beacon_reconfigure_timer (ctx, false);
+ sar_activate (ctx->sar, true);
+ pbproc_activate (ctx->pbproc, true);
+}
+
+void
+cp_av_sta_action_poweron__idle__enter (cp_t *ctx)
+{
+ if (ctx->sta_action.poweron.enter.need_set)
+ {
+ /* TODO: Changing the KEY should be handled by a new State in the
+ * Started FSM see #2800 */
+ cp_fsm_post_new_event (ctx, bare, to_poweron);
+ }
+}
+
+/**
+ * Start USTT timer.
+ * \param ctx control plane context
+ * \param ustt_ms USTT timer approximated value
+ */
+static void
+cp_av_sta_action_poweron_ustt_start (cp_t *ctx, uint ustt_ms)
+{
+ cp_fsm_event_t *event;
+ uint ustt_timeout_ms = ustt_ms / 2
+ + lib_rnd_uniform (&ctx->rnd, ustt_ms);
+ event = cp_fsm_event_bare_new (ctx, CP_FSM_EVENT_TYPE_ustt_timeout);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.poweron.ustt_timer,
+ event, ustt_timeout_ms);
+}
+
+/**
+ * Common handling of POWERON and USTA => USTT TIMEOUT.
+ * \param ctx control plane context
+ * \param ustt_ms USTT timer approximated value
+ */
+static void
+cp_av_sta_action_poweron_ustt_timeout (cp_t *ctx, uint ustt_ms)
+{
+ /* Send an CM_UNASSOCIATED_STA.IND. */
+ cp_msg_cm_unassociated_sta_ind_send (
+ ctx, &CP_MME_PEER (MAC_BROADCAST, MAC_TEI_UNASSOCIATED),
+ cp_sta_own_data_get_nid (ctx), CP_CCO_LEVEL);
+ cp_av_sta_action_poweron_ustt_start (ctx, ustt_ms);
+}
+
+void
+cp_av_sta_action_poweron__poweron__enter (cp_t *ctx)
+{
+ cp_fsm_event_t *event;
+ /* BTT timer. */
+ uint btt_timeout_min_ms, btt_timeout_max_ms, btt_timeout_ms;
+ if (cp_sta_own_data_get_was_cco (ctx))
+ {
+ btt_timeout_min_ms = CP_CCO_BEACON_SCAN_MIN_MS;
+ btt_timeout_max_ms = CP_CCO_BEACON_SCAN_MAX_MS;
+ }
+ else
+ {
+ btt_timeout_min_ms = CP_BEACON_SCAN_MIN_MS;
+ btt_timeout_max_ms = CP_BEACON_SCAN_MAX_MS;
+ }
+ btt_timeout_ms = lib_rnd_uniform (
+ &ctx->rnd, btt_timeout_max_ms - btt_timeout_min_ms + 1)
+ + btt_timeout_min_ms;
+ event = cp_fsm_event_bare_new (ctx, CP_FSM_EVENT_TYPE_btt_timeout);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.poweron.btt_timer,
+ event, btt_timeout_ms);
+ /* USTT timer. */
+ cp_av_sta_action_poweron_ustt_start (ctx, CP_USTA_IND_INTERVAL_MS);
+
+ if (ctx->sta_action.poweron.enter.need_set)
+ {
+ cp_sta_own_data_set_nid (ctx, ctx->sta_action.poweron.enter.nid);
+ cp_sta_own_data_set_nmk (ctx, ctx->sta_action.poweron.enter.nmk,
+ ctx->sta_action.poweron.enter.type);
+
+ ctx->sta_action.poweron.enter.need_set = false;
+ }
+
+ bsu_beacon_t beacon;
+ cp_beacon_fill (ctx, &beacon);
+ /* Act as STA, for BSU corresponds to only hear the central beacon from
+ * the CCo. */
+ bsu_update (ctx->bsu, &beacon, BSU_UPDATE_STA_TYPE_STA);
+}
+
+void
+cp_av_sta_action_poweron__poweron__leave (cp_t *ctx)
+{
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.poweron.btt_timer);
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.poweron.ustt_timer);
+}
+
+void
+cp_av_sta_action_poweron__poweron__ustt_timeout (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_av_sta_action_poweron_ustt_timeout (ctx, CP_USTA_IND_INTERVAL_MS);
+}
+
+/**
+ * Search for the first USTA with the mac address lesser than our own mac
+ * address.
+ * \param ctx the module context.
+ * \param net the AVLN to search in.
+ * \return true if a station with a bigger mac address than our own mac
+ * address.
+ */
+static bool
+cp_sta_action_btt_timeout_usta_with_mac_bigger (cp_t *ctx, cp_net_t *net)
+{
+ cp_sta_t *sta;
+ bool sta_found = false;
+ mac_t rmac = MAC_REVERSE (cp_sta_own_data_get_mac_address (ctx));
+ for (sta = cp_net_sta_get_first (ctx, net, CP_NET_STA_UNASSOC);
+ sta && !sta_found;
+ sta = cp_net_sta_get_next (ctx, net, sta))
+ {
+ if (sta->cco_cap > CP_CCO_LEVEL
+ || (sta->cco_cap == CP_CCO_LEVEL
+ && MAC_REVERSE (cp_sta_get_mac_address (sta)) > rmac))
+ sta_found = true;
+ }
+ return sta_found;
+}
+
+void
+cp_av_sta_action_poweron__poweron__btt_timeout (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ bool iam_cco_on_my_nid = false, iam_cco_on_other_nid = true;
+ cp_nid_t nid = cp_sta_own_data_get_nid (ctx);
+ cp_net_t *net;
+ for (net = cp_sta_mgr_get_first_avln (ctx);
+ net;
+ net = cp_sta_mgr_get_next_avln (ctx, net))
+ {
+ /* Search for AVLN with our NID. */
+ if (cp_net_get_nid (ctx, net) == nid)
+ {
+ iam_cco_on_my_nid = iam_cco_on_other_nid =
+ !cp_sta_action_btt_timeout_usta_with_mac_bigger (
+ ctx, net)
+ && !net->num_associated_stas;
+ }
+ /* Search for AVLN with another NID. */
+ else if (iam_cco_on_other_nid)
+ {
+ iam_cco_on_other_nid = !net->num_associated_stas;
+ }
+ }
+ if (iam_cco_on_my_nid)
+ {
+ cp_av_cco_action_cco__unassoc_start (ctx);
+ cp_fsm_branch (ctx, POWERON, btt_timeout, nid_match_cco);
+ }
+ else if (iam_cco_on_other_nid)
+ {
+ cp_av_cco_action_ucco_start (ctx);
+ cp_fsm_branch (ctx, POWERON, btt_timeout, no_avln);
+ }
+ else
+ cp_fsm_branch (ctx, POWERON, btt_timeout, avln);
+}
+
+void
+cp_av_sta_action_poweron__poweron__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ cp_av_sta_action_beacon_match_and_join (
+ ctx, beacon, net, sta, false /* not in SC */,
+ CP_FSM_BRANCH (POWERON, BEACON, nid_match),
+ CP_FSM_BRANCH (POWERON, BEACON, no_nid_match));
+}
+
+void
+cp_av_sta_action_poweron__poweron_joining__left (cp_t *ctx)
+{
+}
+
+void
+cp_av_sta_action_poweron__joining__to_stop (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_av_sta_action_assoc_leave (ctx);
+}
+
+static inline void
+cp_av_sta_action_poweron__usta_usta_joining__enter (cp_t *ctx)
+{
+ bsu_beacon_t beacon;
+ if (MAC_TEI_IS_STA (cp_sta_own_data_get_tei (ctx)))
+ cp_av_cco_action_cco__unassoc_stop (ctx);
+ cp_beacon_fill (ctx, &beacon);
+ bsu_update (ctx->bsu, &beacon, BSU_UPDATE_STA_TYPE_STA);
+}
+
+void
+cp_av_sta_action_poweron__usta__enter (cp_t *ctx)
+{
+ cp_av_sta_action_poweron__usta_usta_joining__enter (ctx);
+ cp_av_sta_action_poweron_ustt_start (ctx, CP_DISCOVER_PERIOD_MAX_MS);
+}
+
+void
+cp_av_sta_action_poweron__usta_joining__enter (cp_t *ctx)
+{
+ cp_av_sta_action_poweron__usta_usta_joining__enter (ctx);
+}
+
+void
+cp_av_sta_action_poweron__usta__leave (cp_t *ctx)
+{
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.poweron.ustt_timer);
+}
+
+void
+cp_av_sta_action_poweron__usta__ustt_timeout (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_av_sta_action_poweron_ustt_timeout (ctx, CP_DISCOVER_PERIOD_MAX_MS);
+}
+
+void
+cp_av_sta_action_poweron__usta__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ cp_av_sta_action_beacon_match_and_join (
+ ctx, beacon, net, sta, false /* not in SC */,
+ CP_FSM_BRANCH (USTA, BEACON, nid_match),
+ CP_FSM_BRANCH (USTA, BEACON, no_nid_match));
+}
+
+void
+cp_av_sta_action_poweron__usta__usta_ind (cp_t *ctx, cp_net_t *net,
+ cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (net);
+ dbg_assert (sta);
+ if (cp_net_get_nid (ctx, net) != cp_sta_own_data_get_nid (ctx))
+ {
+ cp_fsm_branch (ctx, USTA, usta_ind, else);
+ }
+ else
+ {
+ if (sta->cco_cap > CP_CCO_LEVEL
+ || (sta->cco_cap == CP_CCO_LEVEL
+ && (MAC_REVERSE (cp_sta_get_mac_address (sta))
+ > MAC_REVERSE (cp_sta_own_data_get_mac_address (ctx)))))
+ cp_fsm_branch (ctx, USTA, usta_ind, else);
+ else
+ {
+ cp_av_cco_action_cco__unassoc_start (ctx);
+ cp_fsm_branch (ctx, USTA, usta_ind, nid_match_cco);
+ }
+ }
+}
+
+void
+cp_av_sta_action_poweron__usta_joining__left (cp_t *ctx)
+{
+}
+
+void
+cp_av_sta_action_poweron__ucco__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ /* Stop UCCo behavior. */
+ cp_av_cco_action_ucco_stop (ctx);
+ /* Handle incoming beacon. */
+ cp_av_sta_action_beacon_match_and_join (
+ ctx, beacon, net, sta, false /* not in SC */,
+ CP_FSM_BRANCH (UCCO, BEACON, nid_match),
+ CP_FSM_BRANCH (UCCO, BEACON, no_nid_match));
+}
+
+void
+cp_av_sta_action_poweron__sta__to_stop (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_av_sta_action_assoc_leave (ctx);
+}
+
+void
+cp_av_sta_action_poweron_cco__enter (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_fsm_event_t *event;
+ event = cp_fsm_event_bare_new (ctx, CP_FSM_EVENT_TYPE_join_timeout);
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.poweron.join_timer,
+ event, CP_DISCOVER_PERIOD_MAX_MS);
+}
+
+void
+cp_av_sta_action_poweron_cco__leave (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ cp_sta_core_stop_timed_or_cyclic_event (
+ ctx, &ctx->sta_action.poweron.join_timer);
+}
+
+void
+cp_av_sta_action_poweron__cco__join_timeout (cp_t *ctx)
+{
+ cp_av_sta_action_poweron__cco__join_timeout_sc_failed (
+ ctx,
+ CP_FSM_BRANCH (CCO, join_timeout, no_sta_no_avln),
+ CP_FSM_BRANCH (CCO, join_timeout, no_sta_avln),
+ CP_FSM_BRANCH (CCO, join_timeout, sta)
+ );
+}
diff --git a/cesar/cp/av/sta/action/src/sc.c b/cesar/cp/av/sta/action/src/sc.c
new file mode 100644
index 0000000000..9439f6224f
--- /dev/null
+++ b/cesar/cp/av/sta/action/src/sc.c
@@ -0,0 +1,580 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/action/src/sc.c
+ * \brief STA action, Simple Connect procedure functions definitions.
+ * \ingroup cp_av_sta_action
+ */
+#include "common/std.h"
+#include "cp/inc/context.h"
+#include "cp/sta/action/inc/context.h"
+
+#include "action.h"
+#include "cp/sta/action/action.h"
+
+#include "cp/sta/core/core.h"
+#include "cp/av/sta/mgr/sta_mgr.h"
+#include "cp/msg/inc/msg_cm.h"
+#include "cp/msg/inc/msg_drv.h"
+#include "cp/fsm/inc/events.h"
+#include "cp/fsm/fsm.h"
+#include "cp/cco/action/cco_action.h"
+#include "cp/secu/defs.h"
+
+#include "cp/av/sta/action/inc/action.h"
+#include "cp/av/beacon/beacon.h"
+
+/**
+ * SC timeout.
+ */
+#define SC_TIMEOUT_MS 30000
+
+/**
+ * Minimum value of the timer for periodic broadcast of SC_JOIN.REQ MME.
+ */
+#define SC_PERIODIC_SC_JOIN_REQ_BCAST_MS_MIN 750
+
+/**
+ * Maximum value of the timer for periodic broadcast of SC_JOIN.REQ MME.
+ */
+#define SC_PERIODIC_SC_JOIN_REQ_BCAST_MS_MAX 1250
+
+/**
+ * Start SC timer.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__start_timer (cp_t *ctx);
+
+/**
+ * Stop SC timer.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__stop_timer (cp_t *ctx);
+
+/**
+ * Start the SC procedure as the "add" STA.
+ * \param ctx control plane context.
+ * \param peer peer with which we are doing the SC procedure.
+ *
+ * This function send the SC_JOIN.CNF and make the top FSM move to CCo if
+ * needed.
+ */
+void
+cp_av_sta_action_sc__start_sc_in_add (cp_t *ctx, cp_mme_peer_t *peer);
+
+/**
+ * Send a CM_SC_JOIN.REQ to all STA in broadcast.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__send_cm_sc_join_req (cp_t *ctx);
+
+/**
+ * Start the SC JOIN.REQ timer.
+ * \param ctx control plane context.
+ */
+void
+cp_av_sta_action_sc__start_sc_join_req_timer (cp_t *ctx);
+
+void
+cp_av_sta_action_sc__start_timer (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+ /* Event to generate when SC timeout. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_timeout);
+ /* Enable SC timeout timer. */
+ cp_sta_core_gen_timed_event (ctx, &ctx->sta_action.sc.timeout_timer, event,
+ SC_TIMEOUT_MS);
+}
+
+void
+cp_av_sta_action_sc__stop_timer (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+ /* Disable SC timeout timer. */
+ cp_sta_core_stop_timed_or_cyclic_event (ctx,
+ &ctx->sta_action.sc.timeout_timer);
+}
+
+void
+cp_av_sta_action_sc__start_sc_in_add (cp_t *ctx, cp_mme_peer_t *peer)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (peer);
+ /* Keep track of peer with witch we are doing SC procedure. */
+ ctx->sta_action.sc.peer = *peer;
+ /* Create reply (CM_SC_JOIN.CNF). */
+ cp_msg_cm_sc_join_cnf_t cnf;
+ cnf.nid = cp_sta_own_data_get_nid (ctx);
+ cnf.avln_status = MAC_TEI_IS_STA (cp_sta_own_data_get_tei (ctx));
+ cnf.cco_cap = CP_CCO_LEVEL;
+ cnf.pco_cap = CP_PCO_CAP;
+ cnf.backup_cco_cap = CP_BACKUP_CCO_CAP;
+ cnf.pco_status = cp_sta_own_data_get_pco_status (ctx);
+ cnf.backup_cco_status = cp_sta_own_data_get_backup_cco_status (ctx);
+ if (cnf.avln_status)
+ {
+ /* We are on AVLN, give our CCo status. */
+ cnf.cco_status = cp_sta_own_data_get_cco_status (ctx);
+ }
+ else
+ {
+ /* We are not on an AVLN, we must create one and become CCo. */
+ cnf.cco_status = true;
+ /* Make the main CP FSM move to CCo. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ ctx, CP_FSM_EVENT_TYPE_sc_get_cco_functionality);
+ cp_fsm_trigger (ctx, event);
+ }
+ /* Send the reply. */
+ cp_msg_cm_sc_join_cnf_send (ctx, peer, &cnf);
+}
+
+void
+cp_av_sta_action_sc__send_cm_sc_join_req (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+
+ /* Send the SC_JOIN MME. */
+ cp_mme_peer_t peer = CP_MME_PEER (MAC_BROADCAST, MAC_TEI_UNASSOCIATED);
+ cp_msg_cm_sc_join_req_send (ctx, &peer);
+}
+
+void
+cp_av_sta_action_sc__start_sc_join_req_timer (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+
+ /* Event to generate when SC_JOIN.REQ timer times-out. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_join_req_timeout);
+ /* Generate a random value to wait for the broadcast of SC_JOIN.REQ. */
+ uint rnd_wait = lib_rnd_uniform (&ctx->rnd,
+ SC_PERIODIC_SC_JOIN_REQ_BCAST_MS_MAX
+ - SC_PERIODIC_SC_JOIN_REQ_BCAST_MS_MIN);
+ rnd_wait += SC_PERIODIC_SC_JOIN_REQ_BCAST_MS_MIN;
+ /* Start the SC JOIN REQ timer. */
+ cp_sta_core_gen_timed_event
+ (ctx, &ctx->sta_action.sc.timer_sc_join_req_broadcast,
+ event, rnd_wait);
+}
+
+void
+cp_av_sta_action_sc__start_sc_join (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+
+ /* Generate the event to make the SC FSM start. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_start_join);
+ cp_fsm_post (ctx, event);
+}
+
+void
+cp_av_sta_action_sc__start_sc_add (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+
+ /* Generate the event to make the SC FSM start. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_start_add);
+ cp_fsm_post (ctx, event);
+}
+
+void
+cp_av_sta_action_sc__sc_idle__enter (cp_t *ctx)
+{
+ /* Stop SC timer. */
+ cp_av_sta_action_sc__stop_timer (ctx);
+ cp_sta_own_data_set_sc (ctx, false);
+}
+
+void
+cp_av_sta_action_sc__sc_idle__leave (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+ /* Start SC timer. */
+ cp_av_sta_action_sc__start_timer (ctx);
+ cp_sta_own_data_set_sc (ctx, true);
+}
+
+void
+cp_av_sta_action_sc__sc_join__enter (cp_t *ctx)
+{
+ /* Send a SC_JOIN.REQ. */
+ cp_av_sta_action_sc__start_sc_join_req_timer (ctx);
+ /* Start the timer. */
+ cp_av_sta_action_sc__send_cm_sc_join_req (ctx);
+}
+
+void
+cp_av_sta_action_sc__sc_join__leave (cp_t *ctx)
+{
+ /* Check parameter. */
+ dbg_assert (ctx);
+ /* Disable SC timeout timer. */
+ cp_sta_core_stop_timed_or_cyclic_event
+ (ctx, &ctx->sta_action.sc.timer_sc_join_req_broadcast);
+}
+
+void
+cp_av_sta_action_sc__sc_timeout (cp_t *ctx)
+{
+ /* Generate the event for the CP FSM. */
+ cp_fsm_post_new_event (ctx, bare, sc_failed);
+}
+
+void
+cp_av_sta_action_sc_add__sc_timeout (cp_t *ctx)
+{
+ /* Generate the event for the CP FSM. */
+ cp_fsm_post_new_event (ctx, bare, sc_failed);
+}
+
+void
+cp_av_sta_action_sc__sc_add__cm_sc_join_req (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ uint cco_cap;
+
+ /* Check received MME. */
+ if ((mme->peer.tei != 0x0)
+ || (!cp_msg_cm_sc_join_req_receive (ctx, mme, &cco_cap))
+ )
+ {
+ /* Error in received MME. */
+ cp_fsm_branch (ctx, SC_ADD, CM_SC_JOIN_REQ, nok);
+ }
+ else
+ {
+ /* Let's try SC procedure with peer. */
+ cp_av_sta_action_sc__start_sc_in_add (ctx, &mme->peer);
+ /* Move FSM. */
+ cp_fsm_branch (ctx, SC_ADD, CM_SC_JOIN_REQ, ok);
+ }
+}
+
+void
+cp_av_sta_action_sc__to_stop (cp_t *ctx)
+{
+ /* Generate the event for the CP FSM. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_failed);
+ cp_fsm_post (ctx, event);
+}
+
+void
+cp_av_sta_action_sc__sc_wait_peer_associated__new_sta_associated (cp_t *ctx,
+ cp_net_t *net,
+ cp_sta_t *sta)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (net);
+ dbg_assert (sta);
+
+ /* If it is our net and the STA we are doing the SC procedure. */
+ if (ctx->sta_action.sc.peer.mac == cp_sta_get_mac_address (sta))
+ {
+ /* Store its TEI. */
+ ctx->sta_action.sc.peer.tei = cp_sta_get_tei (sta);
+ /* Start the exchange of hash key to build the TEK. */
+ cp_msg_cm_get_key_req_t req;
+ req.relayed = false;
+ req.key_type = CP_MSG_KEY_HASH_KEY;
+ req.nid = cp_sta_own_data_get_nid (ctx);
+ /* Generate hash key. */
+ cp_secu_generate_hash (ctx, lib_rnd32 (&ctx->rnd), (u8 *) req.hash_key,
+ CP_SECU_HASH_KEY_FOR_TEK_SIZE);
+ /* Keep a copy of the hash key. */
+ memcpy (ctx->sta_action.sc.hash_key, req.hash_key, CP_HASH_KEY_SIZE);
+ cp_secu_protocol_run_new (&ctx->sta_action.sc.prun, 3,
+ &ctx->rnd);
+ /* Send GET_KEY_REQ_PID3. */
+ cp_msg_cm_get_key_req_send (ctx, &ctx->sta_action.sc.peer,
+ CP_MME_PEKS_SPC_NOT_EMBEDDED, /* Not encrypted! */
+ &ctx->sta_action.sc.prun, &req);
+ /* Update FSM. */
+ cp_fsm_branch (ctx, SC_WAIT_PEER_ASSOCIATED, new_sta_associated,
+ sta_is_sc_peer);
+ }
+ else
+ {
+ /* Nothing to do. */
+ /* Update FSM. */
+ cp_fsm_branch (ctx, SC_WAIT_PEER_ASSOCIATED, new_sta_associated,
+ sta_not_sc_peer);
+ }
+}
+
+void
+cp_av_sta_action_sc__sc_join__cm_sc_join_req (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ uint cco_cap;
+ /* Check SC_JOIN.REQ */
+ if (!cp_msg_cm_sc_join_req_receive (ctx, mme, &cco_cap))
+ {
+ /* Incorrect MME. */
+ cp_fsm_branch (ctx, SC_JOIN, CM_SC_JOIN_REQ, nok);
+ }
+ else
+ {
+ /* SC_JOIN.REQ is correct, let's compare CCo capabilities to know
+ * which one is going to SC_ADD. */
+ /* To prevent a warning. */
+ const uint my_cco_cap = CP_CCO_LEVEL;
+ if (((int) my_cco_cap > (int) cco_cap)
+ || ((my_cco_cap == cco_cap)
+ && (MAC_REVERSE (cp_sta_own_data_get_mac_address (ctx))
+ > MAC_REVERSE (mme->peer.mac))))
+ {
+ /* My CCo capabilities are greater than the peer. */
+ /* Act if we were in SC_ADD procedure. */
+ cp_av_sta_action_sc__start_sc_in_add (ctx, &mme->peer);
+ /* Update FSM. */
+ cp_fsm_branch (ctx, SC_JOIN, CM_SC_JOIN_REQ,
+ ok_my_cco_cap_greater);
+ }
+ else
+ {
+ /* Peer CCo capabilities are greater than mine. */
+ /* Nothing to do, update FSM. */
+ cp_fsm_branch (ctx, SC_JOIN, CM_SC_JOIN_REQ, ok_my_cco_cap_lower);
+ }
+ }
+}
+
+void
+cp_av_sta_action_sc__sc_join__cm_sc_join_cnf (cp_t *ctx, cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ /* Check MME. */
+ cp_msg_cm_sc_join_cnf_t cnf;
+ if (!cp_msg_cm_sc_join_cnf_receive (ctx, mme, &cnf))
+ {
+ /* Error in MME. */
+ cp_fsm_branch (ctx, SC_JOIN, CM_SC_JOIN_CNF, nok);
+ }
+ else
+ {
+ /* Set NID from MME. */
+ cp_sta_own_data_set_nid (ctx, cnf.nid);
+ /* Copy SC peer information. */
+ ctx->sta_action.sc.peer = mme->peer;
+ /* We need to wait for beacon. */
+ cp_fsm_branch (ctx, SC_JOIN, CM_SC_JOIN_CNF, ok);
+ }
+}
+
+void
+cp_av_sta_action_sc__sc_join__sc_join_req_timeout (cp_t *ctx)
+{
+ /* Send the SC_JOIN.REQ MME. */
+ cp_av_sta_action_sc__start_sc_join_req_timer (ctx);
+ /* Restart timer. */
+ cp_av_sta_action_sc__send_cm_sc_join_req (ctx);
+}
+
+void
+cp_av_sta_action_sc__sc_wait_beacon__beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ cp_av_sta_action_beacon_match_and_join (
+ ctx, beacon, net, sta, true /* Simple Connect */,
+ CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON, nid_match),
+ CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON, nid_differs));
+}
+
+void
+cp_av_sta_action_sc__sc_building_tek__cm_get_key_cnf_pid3 (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ cp_msg_cm_get_key_cnf_t cnf;
+ /* Check received MME. */
+ if (!cp_mme_peer_cmp (&mme->peer, &ctx->sta_action.sc.peer)
+ || !cp_msg_cm_get_key_cnf_receive (ctx, mme, &cnf)
+ || (!cp_secu_protocol_check
+ (&ctx->sta_action.sc.prun, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEXT))
+ || (cnf.eks < CP_MME_PEKS_TEK_MIN)
+ || (cnf.eks > CP_MME_PEKS_TEK_MAX))
+
+ {
+ /* Error in MME. */
+ cp_fsm_branch (ctx, SC_BUILDING_TEK, CM_GET_KEY_CNF_PID3, unrelated);
+ }
+ else
+ {
+ if (cnf.result != CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED)
+ {
+ /* Hash key exchange fails. */
+ cp_fsm_branch (ctx, SC_BUILDING_TEK, CM_GET_KEY_CNF_PID3, nok);
+ }
+ else
+ {
+ /* Hash key exchange for TEK succeed. */
+ /* Compute TEK. */
+ cp_secu_tek_gen (ctx->sta_action.sc.hash_key,
+ cnf.hash_key,
+ &ctx->sta_action.sc.tek);
+ /* Set the TEK for encryption. */
+ cp_sta_own_data_set_tek (ctx, ctx->sta_action.sc.tek);
+ /* Next protocol run. */
+ ctx->sta_action.sc.prun = mme->prun;
+ cp_secu_protocol_next (&ctx->sta_action.sc.prun, &ctx->rnd,
+ false);
+ /* Create reply. */
+ cp_msg_cm_set_key_req_t req;
+ req.key_type = CP_MSG_KEY_NMK;
+ req.cco_cap = CP_CCO_LEVEL;
+ req.nid = cp_sta_own_data_get_nid (ctx);
+ /* Check this. */
+ req.new_eks = CP_MME_PEKS_NMK;
+ req.new_key = cp_sta_own_data_get_nmk (ctx);
+ /* Send the NMK encrypted with TEK. */
+ cp_msg_cm_set_key_req_send (ctx, &mme->peer, cnf.eks,
+ &ctx->sta_action.sc.prun,
+ &req);
+ cp_fsm_branch (ctx, SC_BUILDING_TEK, CM_GET_KEY_CNF_PID3, ok);
+ }
+ }
+}
+
+void
+cp_av_sta_action_sc__sc_nmk_exchange__cm_set_key_cnf_pid3 (cp_t *ctx,
+ cp_mme_rx_t *mme)
+{
+ /* Check parameters. */
+ dbg_assert (ctx);
+ dbg_assert (mme);
+
+ cp_msg_cm_set_key_cnf_t cnf;
+ /* Check received MME. */
+ if (!cp_mme_peer_cmp (&mme->peer, &ctx->sta_action.sc.peer)
+ || !cp_msg_cm_set_key_cnf_receive (ctx, mme, &cnf)
+ || (!cp_secu_protocol_check
+ (&ctx->sta_action.sc.prun, &mme->prun,
+ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_LAST)))
+ {
+ /* Error in MME. */
+ cp_fsm_branch (ctx, SC_NMK_EXCHANGE, CM_SET_KEY_CNF_PID3, unrelated);
+ }
+ else
+ {
+ if (cnf.result != CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS)
+ {
+ /* NMK exchange failed, inform main FSM. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_failed);
+ cp_fsm_post (ctx, event);
+ /* Move the FSM. */
+ cp_fsm_branch (ctx, SC_NMK_EXCHANGE, CM_SET_KEY_CNF_PID3, nok);
+ }
+ else
+ {
+ /* NMK exchange succeed, inform main FSM. */
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_sc_succeed);
+ cp_fsm_post (ctx, event);
+ /* Move the FSM. */
+ cp_fsm_branch (ctx, SC_NMK_EXCHANGE, CM_SET_KEY_CNF_PID3, ok);
+ }
+ }
+}
+
+void
+cp_av_sta_action_sc__sc_usta_track_beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ /* Check parameters. */
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (ctx);
+ cp_nid_t our_nid = cp_sta_own_data_get_nid (ctx);
+ cp_nid_t its_nid = cp_net_get_nid (ctx, net);
+ u8 its_snid = cp_net_get_snid (ctx, net);
+ /* Does not support proxy networking for the moment, only handle CCo
+ * beacon. */
+ if (cp_sta_get_cco_status (sta))
+ {
+ /* Should we track this beacon? */
+ if (!own_data->nid_track /* No AVLN tracked. */
+ || (our_nid != own_data->nid_track
+ && our_nid == its_nid) /* Better NID match. */
+ )
+ {
+ own_data->nid_track = its_nid;
+ cp_av_sta_mgr_set_tracking (ctx, its_snid, its_nid);
+ cp_beacon_process_tracked_avln (ctx, beacon, net);
+ }
+ }
+}
+
+void
+cp_av_sta_action_sc__sc_ucco_track_beacon (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ dbg_assert (sta);
+ /* Change to STA behaviour. */
+ cp_beacon_reconfigure_timer (ctx, false);
+ /* Handle incoming beacon. */
+ cp_av_sta_action_sc__sc_usta_track_beacon (ctx, beacon, net, sta);
+}
+
+void
+cp_av_sta_action_sc__sc_sta__avln_failure (cp_t *ctx)
+{
+ cp_fsm_event_t *event = cp_fsm_event_bare_new
+ (ctx, CP_FSM_EVENT_TYPE_to_stop);
+ cp_fsm_post (ctx, event);
+}
+
+void
+cp_av_sta_action_sc__sc_cco__sc_failed (cp_t *ctx)
+{
+ cp_av_sta_action_poweron__cco__join_timeout_sc_failed (
+ ctx,
+ CP_FSM_BRANCH (SC_CCO, sc_failed, no_sta_no_avln),
+ CP_FSM_BRANCH (SC_CCO, sc_failed, no_sta_avln),
+ CP_FSM_BRANCH (SC_CCO, sc_failed, sta)
+ );
+}
diff --git a/cesar/cp/av/sta/action/test/utest/Config b/cesar/cp/av/sta/action/test/utest/Config
new file mode 100644
index 0000000000..3ebfb2f0b9
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/Config
@@ -0,0 +1 @@
+CONFIG_CP_AV = y
diff --git a/cesar/cp/av/sta/action/test/utest/Makefile b/cesar/cp/av/sta/action/test/utest/Makefile
new file mode 100644
index 0000000000..ca1d30eda7
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/Makefile
@@ -0,0 +1,26 @@
+BASE = ../../../../../..
+
+INCLUDES = cp/av/sta/action/test/utest cp/av/sta/action/test/utest/override
+
+HOST_PROGRAMS = test_sta_action
+test_sta_action_SOURCES = test_sta_action.c assoc.c drv.c info.c key.c \
+ bridge.c handover.c \
+ msg_stub.c dataplane_stub.c fsm_stub.c \
+ core_stub.c beacon_stub.c cp_stub.c \
+ cco_stub.c scenario_actions.c vs.c ce_stub.c \
+ mac_sar_interface_stub.c
+
+test_sta_action_MODULES = lib lib/scenario cp/av/sta/action cp/av/sta/mgr \
+ cp/av/fsm/stub cp/secu mac/common cl/stub cl \
+ cp/av/cco/action/stub cp/av/beacon/stub cp/msg/stub \
+ ce/stub mac/sar/stub cp/av/cco/bw/stub bsu/stub \
+ hal/ipmbox/stub
+
+test_sta_action_CONFIG_MODULES = cp
+cp_av_fsm_MODULE_SOURCES = tables.c
+
+# For bridging MME tests.
+cl_stub_MODULE_SOURCES = cl.c cl_mactotei.c brg_rx.c
+cl_MODULE_SOURCES = bridge_table.c data_rate.c
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/cp/av/sta/action/test/utest/inc/scenario_defs.h b/cesar/cp/av/sta/action/test/utest/inc/scenario_defs.h
new file mode 100644
index 0000000000..9e89572348
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/inc/scenario_defs.h
@@ -0,0 +1,890 @@
+#ifndef inc_scenario_defs_h
+#define inc_scenario_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/scenario_defs.h
+ * \brief Scenario definitions.
+ * \ingroup test
+ */
+
+#include "cp/msg/msg.h"
+#include "cp/sta/mgr/sta.h"
+#include "cp/sta/mgr/net.h"
+#include "cp/fsm/fsm.h"
+#include "cl/cl_mactotei.h"
+#include "mac/common/tonemap.h"
+
+/* Scenario globals. */
+#define SCENARIO_DEFS_GLOBALS \
+ cp_t *cp; \
+ u16 prn; \
+ u32 my_nonce; \
+ u32 your_nonce; \
+ cp_mme_tx_t *mme;
+
+/* Scenario actions. */
+#define SCENARIO_DEFS_ACTIONS \
+ garbage, \
+ \
+ assoc_start, \
+ assoc_leave, \
+ assoc__unassociated__enter, \
+ assoc__unassociated__to_assoc, \
+ assoc__start_retry_timer, \
+ assoc__stop_retry_timer, \
+ assoc__wait_assoc_cnf__cc_assoc_cnf, \
+ assoc__wait_assoc_cnf__timeout, \
+ assoc__associated__cm_get_key_cnf_pid_0, \
+ assoc__associated__timeout, \
+ assoc__associated__to_leave, \
+ assoc__authenticated__leave, \
+ assoc__authenticated__renew, \
+ assoc__authenticated__cc_assoc_cnf, \
+ assoc__authenticated__cm_set_key_req_pid_1, \
+ assoc__authenticated__to_leave, \
+ assoc__authenticated__cc_leave_ind, \
+ assoc__authenticated__beacon, \
+ assoc__authenticated__beacon_not_received, \
+ assoc__authenticated__nek_request, \
+ assoc__authenticated__cm_get_key_cnf_pid_1, \
+ assoc__leaving__cc_leave_cnf, \
+ assoc__leaving__timeout, \
+ assoc__leave_wait__enter, \
+ assoc__leave_wait__timeout, \
+ \
+ drv__stopped__drv_sta_set_mac_addr_req, \
+ drv__stopped__drv_sta_set_cco_pref_req, \
+ drv__stopped__drv_sta_set_was_cco_req, \
+ drv__stopped__drv_sta_set_npw_req, \
+ drv__stopped__drv_sta_set_dpw_req, \
+ drv__stopped__drv_sta_set_sl_req, \
+ drv__stopped__drv_sta_set_nid_req, \
+ drv__stopped__drv_sta_set_m_sta_hfid_req, \
+ drv__stopped__drv_sta_set_u_sta_hfid_req, \
+ drv__stopped__drv_sta_set_avln_hfid_req, \
+ drv__stopped__drv_sta_set_tonemask_req, \
+ drv__stopped__drv_sta_mac_start_req, \
+ drv__stopped__drv_sta_set_key_req, \
+ drv__stopped__drv_sta_set_dak_req, \
+ drv__started__drv_sta_mac_stop_req, \
+ drv__stopping__stopped, \
+ drv__drv_sta_get_key_req, \
+ drv__drv_sta_status_req, \
+ drv__drv_sta_set_config_req, \
+ drv__drv_mcast_set_list_req, \
+ \
+ process_cc_set_tei_map_ind, \
+ process_cm_unassociated_sta_ind, \
+ \
+ process_cm_set_key_req, \
+ process_cm_set_key_cnf, \
+ process_cm_get_key_req, \
+ process_cm_get_key_cnf, \
+ \
+ process_cc_who_ru_req, \
+ process_cc_who_ru_cnf, \
+ process_cc_discover_list_req, \
+ process_cc_relay_req, \
+ process_cm_hfid_req, \
+ process_cm_mme_error_ind, \
+ \
+ poweron_start, \
+ poweron_stop, \
+ poweron__many__to_idle, \
+ poweron__idle__to_poweron, \
+ poweron__poweron__enter, \
+ poweron__poweron__leave, \
+ poweron__poweron__ustt_timeout, \
+ poweron__poweron__btt_timeout, \
+ poweron__poweron__beacon, \
+ poweron__poweron_joining__left, \
+ poweron__joining__to_stop, \
+ poweron__usta__enter, \
+ poweron__usta__leave, \
+ poweron__usta__ustt_timeout, \
+ poweron__usta__beacon, \
+ poweron__usta__usta_ind, \
+ poweron__usta_joining__left, \
+ poweron__ucco__beacon, \
+ poweron__sta__to_stop, \
+ poweron__cco__join_timeout, \
+ poweron__cco__all_sta_leaved, \
+ poweron_cco__enter, \
+ poweron_cco__leave, \
+ \
+ process_cm_brg_info_cnf, \
+ process_cm_brg_info_req, \
+ update_bridge_table, \
+ \
+ drv__ucco__drv_sta_sc, \
+ drv__cco__drv_sta_sc, \
+ drv__usta__drv_sta_sc, \
+ drv__sta__drv_sta_sc, \
+ sc__start_sc_join, \
+ sc__start_sc_add, \
+ sc__sc_idle__enter, \
+ sc__sc_idle__leave, \
+ sc__sc_join__enter, \
+ sc__sc_join__leave, \
+ sc__sc_join__sc_join_req_timeout, \
+ sc__sc_cco__sc_failed, \
+ sc__sc_timeout, \
+ sc_add__sc_timeout, \
+ sc__sc_join__cm_sc_join_cnf, \
+ sc__sc_join__cm_sc_join_req, \
+ sc__sc_add__cm_sc_join_req, \
+ sc__check_nid_set, \
+ sc__sc_wait_beacon__beacon, \
+ sc__check_sc_assoc_start, \
+ sc__check_sc_status, \
+ sc__sc_wait_peer_associated__new_sta_associated, \
+ sc__sc_building_tek__cm_get_key_cnf_pid3, \
+ sc__sc_nmk_exchange__cm_set_key_cnf_pid3, \
+ sc__sc_usta_track_beacon, \
+ sc__sc_ucco_track_beacon, \
+ assoc__sc_wait_assoc_cnf__cc_assoc_cnf, \
+ assoc__sc_associated__cm_get_key_req_pid_3, \
+ assoc__sc_tek_exchanged__cm_set_key_req_pid_3, \
+ assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0, \
+ \
+ handover__start, \
+ handover__handover_info_ind_receive, \
+ handover__handover_ended, \
+ whoru_timeout_process, \
+ \
+ process_cm_nw_stats_req, \
+ process_cm_nw_info_req, \
+ vs__started__vs_get_tonemap_req, \
+ vs__started__vs_get_link_stats_req, \
+ process_cm_link_stats_req, \
+ vs__started__imac_get_discover_list_req, \
+ \
+ process_cm_sta_cap_req, \
+ vs__started__vs_get_snr_req, \
+ vs_get_snr_cnf_send, \
+ vs__started__vs_get_ce_stats_req, \
+ vs__started__vs_get_pb_stats_req
+
+/* Actions without parameter. */
+#define __0(action) \
+typedef scenario_empty_t scenario_action_ ## action ## _t; \
+void \
+scenario_action_ ## action ## _cb ( \
+ scenario_globals_t *globals, scenario_params_t *params);
+
+/* Actions with parameters. */
+#define __n(action, param...) \
+typedef struct \
+{ \
+ PREPROC_FOR_EACH (__n_, param) \
+} scenario_action_ ## action ## _t; \
+void \
+scenario_action_ ## action ## _cb ( \
+ scenario_globals_t *globals, scenario_params_t *params);
+#define __n_(param) param;
+
+/* Actions with MME and parameters. */
+#define __m(action, param...) \
+typedef struct \
+{ \
+ cp_mme_peer_t peer; \
+ PREPROC_FOR_EACH (__m_, param) \
+} scenario_action_ ## action ## _t; \
+void \
+scenario_action_ ## action ## _cb ( \
+ scenario_globals_t *globals, scenario_params_t *params);
+#define __m_(param) param;
+
+__0 (garbage)
+
+__n (assoc_start, cp_net_t *cco_net, cp_sta_t *cco)
+__0 (assoc_leave)
+__0 (assoc__unassociated__enter)
+__0 (assoc__unassociated__to_assoc)
+__0 (assoc__start_retry_timer)
+__0 (assoc__stop_retry_timer)
+__m (assoc__wait_assoc_cnf__cc_assoc_cnf)
+__0 (assoc__wait_assoc_cnf__timeout)
+__m (assoc__associated__cm_get_key_cnf_pid_0)
+__0 (assoc__associated__timeout)
+__0 (assoc__associated__to_leave)
+__0 (assoc__authenticated__leave)
+__0 (assoc__authenticated__renew)
+__m (assoc__authenticated__cc_assoc_cnf)
+__m (assoc__authenticated__cm_set_key_req_pid_1)
+__0 (assoc__authenticated__to_leave)
+__0 (assoc__authenticated__nek_request)
+__m (assoc__authenticated__cm_get_key_cnf_pid_1)
+
+__m (assoc__authenticated__cc_leave_ind)
+__n (assoc__authenticated__beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__0 (assoc__authenticated__beacon_not_received)
+__m (assoc__leaving__cc_leave_cnf)
+__0 (assoc__leaving__timeout)
+__0 (assoc__leave_wait__enter)
+__0 (assoc__leave_wait__timeout)
+
+__m (drv__stopped__drv_sta_set_mac_addr_req)
+__m (drv__stopped__drv_sta_set_cco_pref_req)
+__m (drv__stopped__drv_sta_set_was_cco_req)
+__m (drv__stopped__drv_sta_set_npw_req)
+__m (drv__stopped__drv_sta_set_dpw_req)
+__m (drv__stopped__drv_sta_set_sl_req)
+__m (drv__stopped__drv_sta_set_nid_req)
+__m (drv__stopped__drv_sta_set_m_sta_hfid_req)
+__m (drv__stopped__drv_sta_set_u_sta_hfid_req)
+__m (drv__stopped__drv_sta_set_avln_hfid_req)
+__m (drv__stopped__drv_sta_set_tonemask_req)
+__m (drv__stopped__drv_sta_mac_start_req)
+__m (drv__stopped__drv_sta_set_key_req)
+__m (drv__stopped__drv_sta_set_dak_req)
+__m (drv__started__drv_sta_mac_stop_req)
+__0 (drv__stopping__stopped)
+__m (drv__drv_sta_get_key_req)
+__m (drv__drv_sta_status_req)
+__m (drv__drv_sta_set_config_req)
+
+__m (drv__drv_mcast_set_list_req)
+
+__m (process_cc_set_tei_map_ind)
+__m (process_cm_unassociated_sta_ind)
+
+__m (process_cm_set_key_req, u8 pid)
+__m (process_cm_set_key_cnf, u8 pid)
+__m (process_cm_get_key_req, u8 pid)
+__m (process_cm_get_key_cnf, u8 pid)
+
+__m (process_cc_who_ru_req)
+__m (process_cc_who_ru_cnf)
+__m (process_cc_discover_list_req)
+__m (process_cc_relay_req, bool encrypt)
+__m (process_cm_hfid_req)
+__m (process_cm_mme_error_ind)
+__m (process_cm_nw_stats_req)
+__m (process_cm_nw_info_req)
+__m (process_cm_link_stats_req)
+__m (vs__started__vs_get_tonemap_req)
+__m (vs__started__vs_get_link_stats_req)
+__m (vs__started__imac_get_discover_list_req)
+__m (process_cm_sta_cap_req)
+__m (vs__started__vs_get_snr_req)
+__n (vs_get_snr_cnf_send, phy_chandata_t * chan_data,
+ u16 tm_ber, bool success)
+__m (vs__started__vs_get_ce_stats_req)
+__m (vs__started__vs_get_pb_stats_req)
+
+__0 (poweron_start)
+__0 (poweron_stop)
+__0 (poweron__many__to_idle)
+__0 (poweron__idle__to_poweron)
+__0 (poweron__poweron__enter)
+__0 (poweron__poweron__leave)
+__0 (poweron__poweron__ustt_timeout)
+__0 (poweron__poweron__btt_timeout)
+__n (poweron__poweron__beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__0 (poweron__poweron_joining__left)
+__0 (poweron__joining__to_stop)
+__0 (poweron__usta__enter)
+__0 (poweron__usta__leave)
+__0 (poweron__usta__ustt_timeout)
+__n (poweron__usta__beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__n (poweron__usta__usta_ind, cp_net_t *net, cp_sta_t *sta)
+__0 (poweron__usta_joining__left)
+__n (poweron__ucco__beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__0 (poweron__sta__to_stop)
+__0 (poweron__cco__join_timeout)
+__0 (poweron__cco__all_sta_leaved)
+__0 (poweron_cco__enter)
+__0 (poweron_cco__leave)
+
+__m (process_cm_brg_info_cnf)
+__m (process_cm_brg_info_req)
+__0 (update_bridge_table)
+
+__m (drv__usta__drv_sta_sc)
+__m (drv__ucco__drv_sta_sc)
+__m (drv__cco__drv_sta_sc)
+__m (drv__sta__drv_sta_sc)
+__0 (sc__start_sc_join)
+__0 (sc__start_sc_add)
+__0 (sc__sc_idle__enter)
+__0 (sc__sc_idle__leave)
+__0 (sc__sc_join__enter)
+__0 (sc__sc_join__leave)
+__0 (sc__sc_join__sc_join_req_timeout)
+__0 (sc__sc_cco__sc_failed)
+__0 (sc__sc_timeout)
+__0 (sc_add__sc_timeout)
+__m (sc__sc_join__cm_sc_join_cnf)
+__m (sc__sc_join__cm_sc_join_req)
+__m (sc__sc_add__cm_sc_join_req)
+__n (sc__check_nid_set, cp_nid_t nid)
+__n (sc__check_sc_assoc_start, cp_mme_peer_t *sc_peer,
+ cp_mme_peer_t *cco_peer, cp_net_t *net)
+__n (sc__check_sc_status, bool sc_status)
+__n (sc__sc_wait_beacon__beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__n (sc__sc_wait_peer_associated__new_sta_associated,
+ cp_net_t *net, cp_sta_t *sta)
+__m (sc__sc_building_tek__cm_get_key_cnf_pid3)
+__m (sc__sc_nmk_exchange__cm_set_key_cnf_pid3)
+__n (sc__sc_usta_track_beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__n (sc__sc_ucco_track_beacon, bsu_beacon_t *beacon,
+ cp_net_t *net, cp_sta_t *sta)
+__m (assoc__sc_wait_assoc_cnf__cc_assoc_cnf)
+__m (assoc__sc_associated__cm_get_key_req_pid_3)
+__m (assoc__sc_tek_exchanged__cm_set_key_req_pid_3)
+__m (assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0)
+
+__m (handover__start)
+__m (handover__handover_info_ind_receive)
+__n (handover__handover_ended)
+__0 (whoru_timeout_process)
+
+#undef __0
+#undef __n
+#undef __n_
+#undef __m
+#undef __m_
+
+/* Scenario events. */
+#define SCENARIO_DEFS_EVENTS \
+ cp_msg_cc_who_ru_req_send, \
+ cp_msg_cc_who_ru_req_receive, \
+ cp_msg_cc_who_ru_cnf_send, \
+ cp_msg_cc_who_ru_cnf_receive, \
+ cp_msg_cc_assoc_req_send, \
+ cp_msg_cc_assoc_cnf_receive, \
+ cp_msg_cc_leave_req_send, \
+ cp_msg_cc_leave_cnf_receive, \
+ cp_msg_cc_leave_ind_receive, \
+ cp_msg_cc_leave_rsp_send, \
+ cp_msg_cc_set_tei_map_ind_receive_begin, \
+ cp_msg_cc_set_tei_map_ind_receive_sta, \
+ cp_msg_cc_set_tei_map_ind_receive_end, \
+ cp_msg_cc_relay_req_receive, \
+ cp_msg_cc_relay_ind_send, \
+ \
+ cp_msg_cm_unassociated_sta_ind_send, \
+ cp_msg_cm_unassociated_sta_ind_receive, \
+ cp_msg_cm_set_key_req_receive, \
+ cp_msg_cm_set_key_cnf_send, \
+ cp_msg_cm_get_key_req_send, \
+ cp_msg_cm_get_key_cnf_receive, \
+ cp_msg_cm_get_key_cnf_send, \
+ cp_msg_cm_get_key_req_receive, \
+ cp_msg_cm_hfid_req_receive, \
+ cp_msg_cm_hfid_cnf_send, \
+ cp_msg_cm_mme_error_ind_receive, \
+ cp_msg_cm_sc_join_cnf_send, \
+ cp_msg_cm_sc_join_cnf_receive, \
+ cp_msg_cm_sc_join_req_send, \
+ cp_msg_cm_sc_join_req_receive, \
+ cp_msg_cm_set_key_req_send, \
+ cp_msg_cm_set_key_cnf_receive, \
+ \
+ cp_msg_drv_sta_set_mac_addr_req_receive, \
+ cp_msg_drv_sta_set_cco_pref_req_receive, \
+ cp_msg_drv_sta_set_was_cco_req_receive, \
+ cp_msg_drv_sta_set_npw_req_receive, \
+ cp_msg_drv_sta_set_dpw_req_receive, \
+ cp_msg_drv_sta_set_sl_req_receive, \
+ cp_msg_drv_sta_set_nid_req_receive, \
+ cp_msg_drv_sta_set_m_sta_hfid_req_receive, \
+ cp_msg_drv_sta_set_u_sta_hfid_req_receive, \
+ cp_msg_drv_sta_set_avln_hfid_req_receive, \
+ cp_msg_drv_sta_set_tonemask_req_receive, \
+ cp_msg_drv_sta_mac_start_req_receive, \
+ cp_msg_drv_sta_mac_stop_req_receive, \
+ cp_msg_drv_sta_sc_req_receive, \
+ cp_msg_drv_sta_set_key_req_receive, \
+ cp_msg_drv_sta_set_key_ind_send, \
+ cp_msg_drv_sta_set_dak_req_receive, \
+ cp_msg_drv_any_cnf_send, \
+ cp_msg_drv_sta_get_key_req_receive, \
+ cp_msg_drv_sta_get_key_cnf_send, \
+ cp_msg_drv_sta_status_req_receive, \
+ cp_msg_drv_sta_status_cnf_send, \
+ cp_msg_drv_sta_status_ind_send, \
+ cp_msg_drv_sta_set_config_req_receive, \
+ cp_msg_drv_mcast_set_list_req_receive, \
+ \
+ cp_fsm_event_bare_new, \
+ cp_fsm_event_mme_new, \
+ cp_fsm_branch, \
+ \
+ cp_sta_core_gen_timed_event, \
+ cp_sta_core_stop_timed_or_cyclic_event, \
+ \
+ cp_beacon_create_default_schedules, \
+ cp_beacon_cco_send_discover_beacon, \
+ cp_beacon_process_tracked_avln, \
+ cp_beacon_reconfigure_timer, \
+ cp_beacon_change_nek, \
+ cp_beacon_deactivate, \
+ cp_beacon_synchronised, \
+ \
+ cp_av_cco_action_cco__assoc_start, \
+ cp_av_cco_action_cco__assoc_stop, \
+ cp_av_cco_action_cco__unassoc_start, \
+ cp_av_cco_action_cco__unassoc_stop, \
+ cp_av_cco_action_ucco_start, \
+ cp_av_cco_action_ucco_stop, \
+ cp_av_cco_action_ucco__to_cco, \
+ cp_av_cco_action_ucco__to_stop, \
+ cp_av_cco_action_cco__to_ucco, \
+ cp_av_cco_action_cco__cco_snid_conflict, \
+ \
+ sar_activate, \
+ sar_cleanup, \
+ \
+ pbproc_activate, \
+ \
+ cl_mactotei_new, \
+ cl_mactotei_copy_except_tag, \
+ cl_mactotei_copy_except_tei, \
+ cl_mactotei_addr_add, \
+ cl_mactotei_use_table, \
+ cl_mactotei_cancel, \
+ cl_get_igmp_groups, \
+ cl_update_igmp_groups, \
+ \
+ cp_msg_cm_brg_info_cnf_receive_begin, \
+ cp_msg_cm_brg_info_cnf_receive, \
+ cp_msg_cm_brg_info_cnf_receive_end, \
+ \
+ cp_msg_cm_brg_info_req_receive, \
+ cp_msg_cm_brg_info_cnf_send_begin, \
+ cp_msg_cm_brg_info_cnf_send, \
+ cp_msg_cm_brg_info_cnf_send_end, \
+ \
+ cp_sta_own_data_set_nid, \
+ \
+ cp_msg_cc_handover_req_receive, \
+ cp_msg_cc_handover_cnf_send, \
+ cp_msg_cc_handover_info_ind_receive_begin, \
+ cp_msg_cc_handover_info_ind_receive, \
+ cp_msg_cc_handover_info_ind_receive_end, \
+ cp_msg_cc_handover_info_rsp_send, \
+ \
+ cp_msg_cm_nw_stats_cnf_send_begin, \
+ cp_msg_cm_nw_stats_cnf_send, \
+ cp_msg_cm_nw_stats_cnf_send_end, \
+ cp_msg_cm_nw_stats_req_receive, \
+ \
+ cp_msg_cm_nw_info_cnf_send_begin, \
+ cp_msg_cm_nw_info_cnf_send, \
+ cp_msg_cm_nw_info_cnf_send_end, \
+ cp_msg_cm_nw_info_req_receive, \
+ \
+ cp_msg_cm_link_stats_cnf_send_begin, \
+ cp_msg_cm_link_stats_cnf_send, \
+ cp_msg_cm_link_stats_cnf_send_end, \
+ cp_msg_cm_link_stats_req_receive, \
+ \
+ cp_msg_vs_get_tonemap_req_receive, \
+ cp_msg_vs_get_tonemap_cnf_send, \
+ \
+ cp_msg_vs_get_link_stats_req_receive, \
+ cp_msg_vs_get_link_stats_cnf_send, \
+ \
+ cp_msg_imac_get_discover_list_req_receive, \
+ cp_msg_imac_get_discover_list_cnf_send_begin, \
+ cp_msg_imac_get_discover_list_cnf_send, \
+ cp_msg_imac_get_discover_list_cnf_send_end, \
+ \
+ cp_msg_cm_sta_cap_req_receive, \
+ cp_msg_cm_sta_cap_cnf_send, \
+ \
+ cp_msg_cc_discover_list_req_receive, \
+ cp_msg_cc_discover_list_cnf_send_begin, \
+ cp_msg_cc_discover_list_cnf_send_stations_begin, \
+ cp_msg_cc_discover_list_cnf_send_station, \
+ cp_msg_cc_discover_list_cnf_send_net_begin, \
+ cp_msg_cc_discover_list_cnf_send_net, \
+ cp_msg_cc_discover_list_cnf_send_end, \
+ \
+ cp_msg_drv_sta_set_u_sta_hfid_ind_send, \
+ cp_msg_drv_sta_set_avln_hfid_ind_send, \
+ \
+ cp_msg_vs_get_snr_req_receive, \
+ cp_msg_vs_get_snr_cnf_send, \
+ \
+ cp_msg_vs_get_ce_stats_req_receive, \
+ cp_msg_vs_get_ce_stats_cnf_send, \
+ \
+ cp_msg_vs_get_pb_stats_req_receive, \
+ cp_msg_vs_get_pb_stats_cnf_send_begin, \
+ cp_msg_vs_get_pb_stats_cnf_send_measure, \
+ cp_msg_vs_get_pb_stats_cnf_send_end
+
+/* MME send event. */
+#define __ms(event, param...) \
+typedef struct \
+{ \
+ cp_mme_peer_t peer; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME send event complex. */
+#define __msc(event, param...) \
+typedef struct \
+{ \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME send event with encryption information. */
+#define __msk(event, param...) \
+typedef struct \
+{ \
+ cp_mme_peer_t peer; \
+ cp_mme_peks_t peks; \
+ u8 pid; \
+ u8 pmn; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME send event for CC_RELAY.IND. */
+#define __msr(event, param...) \
+typedef struct \
+{ \
+ mac_t mac_fa; \
+ cp_tei_t ftei; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME receive event. */
+#define __mr(event, param...) \
+typedef struct \
+{ \
+ bool ok; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+/* MME receive event with encryption information. */
+#define __mrk(event, param...) \
+typedef struct \
+{ \
+ bool ok; \
+ cp_mme_peks_t peks; \
+ u8 pid; \
+ u8 pmn; \
+ bool new_prn; \
+ bool new_my_nonce; \
+ bool new_your_nonce; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+#define __p_(param) param;
+
+__ms (cp_msg_cc_who_ru_req_send, cp_nid_t nid)
+__mr (cp_msg_cc_who_ru_req_receive, cp_nid_t nid)
+__ms (cp_msg_cc_who_ru_cnf_send, cp_nid_t nid, mac_t cco_mac, char *avln_hfid)
+__mr (cp_msg_cc_who_ru_cnf_receive, cp_nid_t nid, mac_t cco_mac, char *avln_hfid)
+__mr (cp_msg_cc_discover_list_req_receive)
+__ms (cp_msg_cc_discover_list_cnf_send_begin, uint nb_sta, uint nb_net,
+ cp_msg_cc_discover_list_ctx_t * disc_ctx)
+__msc (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ cp_msg_cc_discover_list_ctx_t *disc_ctxc)
+__msc (cp_msg_cc_discover_list_cnf_send_station,
+ mac_t mac_addr, cp_tei_t tei,
+ enum cp_msg_cc_discover_list_same_network_t same_network,
+ cp_snid_t snid, hpav_access_t access, u8 cco_cap, bool proxy_cap,
+ bool backup_cco_cap, bool cco_status, bool pco_status,
+ bool backup_cco_status, u8 signal_level, u8 average_ble)
+__msc (cp_msg_cc_discover_list_cnf_send_net_begin,
+ cp_msg_cc_discover_list_ctx_t *disc_ctxc)
+__msc (cp_msg_cc_discover_list_cnf_send_net,
+ cp_nid_t nid, cp_snid_t snid, hpav_access_t access, u8 hm,
+ u8 numslots,
+ enum cp_msg_cc_discover_list_coodinated_status_t coordinated_status,
+ u16 offset)
+__msc (cp_msg_cc_discover_list_cnf_send_end)
+__ms (cp_msg_cc_assoc_req_send, enum cp_msg_cc_assoc_req_type_t request_type,
+ cp_nid_t nid, u8 cco_cap, u8 proxy_cap)
+__mr (cp_msg_cc_assoc_cnf_receive, enum cp_msg_cc_assoc_cnf_result_t result,
+ cp_nid_t nid, cp_snid_t snid, cp_tei_t sta_tei, u16 lease_time_min)
+__ms (cp_msg_cc_leave_req_send, enum cp_msg_cc_leave_req_reason_t reason)
+__mr (cp_msg_cc_leave_cnf_receive)
+__mr (cp_msg_cc_leave_ind_receive, enum cp_msg_cc_leave_ind_reason_t reason,
+ cp_nid_t nid)
+__ms (cp_msg_cc_leave_rsp_send)
+__mr (cp_msg_cc_set_tei_map_ind_receive_begin,
+ enum cp_msg_cc_set_tei_map_ind_mode_t mode, uint sta_nb)
+__mr (cp_msg_cc_set_tei_map_ind_receive_sta, cp_tei_t tei, mac_t mac,
+ enum cp_msg_cc_set_tei_map_ind_status_t status)
+__mr (cp_msg_cc_set_tei_map_ind_receive_end)
+__mr (cp_msg_cc_relay_req_receive, mac_t mac_fa, cp_tei_t ftei,
+ uint length, uint mmtype)
+__msr (cp_msg_cc_relay_ind_send, mac_t osa, cp_tei_t stei, uint length)
+
+__ms (cp_msg_cm_unassociated_sta_ind_send, cp_nid_t nid, u8 cco_cap)
+__mr (cp_msg_cm_unassociated_sta_ind_receive, cp_nid_t nid, u8 cco_cap)
+__mrk (cp_msg_cm_set_key_req_receive,
+ enum cp_msg_key_type_t key_type, u8 cco_cap, cp_nid_t nid, u8 new_eks,
+ cp_key_t new_key)
+__msk (cp_msg_cm_set_key_cnf_send, enum cp_msg_cm_set_key_cnf_result_t result,
+ u8 cco_cap)
+__msk (cp_msg_cm_get_key_req_send, bool relayed,
+ enum cp_msg_key_type_t key_type, cp_nid_t nid, u32 *hash_key)
+__mrk (cp_msg_cm_get_key_cnf_receive,
+ enum cp_msg_cm_get_key_cnf_result_t result,
+ enum cp_msg_key_type_t key_type, cp_nid_t nid, u8 eks, u32 *hash_key,
+ cp_key_t *key)
+__mrk (cp_msg_cm_get_key_req_receive,
+ bool relayed,
+ enum cp_msg_key_type_t key_type, cp_nid_t nid, u32 *hash_key)
+__msk (cp_msg_cm_get_key_cnf_send,
+ enum cp_msg_cm_get_key_cnf_result_t result,
+ enum cp_msg_key_type_t key_type, cp_nid_t nid, u8 eks, u32 *hash_key)
+__mr (cp_msg_cm_hfid_req_receive, enum cp_msg_cm_hfid_req_reqtype_t req_type,
+ cp_nid_t nid, char *hfid)
+__ms (cp_msg_cm_hfid_cnf_send, enum cp_msg_cm_hfid_cnf_restype_t restype,
+ char *hfid)
+__mr (cp_msg_cm_mme_error_ind_receive,
+ enum cp_msg_cm_mme_error_ind_reason_t reason, u8 rx_mmv,
+ cp_mmtype_t rx_mmtype, uint offset)
+__ms (cp_msg_cm_sc_join_cnf_send, cp_nid_t nid, bool avln_status, u8 cco_cap,
+ bool pco_cap, bool backup_cco_cap, bool cco_status, bool pco_status,
+ bool backup_cco_status)
+__mr (cp_msg_cm_sc_join_cnf_receive, cp_nid_t nid, bool avln_status, u8
+ cco_cap, bool pco_cap, bool backup_cco_cap, bool cco_status, bool
+ pco_status, bool backup_cco_status)
+__ms (cp_msg_cm_sc_join_req_send)
+__mr (cp_msg_cm_sc_join_req_receive, uint cco_cap)
+__msk (cp_msg_cm_set_key_req_send, enum cp_msg_key_type_t key_type, u8
+ cco_cap, cp_nid_t nid, u8 new_eks, cp_key_t new_key)
+__mrk (cp_msg_cm_set_key_cnf_receive, enum cp_msg_cm_set_key_cnf_result_t
+ result, u8 cco_cap);
+
+__mr (cp_msg_drv_sta_set_mac_addr_req_receive, mac_t mac)
+__mr (cp_msg_drv_sta_set_cco_pref_req_receive, bool cco_pref)
+__mr (cp_msg_drv_sta_set_was_cco_req_receive, bool was_cco)
+__mr (cp_msg_drv_sta_set_npw_req_receive, char *npw)
+__mr (cp_msg_drv_sta_set_dpw_req_receive, char *dpw)
+__mr (cp_msg_drv_sta_set_sl_req_receive, cp_security_level_t sl)
+__mr (cp_msg_drv_sta_set_nid_req_receive, cp_nid_t nid)
+__mr (cp_msg_drv_sta_set_m_sta_hfid_req_receive, char *m_sta_hfid)
+__mr (cp_msg_drv_sta_set_u_sta_hfid_req_receive, char *u_sta_hfid)
+__mr (cp_msg_drv_sta_set_avln_hfid_req_receive, char *avln_hfid)
+__mr (cp_msg_drv_sta_set_tonemask_req_receive, u32 *tonemask)
+__mr (cp_msg_drv_sta_mac_start_req_receive)
+__mr (cp_msg_drv_sta_mac_stop_req_receive)
+__mr (cp_msg_drv_sta_sc_req_receive, bool sc_join)
+__mr (cp_msg_drv_sta_set_key_req_receive, cp_key_t nmk,
+ enum cp_msg_drv_sta_set_key_type_t type, cp_nid_t nid,
+ cp_security_level_t sl)
+__ms (cp_msg_drv_sta_set_key_ind_send, cp_key_t nmk,
+ enum cp_msg_drv_sta_set_key_type_t type, cp_nid_t nid,
+ cp_security_level_t sl)
+__mr (cp_msg_drv_sta_set_dak_req_receive, cp_key_t dak)
+__ms (cp_msg_drv_any_cnf_send, cp_mmtype_t mmtype, cp_msg_drv_result_t result)
+__mr (cp_msg_drv_sta_get_key_req_receive)
+__ms (cp_msg_drv_sta_get_key_cnf_send, uint result, cp_key_t nmk,
+ cp_nid_t nid, cp_security_level_t sl)
+__mr (cp_msg_drv_sta_status_req_receive)
+__ms (cp_msg_drv_sta_status_cnf_send, uint result,
+ cp_msg_drv_sta_status_status_t status,
+ cp_msg_drv_sta_status_cco_t cco,
+ bool preferred_cco,
+ bool backup_cco,
+ bool simple_connect,
+ bsu_aclf_frequency_t pwl_sync_frequency)
+__ms (cp_msg_drv_sta_status_ind_send,
+ cp_msg_drv_sta_status_status_t status,
+ cp_msg_drv_sta_status_cco_t cco,
+ bool preferred_cco,
+ bool backup_cco,
+ bool simple_connect,
+ bsu_aclf_frequency_t pwl_sync_frequency)
+__mr (cp_msg_drv_sta_set_config_req_receive,
+ char *config)
+__mr (cp_msg_drv_mcast_set_list_req_receive,
+ int nb_groups,
+ mac_t* groups, int* nb_members,
+ mac_t* members)
+
+__mr (cp_msg_cm_brg_info_cnf_receive_begin, uint bsf, uint nbda)
+__mr (cp_msg_cm_brg_info_cnf_receive, mac_t mac)
+__mr (cp_msg_cm_brg_info_cnf_receive_end)
+
+__mr (cp_msg_cm_brg_info_req_receive)
+__ms (cp_msg_cm_brg_info_cnf_send_begin, const uint bsf, const uint nbda,
+ const uint own_tei)
+__msc (cp_msg_cm_brg_info_cnf_send, const mac_t mac)
+__msc (cp_msg_cm_brg_info_cnf_send_end)
+
+__mr (cp_msg_cc_handover_req_receive,
+ cp_msg_cc_handover_req_soft_hard_t soft_hard,
+ cp_msg_cc_handover_req_reason_t reason)
+__ms (cp_msg_cc_handover_cnf_send, cp_msg_cc_handover_cnf_result_t result)
+__mr (cp_msg_cc_handover_info_ind_receive_begin,
+ cp_msg_cc_handover_info_ind_rsc_t rsc,
+ cp_tei_t bcco,
+ uint num_sta)
+__mr (cp_msg_cc_handover_info_ind_receive, cp_tei_t tei, mac_t mac_addr,
+ uint status, cp_tei_t ptei)
+__mr (cp_msg_cc_handover_info_ind_receive_end)
+__ms (cp_msg_cc_handover_info_rsp_send)
+
+__ms (cp_msg_cm_nw_stats_cnf_send_begin, const uint num_stats)
+__msc (cp_msg_cm_nw_stats_cnf_send, mac_t mac, uint phy_dr_tx, uint phy_dr_rx)
+__msc (cp_msg_cm_nw_stats_cnf_send_end)
+__mr (cp_msg_cm_nw_stats_req_receive)
+
+__ms (cp_msg_cm_nw_info_cnf_send_begin, const uint num_nw)
+__msc (cp_msg_cm_nw_info_cnf_send, cp_nid_t nid, cp_snid_t snid,
+ cp_tei_t tei, enum cp_msg_cm_nw_info_cnf_sta_role_t sta_role,
+ mac_t cco_mac, hpav_access_t access, u8 num_coord_nets)
+__msc (cp_msg_cm_nw_info_cnf_send_end)
+__mr (cp_msg_cm_nw_info_req_receive)
+
+__ms (cp_msg_cm_link_stats_cnf_send_begin, u8 req_id, u8 res_type)
+__msc (cp_msg_cm_link_stats_cnf_send, mfs_t *mfs,
+ cp_msg_cm_link_stats_tlflag_t transmit)
+__msc (cp_msg_cm_link_stats_cnf_send_end)
+__mr (cp_msg_cm_link_stats_req_receive, int req_type, u8 req_id, cp_nid_t nid,
+ u8 lid, bool transmit, bool mgmt_flag, mac_t mac)
+__mr (cp_msg_cm_sta_cap_req_receive)
+__ms (cp_msg_cm_sta_cap_cnf_send, u8 av_version, mac_t mac, uint oui,
+ u8 auto_connect, u8 smoothing, u8 cco_cap, u8 proxy_cap,
+ u8 backup_cco_cap, u8 soft_handover, u8 two_sym_fc,
+ u16 max_fl_av, u8 homeplug_11_cap, u8 homeplug_101_int,
+ u8 regulatory_cap, u8 bidir_burst, u16 implementation_version)
+
+__mr (cp_msg_vs_get_tonemap_req_receive,
+ mac_t mac_addr,
+ cp_msg_vs_get_tonemap_tmi_t tmi,
+ u8 int_id,
+ cp_msg_vs_get_tonemap_req_dir_t dir)
+__ms (cp_msg_vs_get_tonemap_cnf_send,
+ cp_msg_vs_get_tonemap_cnf_result_t result,
+ uint beacon_delta,
+ u8 int_id,
+ tonemaps_t *tms,
+ cp_msg_vs_get_tonemap_tmi_t tmi)
+
+__mr (cp_msg_vs_get_link_stats_req_receive,
+ cp_msg_vs_get_link_stats_req_reqtype_t ReqType,
+ u8 ReqID,
+ cp_nid_t nid,
+ u8 lid,
+ cp_msg_vs_get_link_stats_req_tlflag_t TLFlag,
+ cp_msg_vs_get_link_stats_req_mgmtflag_t Mgmt_Flag,
+ mac_t dasa)
+__ms (cp_msg_vs_get_link_stats_cnf_send,
+ u8 ReqID,
+ cp_msg_vs_get_link_stats_cnf_result_t result,
+ u32 Bad_CRC)
+__mr (cp_msg_vs_get_snr_req_receive,
+ mac_t mac_addr,
+ cp_msg_vs_get_snr_req_int_t tm_int_i,
+ u8 int_id,
+ u8 carrier_gr)
+__ms (cp_msg_vs_get_snr_cnf_send,
+ cp_msg_vs_get_snr_cnf_result_t result,
+ u8 int_id, uint intervals_nb,
+ tonemap_intervals_t *intervals,
+ u16 tm_ber, u8 carrier_gr, u32 *snr)
+
+__mr (cp_msg_imac_get_discover_list_req_receive)
+__ms (cp_msg_imac_get_discover_list_cnf_send_begin,
+ cp_msg_imac_get_discover_list_cnf_result_t result,
+ u8 version, u8 num_stations)
+__msc (cp_msg_imac_get_discover_list_cnf_send,
+ mac_t mac, u8 ble_tx, u8 ble_rx)
+__msc (cp_msg_imac_get_discover_list_cnf_send_end)
+
+__ms (cp_msg_drv_sta_set_u_sta_hfid_ind_send, char *u_sta_hfid)
+__ms (cp_msg_drv_sta_set_avln_hfid_ind_send, char *avln_hfid)
+__ms (cl_mactotei_addr_add,
+ mac_t mac, uint tag)
+
+__mr (cp_msg_vs_get_ce_stats_req_receive, mac_t mac)
+__ms (cp_msg_vs_get_ce_stats_cnf_send, u8 version, u8 result, sta_t *sta,
+ tonemask_info_t *ti)
+
+__mr (cp_msg_vs_get_pb_stats_req_receive, cp_tei_t stei_filter)
+__ms (cp_msg_vs_get_pb_stats_cnf_send_begin, int nb_measures)
+__msc (cp_msg_vs_get_pb_stats_cnf_send_measure, int start_to_read,
+ int nb_entries)
+__msc (cp_msg_vs_get_pb_stats_cnf_send_end)
+
+#undef __ms
+#undef __msk
+#undef __msr
+#undef __mr
+#undef __mrk
+#undef __msc
+
+/* Event with return. */
+#define __er(event, param...) \
+typedef struct \
+{ \
+ bool ok; \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+
+/* Any event. */
+#define __e(event, param...) \
+typedef struct \
+{ \
+ PREPROC_FOR_EACH (__p_, ## param) \
+} scenario_event_ ## event ## _t;
+
+__e (cp_fsm_event_bare_new, cp_fsm_event_type_t type)
+__e (cp_fsm_event_mme_new, cp_fsm_event_type_t type)
+__e (cp_fsm_branch, cp_fsm_branch_t branch)
+
+__e (cp_sta_core_gen_timed_event, uint delay_min_ms, uint delay_max_ms)
+__e (cp_sta_core_stop_timed_or_cyclic_event)
+
+__e (cp_beacon_create_default_schedules)
+__e (cp_beacon_cco_send_discover_beacon)
+__e (cp_beacon_process_tracked_avln, bsu_beacon_t *beacon, cp_net_t *net)
+__e (cp_beacon_reconfigure_timer)
+__e (cp_beacon_change_nek, u8 eks, cp_key_t *nek, bool now)
+__e (cp_beacon_deactivate)
+__er (cp_beacon_synchronised)
+
+__e (cp_av_cco_action_ucco_start)
+__e (cp_av_cco_action_ucco_stop)
+__e (cp_av_cco_action_ucco__to_cco)
+__e (cp_av_cco_action_ucco__to_stop)
+__e (cp_av_cco_action_cco__to_ucco)
+__e (cp_av_cco_action_cco__assoc_start)
+__e (cp_av_cco_action_cco__assoc_stop)
+__e (cp_av_cco_action_cco__unassoc_start)
+__e (cp_av_cco_action_cco__unassoc_stop)
+__e (cp_av_cco_action_cco__cco_snid_conflict)
+
+__e (sar_activate, bool flag)
+__e (sar_cleanup)
+
+__e (pbproc_activate, bool flag)
+__e (cl_mactotei_use_table)
+__e (cl_mactotei_cancel)
+__e (cl_mactotei_new)
+__e (cl_mactotei_copy_except_tag)
+__e (cl_mactotei_copy_except_tei)
+__e (cp_sta_own_data_set_nid, cp_nid_t nid)
+__e (cl_get_igmp_groups, igmp_groups_t *groups)
+__e (cl_update_igmp_groups)
+#undef __e
+#undef __er
+
+#undef __p_
+
+#endif /* inc_scenario_defs_h */
diff --git a/cesar/cp/av/sta/action/test/utest/inc/test_sta_action.h b/cesar/cp/av/sta/action/test/utest/inc/test_sta_action.h
new file mode 100644
index 0000000000..177f1ca7d1
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/inc/test_sta_action.h
@@ -0,0 +1,70 @@
+#ifndef inc_test_sta_action_h
+#define inc_test_sta_action_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/test_sta_action.h
+ * \brief Test sta/action.
+ * \ingroup test
+ */
+#include "cp/inc/context.h"
+
+/** Contexts used in tests. */
+struct test_sta_action_t
+{
+ cp_t cp;
+ mac_config_t mac_config;
+ bsu_aclf_t bsu_aclf;
+};
+typedef struct test_sta_action_t test_sta_action_t;
+
+/**
+ * Initialise test contexts.
+ * \param ctx test context
+ */
+void
+test_sta_action_init (test_sta_action_t *ctx);
+
+/**
+ * Uninitialise test contexts.
+ * \param ctx test context
+ */
+void
+test_sta_action_uninit (test_sta_action_t *ctx);
+
+/**
+ * Reset test contexts.
+ * \param ctx test context
+ */
+void
+test_sta_action_reset (test_sta_action_t *ctx);
+
+/**
+ * Create our AVLN as if the STA was associated.
+ * \param ctx test context
+ * \param nid our NID
+ * \param snid our SNID
+ */
+void
+test_sta_action_create_our_net (test_sta_action_t *ctx, cp_nid_t nid,
+ cp_snid_t snid);
+
+/**
+ * Fill the beacon with the NID, SNID, STEI and MAC address if valid.
+ * \param beacon the beacon to fill.
+ * \param nid the network Identifier of the CCo.
+ * \param snid the short network identifier of the CCo.
+ * \param stei the source TEI of the CCo.
+ * \param mac the Mac address of the CCo.
+ */
+void
+test_sta_action_beacon_create (
+ bsu_beacon_t *beacon, cp_nid_t nid, cp_snid_t snid, cp_tei_t stei,
+ mac_t mac);
+
+#endif /* inc_test_sta_action_h */
diff --git a/cesar/cp/av/sta/action/test/utest/override/cp/inc/context.h b/cesar/cp/av/sta/action/test/utest/override/cp/inc/context.h
new file mode 100644
index 0000000000..f47ea99def
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/override/cp/inc/context.h
@@ -0,0 +1,78 @@
+#ifndef override_cp_inc_context_h
+#define override_cp_inc_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file override/cp/inc/context.h
+ * \brief Control plane context override.
+ * \ingroup test
+ */
+#include "cp/types.h"
+#include "cp/sta/action/inc/context.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/sta/mgr/inc/sta_mgr.h"
+#include "cl/cl.h"
+#include "mac/common/config.h"
+#include "mac/common/store.h"
+#include "mac/sar/sar.h"
+#include "mac/pbproc/pbproc.h"
+#include "lib/rnd.h"
+#include "lib/trace.h"
+#include "ce/tx/inc/tx.h"
+
+enum cp_handover_reason_t
+{
+ CP_HANDOVER_REASON_CCO_SELECTION,
+ CP_HANDOVER_REASON_CCO_LEAVING,
+ CP_HANDOVER_REASON_USER_APPOINT,
+ CP_HANDOVER_REASON_NB,
+};
+
+enum cp_handover_soft_hard_t
+{
+ CP_HANDOVER_SOFT_HARD_SOFT,
+ CP_HANDOVER_SOFT_HARD_HARD,
+ CP_HANDOVER_NB,
+};
+
+struct cp_handover_t
+{
+ /** Handover timeout. */
+ cp_sta_core_timed_event_def_t handover_timeout;
+
+ /** handover reason. */
+ enum cp_handover_reason_t reason;
+
+ /** Handover soft hard */
+ enum cp_handover_soft_hard_t soft_hard;
+};
+
+
+struct cp_t
+{
+ cp_sta_action_t sta_action;
+ cp_sta_mgr_t sta_mgr;
+ lib_rnd_t rnd;
+ cl_t *cl;
+ mac_config_t *mac_config;
+ mac_store_t *mac_store;
+ sar_t *sar;
+ pbproc_t *pbproc;
+ /** Handover context. */
+ struct cp_handover_t handover;
+ ce_tx_t ce_tx;
+ ce_rx_t *ce_rx;
+ void *bsu;
+ bsu_aclf_t *bsu_aclf;
+
+#if CONFIG_TRACE
+ trace_buffer_t trace;
+#endif
+};
+
+#endif /* override_cp_inc_context_h */
diff --git a/cesar/cp/av/sta/action/test/utest/override/cp/sta/core/core.h b/cesar/cp/av/sta/action/test/utest/override/cp/sta/core/core.h
new file mode 100644
index 0000000000..e7519405ee
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/override/cp/sta/core/core.h
@@ -0,0 +1,38 @@
+#ifndef override_cp_sta_core_core_h
+#define override_cp_sta_core_core_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file override/cp/sta/core/core.h
+ * \brief STA core override.
+ * \ingroup test
+ */
+#include "cp/types.h"
+#include "cp/fsm/forward.h"
+
+struct cp_sta_core_timed_event_def_t
+{
+};
+typedef struct cp_sta_core_timed_event_def_t cp_sta_core_timed_event_def_t;
+
+void
+cp_sta_core_gen_timed_event (
+ cp_t *cp_ctx, cp_sta_core_timed_event_def_t *sta_core_timed_event,
+ cp_fsm_event_t *fsm_event, uint event_delay_ms);
+
+void
+cp_sta_core_stop_timed_or_cyclic_event(
+ cp_t *cp_ctx, cp_sta_core_timed_event_def_t *sta_core_timed_event);
+
+u32
+cp_sta_core_get_date_ms (cp_t *ctx);
+
+void
+cp_sta_core_checkpoint (cp_t *ctx);
+
+#endif /* override_cp_sta_core_core_h */
diff --git a/cesar/cp/av/sta/action/test/utest/src/assoc.c b/cesar/cp/av/sta/action/test/utest/src/assoc.c
new file mode 100644
index 0000000000..bb0aa3ecf0
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/assoc.c
@@ -0,0 +1,1344 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/assoc.c
+ * \brief Test sta/action/assoc.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_sta_action.h"
+
+#include "cp/sta/action/action.h"
+#include "cp/sta/mgr/inc/sta.h"
+
+void
+assoc_create_cco (test_t t, test_sta_action_t *ctx, cp_snid_t snid,
+ cp_nid_t nid, cp_tei_t cco_tei, mac_t cco_mac,
+ cp_net_t **cco_net, cp_sta_t **cco,
+ scenario_entry_t *assoc_entry)
+{
+ /* Clean current state. */
+ if (*cco)
+ slab_release (*cco);
+ cp_sta_mgr_uninit (&ctx->cp);
+ cp_sta_mgr_init (&ctx->cp);
+ /* Set our NID/SNID. */
+ cp_sta_own_data_set_nid (&ctx->cp, nid);
+ cp_sta_own_data_set_snid (&ctx->cp, 0);
+ /* Create a CCo to associate with. */
+ *cco_net = cp_sta_mgr_add_avln (&ctx->cp, snid, nid);
+ dbg_assert (*cco_net);
+ *cco = cp_sta_mgr_sta_add (&ctx->cp, *cco_net, cco_tei, cco_mac);
+ if (cco_tei)
+ cp_net_set_cco (&ctx->cp, *cco_net, cco_tei);
+ /* Update scenario. */
+ dbg_assert (assoc_entry->event_id == SCENARIO_ACTION_ID &&
+ assoc_entry->action_cb == scenario_action_assoc_start_cb);
+ assoc_entry->params.action_assoc_start.cco_net = *cco_net;
+ assoc_entry->params.action_assoc_start.cco = *cco;
+}
+
+void
+assoc_basic_test_cases (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ test_case_begin (t, "assoc");
+ /* Create a CCo to associate with. */
+ const cp_snid_t snid = 2;
+ const cp_nid_t nid = 0xf11111111111ull;
+ const cp_tei_t cco_tei = 1, sta_tei = 2;
+ const mac_t cco_mac = 0x111111111111ull;
+ cp_net_t *cco_net;
+ cp_sta_t *cco = NULL;
+ cp_mme_peer_t cco_peer = CP_MME_PEER (cco_mac, cco_tei);
+ /* Association test. */
+ scenario_entry_t associate_entries[] = {
+ SCENARIO_ACTION (assoc_start, .cco_net = cco_net, .cco = cco),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_ACTION (assoc__unassociated__to_assoc),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = cco_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 15),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 10 * 60 * 1000,
+ .delay_max_ms = 10 * 60 * 1000),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 0, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ CC_ASSOC_CNF, ok)),
+ SCENARIO_END
+ };
+ test_begin (t, "ok")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_run (t, associate_entries, &globals);
+ test_fail_unless (cp_sta_own_data_get_nid (&ctx.cp) == nid);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == snid);
+ test_fail_unless (cp_sta_own_data_get_tei (&ctx.cp) == sta_tei);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (&ctx.cp);
+ cp_sta_t *our_cco = cp_net_get_cco (&ctx.cp, our_net);
+ test_fail_unless (our_cco == cco);
+ slab_release (our_cco);
+ } test_end;
+ test_begin (t, "errors")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ cp_sta_own_data_set_authenticated_status (&ctx.cp, true);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc_start, .cco_net = cco_net, .cco = cco),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_ACTION (assoc__unassociated__to_assoc),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = cco_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ /* Bad MAC. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__cc_assoc_cnf,
+ .peer = CP_MME_PEER (0x424242424242ull,
+ cco_tei)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ CC_ASSOC_CNF,
+ unrelated)),
+ /* Bad MME. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = false,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 15),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ CC_ASSOC_CNF,
+ unrelated)),
+ /* Bad NID. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid + 1, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 15),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ CC_ASSOC_CNF,
+ unrelated)),
+ /* Failure. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true, .result
+ = CP_MSG_CC_ASSOC_CNF_RESULT_FAILURE_OTHER_REASON,
+ .nid = nid, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 15),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ CC_ASSOC_CNF,
+ nok)),
+ /* LEFT event. */
+ SCENARIO_ACTION (assoc__unassociated__enter),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_left),
+ SCENARIO_END
+ };
+ /* Change hybrid mode to AV Only, at the end it should be hybrid
+ * delimiter mode. */
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ own_data->hybrid_mode = MAC_COEXISTENCE_AV_ONLY_MODE;
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp_sta_own_data_get_authenticated_status (&ctx.cp)
+ == false);
+ test_fail_unless (cp_sta_own_data_get_tei (&ctx.cp) == 0);
+ test_fail_unless (MAC_TEI_UNASSOCIATED == own_data->tei_track);
+ test_fail_unless (!cp_net_blacklisted_status_get (&ctx.cp, cco_net));
+ test_fail_unless (own_data->hybrid_mode =
+ MAC_COEXISTENCE_HYBRID_DELIMITERS_MODE);
+ } test_end;
+ test_begin (t, "timeout")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc_start, .cco_net = cco_net, .cco = cco),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_ACTION (assoc__unassociated__to_assoc),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = cco_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ /* Test timer start/stop here. */
+ SCENARIO_ACTION (assoc__start_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 1000,
+ .delay_max_ms = 1000),
+ /* First timeout. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 1000,
+ .delay_max_ms = 1000),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = cco_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ assoc_timeout, retry)),
+ /* Second timeout. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 1000,
+ .delay_max_ms = 1000),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = cco_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ assoc_timeout, retry)),
+ /* Third timeout, no retry. */
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__timeout),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ assoc_timeout,
+ no_retry)),
+ SCENARIO_ACTION (assoc__stop_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp_net_blacklisted_status_get (&ctx.cp, cco_net));
+ } test_end;
+ test_case_begin (t, "auth");
+ /* Authentication test. */
+ cp_key_t nek = { { 0x11112222, 0x33334444, 0x55556666, 0x77778888 } };
+ scenario_entry_t auth_entries[] = {
+ /* Associate. */
+ SCENARIO_SUB (associate_entries),
+ /* Authentication response. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_EVENT (cp_beacon_change_nek, .eks = 1, .nek = &nek,
+ .now = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_joined),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ ok)),
+ SCENARIO_END
+ };
+ test_begin (t, "ok")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ SCENARIO_SUB (auth_entries),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp_sta_own_data_get_authenticated_status (&ctx.cp)
+ == true);
+ } test_end;
+ test_begin (t, "errors")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate. */
+ SCENARIO_SUB (associate_entries),
+ /* Bad TEI. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = CP_MME_PEER (cco_mac, 42)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ unrelated)),
+ /* Bad MAC. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = CP_MME_PEER (0x424242424242ull,
+ cco_tei)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ unrelated)),
+ /* Bad MME. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = false,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ unrelated)),
+ /* Bad protocol run. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 3,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ unrelated)),
+ /* Bad NID. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid + 1,
+ .eks = 1, .key = &nek),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ unrelated)),
+ /* Bad key type. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NMK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ unrelated)),
+ /* Failure. */
+ SCENARIO_ACTION (assoc__associated__cm_get_key_cnf_pid_0,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result =
+ CP_MSG_CM_GET_KEY_CNF_RESULT_REQUEST_REFUSED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = NULL),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (ASSOCIATED,
+ CM_GET_KEY_CNF_PID0,
+ nok)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp_sta_own_data_get_authenticated_status (&ctx.cp)
+ == false);
+ test_fail_unless (cp_net_blacklisted_status_get (&ctx.cp, cco_net));
+ } test_end;
+ test_begin (t, "timeout")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate. */
+ SCENARIO_SUB (associate_entries),
+ /* Timeout. */
+ SCENARIO_ACTION (assoc__associated__timeout),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "leave")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate. */
+ SCENARIO_SUB (associate_entries),
+ /* Timeout. */
+ SCENARIO_ACTION (assoc__associated__to_leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_case_begin (t, "authed");
+ /* Authenticated test. */
+ test_begin (t, "renew")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Renew. */
+ SCENARIO_ACTION (assoc__authenticated__renew),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 5 * 60 * 1000 / 2,
+ .delay_max_ms = 5 * 60 * 1000 / 2),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send, .peer = cco_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_RENEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ SCENARIO_ACTION (assoc__authenticated__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 48 * 60),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = (48 * 60 - 5) * 60 * 1000,
+ .delay_max_ms = (48 * 60 - 5) * 60 * 1000),
+ /* Test timer stop here. */
+ SCENARIO_ACTION (assoc__authenticated__leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "renew error")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Bad TEI. */
+ SCENARIO_ACTION (assoc__authenticated__cc_assoc_cnf,
+ .peer = CP_MME_PEER (cco_mac, 42)),
+ /* Bad MAC. */
+ SCENARIO_ACTION (assoc__authenticated__cc_assoc_cnf,
+ .peer = CP_MME_PEER (0x424242424242ull,
+ cco_tei)),
+ /* Bad MME. */
+ SCENARIO_ACTION (assoc__authenticated__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = false,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 15),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ cp_key_t nek2 = { { 0x9999aaaa, 0xbbbbcccc, 0xddddeeee, 0xffff0000 } };
+ cp_key_t nekinvalid = {{0,0,0,0}};
+ test_begin (t, "NEK renew")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* NEK renew. */
+ SCENARIO_ACTION (assoc__authenticated__cm_set_key_req_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_receive, .ok = true,
+ .peks = CP_MME_PEKS_NONE, .pid = 1, .pmn = 1,
+ .new_prn = false, .new_your_nonce = false,
+ .key_type = CP_MSG_KEY_NONCE_ONLY,
+ .cco_cap = 0,
+ .nid = nid, .new_eks = 0, .new_key = nekinvalid),
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_send, .peer = cco_peer,
+ .peks = CP_MME_PEKS_NONE, .pid = 1, .pmn = 2,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = CP_CCO_LEVEL),
+ /* Same thing with the PEKS not embedded. */
+ SCENARIO_ACTION (assoc__authenticated__cm_set_key_req_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_receive, .ok = true,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED, .pid = 1,
+ .pmn = 1,
+ .new_prn = false, .new_your_nonce = false,
+ .key_type = CP_MSG_KEY_NONCE_ONLY,
+ .cco_cap = 0,
+ .nid = nid, .new_eks = 0, .new_key = nekinvalid),
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_send, .peer = cco_peer,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED, .pid = 1,
+ .pmn = 2,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = CP_CCO_LEVEL),
+ SCENARIO_ACTION (assoc__authenticated__cm_set_key_req_pid_1,
+ .peer = cco_peer),
+ /* Follow the procedure. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 1, .pmn = 3,
+ .new_prn = false, .new_your_nonce = false,
+ .key_type = CP_MSG_KEY_NEK,
+ .cco_cap = 0,
+ .nid = nid, .new_eks = 2, .new_key = nek2),
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_send, .peer = cco_peer,
+ .peks = CP_MME_PEKS_NMK, .pid = 1, .pmn = 255,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = CP_CCO_LEVEL),
+ SCENARIO_EVENT (cp_beacon_change_nek, .eks = 2, .nek = &nek2,
+ .now = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "avln failure")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ cp_sta_own_data_set_snid (&ctx.cp, snid);
+ bsu_beacon_t *beacon = INVALID_PTR;
+ cp_sta_t *not_cco, *bad_nid;
+ not_cco = cp_sta_mgr_sta_add (&ctx.cp, cco_net, 2, 0x223344556677ull);
+ slab_release (not_cco);
+ cp_net_t *net = cp_sta_mgr_add_avln (&ctx.cp, 3, nid + 1);
+ bad_nid = cp_sta_mgr_sta_add (&ctx.cp, net, 1, 0x334455667788ull);
+ slab_release (bad_nid);
+ cp_net_t *net_same_nid =
+ cp_sta_mgr_add_avln (
+ &ctx.cp, 4, cp_sta_own_data_get_nid (&ctx.cp));
+ cp_sta_t *cco_net_same_nid =
+ cp_sta_mgr_sta_add (&ctx.cp, net_same_nid, 3, 0x3);
+#define SCENARIO_AVLN_OK \
+ SCENARIO_ACTION (assoc__authenticated__beacon_not_received), \
+ SCENARIO_EVENT (cp_fsm_branch, \
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, \
+ BEACON_NOT_RECEIVED, \
+ else)),
+#define SCENARIO_AVLN_KO \
+ SCENARIO_ACTION (assoc__authenticated__beacon_not_received), \
+ SCENARIO_EVENT (cp_fsm_event_bare_new, \
+ .type = CP_FSM_EVENT_TYPE_avln_failure), \
+ SCENARIO_EVENT (cp_fsm_branch, \
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, \
+ BEACON_NOT_RECEIVED, \
+ avln_failure)),
+ scenario_entry_t entries[] = {
+ /* Normal situation, some loss of beacon. */
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = net_same_nid, .sta = cco_net_same_nid),
+ /* Critical situation, AVLN almost failed. */
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = net_same_nid, .sta = cco_net_same_nid),
+ /* AVLN fail. */
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = net, .sta = bad_nid),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = not_cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = net, .sta = bad_nid),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = not_cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = net, .sta = bad_nid),
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = cco_net, .sta = not_cco),
+ SCENARIO_AVLN_OK
+ SCENARIO_ACTION (assoc__authenticated__beacon, .beacon = beacon,
+ .net = net_same_nid, .sta = cco_net_same_nid),
+ SCENARIO_AVLN_KO
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ slab_release (cco_net_same_nid);
+ } test_end;
+ test_case_begin (t, "leave");
+ /* Leave test. */
+ test_begin (t, "sta ok")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Leave the AVLN. */
+ SCENARIO_ACTION (assoc_leave),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_leave),
+ SCENARIO_ACTION (assoc__authenticated__to_leave),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 40 * 3,
+ .delay_max_ms = 40 * 3),
+ SCENARIO_EVENT (cp_msg_cc_leave_req_send, .peer = cco_peer,
+ .reason =
+ CP_MSG_CC_LEAVE_REQ_REASON_USER_REQUEST),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, to_leave,
+ cco)),
+ SCENARIO_ACTION (assoc__leaving__cc_leave_cnf, .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_leave_cnf_receive, .ok = true),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (LEAVING, CC_LEAVE_CNF,
+ ok)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "sta errors")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Leave the AVLN. */
+ SCENARIO_ACTION (assoc_leave),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_leave),
+ SCENARIO_ACTION (assoc__authenticated__to_leave),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 40 * 3,
+ .delay_max_ms = 40 * 3),
+ SCENARIO_EVENT (cp_msg_cc_leave_req_send, .peer = cco_peer,
+ .reason =
+ CP_MSG_CC_LEAVE_REQ_REASON_USER_REQUEST),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, to_leave,
+ cco)),
+ /* Bad TEI. */
+ SCENARIO_ACTION (assoc__leaving__cc_leave_cnf,
+ .peer = CP_MME_PEER (cco_mac, 42)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (LEAVING, CC_LEAVE_CNF,
+ unrelated)),
+ /* Bad MAC. */
+ SCENARIO_ACTION (assoc__leaving__cc_leave_cnf,
+ .peer = CP_MME_PEER (0x424242424242ull,
+ cco_tei)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (LEAVING, CC_LEAVE_CNF,
+ unrelated)),
+ /* Bad MME, ignored. */
+ SCENARIO_ACTION (assoc__leaving__cc_leave_cnf, .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_leave_cnf_receive, .ok = false),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (LEAVING, CC_LEAVE_CNF,
+ ok)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "sta timeout")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Leave the AVLN. */
+ SCENARIO_ACTION (assoc_leave),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_leave),
+ SCENARIO_ACTION (assoc__authenticated__to_leave),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 40 * 3,
+ .delay_max_ms = 40 * 3),
+ SCENARIO_EVENT (cp_msg_cc_leave_req_send, .peer = cco_peer,
+ .reason =
+ CP_MSG_CC_LEAVE_REQ_REASON_USER_REQUEST),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, to_leave,
+ cco)),
+ /* Timeout. */
+ SCENARIO_ACTION (assoc__leaving__timeout),
+ SCENARIO_EVENT (cp_msg_cc_leave_req_send, .peer = cco_peer,
+ .reason =
+ CP_MSG_CC_LEAVE_REQ_REASON_USER_REQUEST),
+ /* Final timeout. */
+ SCENARIO_ACTION (assoc__leave_wait__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 1000,
+ .delay_max_ms = 1000),
+ SCENARIO_ACTION (assoc__leave_wait__timeout),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "cco ok")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Asked to leave the AVLN. */
+ SCENARIO_ACTION (assoc__authenticated__cc_leave_ind,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_leave_ind_receive, .ok = true,
+ .reason = CP_MSG_CC_LEAVE_IND_REASON_USER_REQUEST,
+ .nid = nid),
+ SCENARIO_EVENT (cp_msg_cc_leave_rsp_send, .peer = cco_peer),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED,
+ CC_LEAVE_IND, ok)),
+ /* Final timeout. */
+ SCENARIO_ACTION (assoc__leave_wait__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 1000,
+ .delay_max_ms = 1000),
+ SCENARIO_ACTION (assoc__leave_wait__timeout),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "cco errors")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, cco_mac, &cco_net,
+ &cco, associate_entries);
+ scenario_entry_t entries[] = {
+ /* Associate and authenticate. */
+ SCENARIO_SUB (auth_entries),
+ /* Bad TEI. */
+ SCENARIO_ACTION (assoc__authenticated__cc_leave_ind,
+ .peer = CP_MME_PEER (cco_mac, 42)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED,
+ CC_LEAVE_IND,
+ nok)),
+ /* Bad MAC. */
+ SCENARIO_ACTION (assoc__authenticated__cc_leave_ind,
+ .peer = CP_MME_PEER (0x424242424242ull,
+ cco_tei)),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED,
+ CC_LEAVE_IND,
+ nok)),
+ /* Bad MME. */
+ SCENARIO_ACTION (assoc__authenticated__cc_leave_ind,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_leave_ind_receive, .ok = false,
+ .reason = CP_MSG_CC_LEAVE_IND_REASON_USER_REQUEST,
+ .nid = nid),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED,
+ CC_LEAVE_IND,
+ nok)),
+ /* Bad NID. */
+ SCENARIO_ACTION (assoc__authenticated__cc_leave_ind,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_leave_ind_receive, .ok = true,
+ .reason = CP_MSG_CC_LEAVE_IND_REASON_USER_REQUEST,
+ .nid = nid + 1),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED,
+ CC_LEAVE_IND,
+ nok)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Cleanup. */
+ slab_release (cco);
+ test_sta_action_uninit (&ctx);
+ /* New test, the CCo does not exists. */
+ test_sta_action_init (&ctx);
+ test_sta_action_create_our_net (&ctx, 0x1, 0x0);
+ test_begin (t, "sta ok")
+ {
+ scenario_entry_t entries[] = {
+ /* Leave the AVLN. */
+ SCENARIO_ACTION (assoc__authenticated__to_leave),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, to_leave,
+ no_cco)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_sta_action_uninit (&ctx);
+}
+
+void
+assoc_basic_test_cases_cco_unknow_mac_addr (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ test_case_begin (t, "assoc");
+ /* Create a CCo to associate with. */
+ const cp_snid_t snid = 2;
+ const cp_nid_t nid = 0xf11111111111ull;
+ const cp_tei_t cco_tei = 1, sta_tei = 2;
+ const mac_t cco_mac = 0x111111111111ull;
+ cp_net_t *cco_net;
+ cp_sta_t *cco = NULL;
+ cp_mme_peer_t cco_peer = CP_MME_PEER (cco_mac, cco_tei);
+ /* Association test. */
+ scenario_entry_t associate_entries[] = {
+ SCENARIO_ACTION (assoc_start, .cco_net = cco_net, .cco = cco),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_ACTION (assoc__unassociated__to_assoc),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = CP_MME_PEER (MAC_BROADCAST, cco_tei),
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ SCENARIO_ACTION (assoc__wait_assoc_cnf__cc_assoc_cnf,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = snid, .sta_tei = sta_tei,
+ .lease_time_min = 15),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 10 * 60 * 1000,
+ .delay_max_ms = 10 * 60 * 1000),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 0, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (WAIT_ASSOC_CONF,
+ CC_ASSOC_CNF, ok)),
+ SCENARIO_END
+ };
+ test_begin (t, "ok")
+ {
+ assoc_create_cco (t, &ctx, snid, nid, cco_tei, MAC_BROADCAST, &cco_net,
+ &cco, associate_entries);
+ scenario_run (t, associate_entries, &globals);
+ test_fail_unless (cp_sta_own_data_get_nid (&ctx.cp) == nid);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) == snid);
+ test_fail_unless (cp_sta_own_data_get_tei (&ctx.cp) == sta_tei);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (&ctx.cp);
+ cp_sta_t *our_cco = cp_net_get_cco (&ctx.cp, our_net);
+ test_fail_unless (our_cco == cco);
+ test_fail_unless (cp_sta_get_mac_address (our_cco) == cco_mac);
+ slab_release (our_cco);
+ } test_end;
+ /* Cleanup. */
+ slab_release (cco);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+assoc_basic_test_cases_nek_request (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ cp_key_t nek = {{0x11111111, 0x22222222, 0x33333333, 0x44444444}};
+
+ test_case_begin (t, "assoc");
+ /* Create a CCo to associate with. */
+ const cp_snid_t snid = 2;
+ const cp_nid_t nid = 0xf11111111111ull;
+ const cp_tei_t cco_tei = 1, sta_tei = 2;
+ const mac_t cco_mac = 0x111111111111ull;
+ const mac_t sta_mac = 0x111111111121ull;
+ cp_sta_t *cco = NULL;
+ cp_mme_peer_t cco_peer = CP_MME_PEER (cco_mac, cco_tei);
+ cp_mme_peer_t wrong_peer = CP_MME_PEER (cco_mac, cco_tei+1);
+
+ cp_net_t *net = cp_sta_mgr_add_avln (&ctx.cp, snid, nid);
+ dbg_assert (net);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+
+ /* Set our NID/SNID. */
+ cp_sta_own_data_set_nid (&ctx.cp, nid);
+ cp_sta_own_data_set_snid (&ctx.cp, snid);
+ cp_sta_own_data_set_mac_address (&ctx.cp, sta_mac);
+ cp_sta_own_data_set_tei (&ctx.cp, sta_tei);
+
+ /* Create a CCo. */
+ cco = cp_sta_mgr_sta_add (&ctx.cp, net, cco_tei, cco_mac);
+ cp_net_set_cco (&ctx.cp, net, cco_tei);
+
+ test_begin (t, "wrong peer answer")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = wrong_peer),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "reception fails")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = false,
+ .peks = CP_MME_PEKS_NMK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "wrong peks")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_DAK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "wrong pmn")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_DAK, .pid = 1, .pmn = 0x3,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "wrong nid")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_DAK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid+1, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "wrong result")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_DAK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_REQUEST_REFUSED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "wrong key type")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_DAK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_DAK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "wrong nonce")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_DAK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = true,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "all good")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (assoc__authenticated__nek_request),
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = cco_peer, .peks = CP_MME_PEKS_NMK,
+ .pid = 1, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid),
+ SCENARIO_ACTION (assoc__authenticated__cm_get_key_cnf_pid_1,
+ .peer = cco_peer),
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 1, .pmn = 0xff,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .nid = nid, .eks = 1,
+ .key = &nek),
+ SCENARIO_EVENT (cp_beacon_change_nek, .eks = 1, .nek = &nek,
+ .now = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+
+ /* Cleanup. */
+ slab_release (cco);
+
+ test_sta_action_uninit (&ctx);
+}
+
+void
+assoc_test_case_track (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ test_case_begin (t, "2 network with same NID");
+ test_begin (t, "Our CCo and another one on the same NID")
+ {
+ /* Create our AVLN. */
+ test_sta_action_create_our_net (&ctx, 0x1, 0x0);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (&ctx.cp);
+ cp_sta_t *our_cco = cp_sta_mgr_sta_add (&ctx.cp, our_net, 1, 1);
+ cp_net_set_cco (&ctx.cp, our_net, 1);
+ /* Create the other network. */
+ cp_net_t *other_net = cp_sta_mgr_add_avln (&ctx.cp, 0x1, 0x1);
+ cp_sta_t *other_cco = cp_sta_mgr_sta_add (&ctx.cp, other_net, 1, 2);
+ cp_net_set_cco (&ctx.cp, other_net, 1);
+ /* Make our station track the our_net. */
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ cp_sta_own_data_set_snid (&ctx.cp, 0x0);
+ own_data->nid_track = 0x1;
+ own_data->cco_mac_addr_track = 0x1;
+ /* Create the beacons. */
+ bsu_beacon_t beacon_our_net, beacon_other_net;
+ test_sta_action_beacon_create (
+ &beacon_our_net, cp_net_get_nid (&ctx.cp, our_net),
+ cp_net_get_snid (&ctx.cp, our_net),
+ cp_sta_get_tei (our_net->cco),
+ cp_sta_get_mac_address (our_net->cco));
+ test_sta_action_beacon_create (
+ &beacon_other_net, cp_net_get_nid (&ctx.cp, other_net),
+ cp_net_get_snid (&ctx.cp, other_net),
+ cp_sta_get_tei (other_net->cco),
+ cp_sta_get_mac_address (other_net->cco));
+ scenario_entry_t entries[] = {
+ /* We receive the beacon of the other network. */
+ SCENARIO_ACTION (assoc__authenticated__beacon_not_received), \
+ SCENARIO_EVENT (cp_fsm_branch, \
+ .branch = CP_FSM_BRANCH (AUTHENTICATED, \
+ BEACON_NOT_RECEIVED, \
+ else)),
+ SCENARIO_ACTION (assoc__authenticated__beacon,
+ .beacon = &beacon_other_net,
+ .net = other_net, .sta = other_cco),
+ SCENARIO_END,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (ctx.cp.sta_action.assoc.beacon_loss);
+ /* An AVLN failure occurs, the network tracked is still our_net.
+ * The delay to track the other net is not ended. */
+ scenario_entry_t entry[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon,
+ .beacon = &beacon_other_net,
+ .net = other_net,
+ .sta = other_cco),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_END,
+ };
+ scenario_run (t, entry, &globals);
+ /* Make our network too old. */
+ our_net->beacon_recv_date = phy_date () - MAC_MS_TO_TCK (1000);
+ /* An AVLN failure occurs, and the network tracked is still our_net.
+ * This test should end by tracking the other net. */
+ scenario_entry_t entry2[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon,
+ .beacon = &beacon_other_net,
+ .net = other_net,
+ .sta = other_cco),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln,
+ .beacon = &beacon_other_net,
+ .net = other_net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_END,
+ };
+ scenario_run (t, entry2, &globals);
+ test_fail_unless (own_data->nid_track == other_net->nid);
+ test_fail_unless (cp_sta_own_data_get_snid (&ctx.cp) ==
+ other_net->snid);
+ cp_net_t *net_track = cp_sta_mgr_get_avln (&ctx.cp, other_net->snid,
+ other_net->nid);
+ test_fail_unless (net_track == other_net);
+ /* We track the other network now. */
+ cp_net_t *net_exch = our_net;
+ our_net = other_net;
+ other_net = net_exch;
+ cp_sta_t *sta_exch = our_cco;
+ our_cco = other_cco;
+ other_cco = sta_exch;
+ /* The CCo change. Create the new one. */
+ bsu_beacon_t beacon_our_new_net;
+ test_sta_action_beacon_create (&beacon_our_new_net, 0x1, 0, 2, 4);
+ cp_sta_t *our_new_cco = cp_sta_mgr_sta_add (&ctx.cp, our_net, 2, 4);
+ cp_sta_private_t *p = PARENT_OF (cp_sta_private_t, public_data,
+ our_new_cco);
+ p->is_cco = true;
+ /* update the beacon reception date. */
+ our_net->beacon_recv_date = phy_date ();
+ other_net->beacon_recv_date = phy_date ();
+ scenario_entry_t entry3[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon,
+ .beacon = &beacon_our_new_net,
+ .net = our_net,
+ .sta = our_new_cco),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln,
+ .beacon = &beacon_our_new_net,
+ .net = our_net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ nid_match)),
+ SCENARIO_END,
+ };
+ scenario_run (t, entry3, &globals);
+ /* Received a central beacon from another station but in a different
+ * slot id. */
+ beacon_our_net.vf.slotid = 2;
+ scenario_entry_t entry4[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon,
+ .beacon = &beacon_our_net,
+ .net = our_net,
+ .sta = our_cco),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_END,
+ };
+ scenario_run (t, entry4, &globals);
+ /* clean up. */
+ slab_release (our_new_cco);
+ slab_release (our_cco);
+ slab_release (other_cco);
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+ }
+ test_end;
+ test_begin (t, "The new CCo does not provide its mac address")
+ {
+ bsu_beacon_t beacon_our_net;
+ test_sta_action_init (&ctx);
+ /* Create our AVLN. */
+ test_sta_action_create_our_net (&ctx, 0x1, 0x0);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (&ctx.cp);
+ cp_sta_t *our_cco =
+ cp_sta_mgr_sta_add (&ctx.cp, our_net, 1, MAC_BROADCAST);
+ cp_net_set_cco (&ctx.cp, our_net, 1);
+ /* Make our station track the our_net. */
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ cp_sta_own_data_set_snid (&ctx.cp, 0x0);
+ own_data->nid_track = 0x1;
+ own_data->cco_mac_addr_track = MAC_ZERO;
+ /* Create the beacons. */
+ test_sta_action_beacon_create (
+ &beacon_our_net, cp_net_get_nid (&ctx.cp, our_net),
+ cp_net_get_snid (&ctx.cp, our_net),
+ cp_sta_get_tei (our_cco),
+ MAC_ZERO);
+ scenario_entry_t entry[] = {
+ /* Our CCo. It does not provide the mac address too. */
+ SCENARIO_ACTION (poweron__poweron__beacon,
+ .beacon = &beacon_our_net,
+ .net = our_net,
+ .sta = our_cco),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_ACTION (poweron__poweron__beacon,
+ .beacon = &beacon_our_net,
+ .net = our_net,
+ .sta = our_cco),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ nid_match)),
+ SCENARIO_END,
+ };
+ scenario_run (t, entry, &globals);
+ /* clean up. */
+ slab_release (our_cco);
+ test_sta_action_uninit (&ctx);
+ }
+ test_end;
+}
+
+void
+assoc_test_suite (test_t t)
+{
+ test_suite_begin (t, "assoc");
+ assoc_basic_test_cases (t);
+ assoc_basic_test_cases_cco_unknow_mac_addr (t);
+ assoc_basic_test_cases_nek_request (t);
+ assoc_test_case_track (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/beacon_stub.c b/cesar/cp/av/sta/action/test/utest/src/beacon_stub.c
new file mode 100644
index 0000000000..5593dc7f24
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/beacon_stub.c
@@ -0,0 +1,102 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/beacon_stub.c
+ * \brief Beacon stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "cp/beacon/beacon.h"
+#include "cp/sta/mgr/sta_mgr.h"
+
+#include "lib/scenario/scenario.h"
+
+void
+cp_beacon_create_default_schedules (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_beacon_create_default_schedules);
+}
+
+void
+cp_beacon_process_tracked_avln (cp_t *ctx, bsu_beacon_t *beacon,
+ cp_net_t *net)
+{
+ dbg_assert (ctx);
+ dbg_assert (beacon);
+ dbg_assert (net);
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (ctx);
+ own->nid_track = beacon->vf.nid;
+ own->tei_track = beacon->vf.stei;
+ own->cco_mac_addr_track = beacon->bmis.mac_address.present ?
+ beacon->bmis.mac_address.mac_address : MAC_ZERO;
+ scenario_event (cp_beacon_process_tracked_avln, param);
+ test_fail_unless (beacon == param->beacon);
+ test_fail_unless (net == param->net);
+ test_fail_unless (cp_net_get_nid (ctx, net) == beacon->vf.nid);
+}
+
+void
+cp_beacon_beacon_not_received (cp_t *ctx)
+{
+ dbg_assert (ctx);
+}
+
+void
+cp_beacon_reconfigure_timer (cp_t *ctx, bool cco)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_beacon_reconfigure_timer);
+}
+
+void
+cp_beacon_change_nek (cp_t *ctx, uint eks, cp_key_t nek, bool now)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_beacon_change_nek, param);
+ test_fail_unless (eks == param->eks);
+ test_fail_unless (memcmp (&nek, param->nek, sizeof (nek)) == 0);
+ test_fail_unless (now == param->now);
+}
+
+void
+cp_beacon_deactivate (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_beacon_deactivate);
+}
+
+void
+cp_beacon_poweron_init (cp_t *ctx)
+{
+}
+
+void
+cp_av_beacon_sta_update_beacon_data (cp_t *ctx)
+{
+}
+
+void
+cp_beacon_cco_update_beacon_data (cp_t *ctx)
+{
+}
+
+
+void
+cp_av_beacon_discover_init (cp_t *ctx) {}
+
+void
+cp_av_beacon_discover_uninit (cp_t *ctx) {}
+
+bool
+cp_beacon_synchronised (cp_t *ctx)
+{
+ scenario_event (cp_beacon_synchronised, param);
+ return param->ok;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/bridge.c b/cesar/cp/av/sta/action/test/utest/src/bridge.c
new file mode 100644
index 0000000000..0c215575e1
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/bridge.c
@@ -0,0 +1,497 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/bridge.c
+ * \brief Test sta/action/bridge
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/test_sta_action.h" // test_sta_*
+#include "lib/scenario/scenario.h" // scenario_*
+#include "lib/blk.h" // blk_check_memory
+#include "lib/test.h" // test_t
+#include "cl/inc/context.h" // cl_t
+#include "cl/bridge_table.h" // bridge_table_*
+#include "cp/sta/action/bridge.h" // cp_sta_action_bridge_init
+
+/**
+ * Test the behavior of the FSM and the parsing of the bridge MMEs.
+ * \param t the test structure.
+ */
+static void
+bridge_info_test_cases (test_t t)
+{
+ /* Test context. */
+ test_sta_action_t ctx;
+ ctx.mac_config.sta_mac_address = 0x42421234;
+ test_sta_action_init (&ctx);
+
+ /* Create structure for global parameters. */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_mme_peer_t peer = CP_MME_PEER (0xaabbccddeeffull, 1);
+ test_case_begin (t, "bridge info receive");
+ test_begin (t, "decode of CM_BRG_INFO.CNF failed")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_cnf, .peer = peer),
+ /* Decode of CM_BRG_INFO.REQ failed. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_begin,
+ .ok = false,
+ .bsf = 0,
+ .nbda = 0),
+ /* Should finish immediately. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "peer with no bridging function")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_cnf, .peer = peer),
+ /* BSF set to 0 (no bridging function). */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_begin,
+ .ok = true,
+ .bsf = 0,
+ .nbda = 5),
+ /* End of message decoding. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_end,
+ .ok = true),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "empty bridge table")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_cnf, .peer = peer),
+ /* No entry but peer is able to bridge. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_begin,
+ .ok = true,
+ .bsf = 1,
+ .nbda = 0),
+ /* End of message decoding. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_end,
+ .ok = true),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "bridge table with one entry")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_cnf, .peer = peer),
+ /* One entry and is able to bridge. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_begin,
+ .ok = true,
+ .bsf = 1,
+ .nbda = 1),
+ /* Get a valid MAC address. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive,
+ .ok = true,
+ .mac = 0x111111111110ull),
+ /* Use new table. */
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ /* End of message decoding. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_end,
+ .ok = true),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "bridge table with one broadcast entry")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_cnf, .peer = peer),
+ /* One entry and is able to bridge. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive_begin,
+ .ok = true,
+ .bsf = 1,
+ .nbda = 5),
+ /* Get a valid MAC address. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive,
+ .ok = true,
+ .mac = 0x111111111110ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive,
+ .ok = true,
+ .mac = 0x111111111112ull),
+ /* Broadcast entry. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_receive,
+ .ok = true,
+ .mac = 0xffffffffffffull),
+ /* Cancel table. */
+ SCENARIO_EVENT (cl_mactotei_cancel),
+ /* End immediately. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "bridge info request received");
+
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+ /* Override CL context. */
+ static cl_t cl;
+ ctx.cp.cl = &cl;
+ ctx.cp.cl->mac_config = &ctx.mac_config;
+ /* Fake bridge table. */
+ bridge_table_init (&cl);
+
+ test_begin (t, "decode of CM_BRG_INFO.REQ failed")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_req, .peer = peer),
+ /* Decode of CM_BRG_INFO.REQ failed. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_req_receive,
+ .ok = false),
+ /* Should finish immediately. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "empty local bridge table")
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_req, .peer = peer),
+ /* Decode of CM_BRG_INFO.REQ succeed. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 0),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ /* Should finish immediately. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "bridge table with 4 entries")
+ {
+ bridge_table_add (&cl, 0x111111111110ull);
+ bridge_table_add (&cl, 0x111111111112ull);
+ bridge_table_add (&cl, 0x111111111114ull);
+ bridge_table_add (&cl, 0x111111111116ull);
+ bridge_table_update (&cl);
+ scenario_entry_t entries[] = {
+ /* Initialize the event. */
+ SCENARIO_ACTION (process_cm_brg_info_req, .peer = peer),
+ /* Decode of CM_BRG_INFO.REQ succeed. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 4),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111110ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111112ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111114ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111116ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ /* Should finish immediately. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Clean. */
+ bridge_table_deinit (&cl);
+
+ /* New test case to check the behavior of the bridge table update. */
+ test_case_begin (t, "bridge table update in STA action (garbage"
+ " collector)");
+
+ /* Start with a fresh bridge table. */
+ bridge_table_init (&cl);
+ cp_sta_action_bridge_init (&ctx.cp);
+
+ test_begin (t, "new bridged entry but not associated, not sending the"
+ " bridge table")
+ {
+ /* The purpose of this scenario is to check that when a new entry is
+ * added to the bridge table and we are not associated, the table is
+ * not sent. */
+ /* Add a new entry into the table. */
+ bridge_table_add (&cl, 0x111111111110ull);
+ /* No update for at least 5 seconds/cycles. */
+ uint count;
+ for (count = 0;
+ count < ctx.cp.sta_action.bridge.min_time_send_new_s + 1;
+ count ++)
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Last emission too recent, do nothing. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ }
+ } test_end;
+
+ /* Pretend we are authenticated.. */
+ cp_sta_own_data_set_authenticated_status (&ctx.cp, true);
+
+ test_begin (t, "we are associated, send the bridge table")
+ {
+ /* The purpose of this scenario is to check that when we are
+ * authenticated, the table is sent. */
+ /* Refresh entry date. */
+ bridge_table_add (&cl, 0x111111111110ull);
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* There should be one new entry in the table. The table should be
+ * broadcast to the STA of the AVLN. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 1),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111110ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Adding a new entry to the bridge table. New table will be sent in 5
+ * seconds. */
+ test_begin (t, "new bridged entry, wait 5 seconds between updates")
+ {
+ /* The purpose of this scenario is to check that when a new entry is
+ * added to the bridge table, it is not sent right now if the last
+ * emission is too close. */
+ /* Add a new entry into the table. */
+ bridge_table_add (&cl, 0x111111111112ull);
+ /* No update for 4 seconds/cycles. */
+ uint count;
+ for (count = 0;
+ count < ctx.cp.sta_action.bridge.min_time_send_new_s - 1;
+ count ++)
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Last emission too recent, do nothing. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ }
+ /* The new bridge table should be emitted now! */
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Bridge table content sent. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 2),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111110ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111112ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "bridge table is sent after 90s without change")
+ {
+ /* The purpose of this test is to check the bridge table is emitted
+ * after a 90 period of inactivity. */
+ /* There should be no emission for
+ * ctx.cp.sta_action.bridge.wait_time_without_update_s - 1
+ * seconds/cycles. */
+ uint count;
+ for (count = 0;
+ count < ctx.cp.sta_action.bridge.wait_time_without_update_s - 1;
+ count ++)
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Last emission too recent without update, do nothing. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ }
+ /* The table should be re-emitted now! */
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* No change in the table, still two entries. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 2),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111110ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111112ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "entry expires in the bridge table, last emission is a"
+ " long time ago, bridge table emitted")
+ {
+ /* The purpose of this scenario is to check that when an entry
+ * expires, the table is emitted again if the last emission cycle is
+ * not too close. */
+ /* First entry should expire in 4 cycles. */
+ uint count;
+ for (count = 0; count < 4; count ++)
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Bridge table has not changed yet. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ }
+ /* The table should be re-emitted now! */
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Only one entry in the table. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 1),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send,
+ .mac = 0x111111111112ull),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "entry expires in the bridge table, last emission is"
+ " too close, bridge table not emitted")
+ {
+ /* The purpose of this scenario is to check that when an entry
+ * expires, the table is not emitted if the last emission cycle is too
+ * close. */
+ /* Last entry should expire now, but the table should not be
+ * re-emitted for the next 5 seconds. */
+ uint count;
+ for (count = 0;
+ count < ctx.cp.sta_action.bridge.min_time_send_new_s - 1;
+ count++)
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Not emitted. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ }
+ } test_end;
+
+ test_begin (t, "bridge table update, become empty, still emitted")
+ {
+ /* The purpose of this scenario is to check that when an update of a
+ * bridge table make it empty, it should still been emitted. */
+ /* Last entry should expire now, bridge table become empty. */
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Empty table emitted. */
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_begin,
+ .bsf = 1,
+ .nbda = 0),
+ SCENARIO_EVENT (cp_msg_cm_brg_info_cnf_send_end),
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "empty bridge table (not after an update, should not been"
+ " emitted")
+ {
+ /* The purpose of this scenario is to check that when a bridge table
+ * is empty, it should not be emitted (not changed still the last
+ * emission!). */
+ /* Wait for more than 90 cycles. */
+ uint count;
+ for (count = 0;
+ count < ctx.cp.sta_action.bridge.wait_time_without_update_s * 2;
+ count++)
+ {
+ scenario_entry_t entries[] = {
+ /* Initialize the event. Call the function to update bridge table.
+ * It is normally called by the CP garbage every one second. */
+ SCENARIO_ACTION (update_bridge_table),
+ /* Not emitted. */
+ SCENARIO_END
+ };
+ /* Check this scenario. */
+ scenario_run (t, entries, &globals);
+ }
+ } test_end;
+
+ /* Clean. */
+ bridge_table_deinit (&cl);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+bridge_test_suite (test_t t)
+{
+ test_suite_begin (t, "bridge");
+ bridge_info_test_cases (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/cco_stub.c b/cesar/cp/av/sta/action/test/utest/src/cco_stub.c
new file mode 100644
index 0000000000..444b0ba5ef
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/cco_stub.c
@@ -0,0 +1,166 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/cco_stub.c
+ * \brief CCo stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "cp/cco/action/cco_action.h"
+
+#include "cp/sta/mgr/sta_mgr.h"
+#include "lib/scenario/scenario.h"
+
+void
+cp_av_cco_action_handover__start (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_cco__snid_conflict (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_av_cco_action_cco__cco_snid_conflict);
+}
+
+void
+cp_av_cco_action_cco__cc_assoc_req (cp_t *ctx, cp_mme_rx_t * assoc_req)
+{
+}
+
+void
+cp_av_cco_action_ucco__cc_assoc_req (cp_t *ctx, cp_mme_rx_t * assoc_req)
+{
+}
+
+void
+cp_av_cco_action_cco__cm_get_key_req_pid0 (cp_t *ctx, cp_mme_rx_t * assoc_req)
+{
+}
+
+void
+cp_av_cco_action_cco__cc_leave_req (cp_t *ctx, cp_mme_rx_t *mme)
+{
+}
+
+void
+cp_av_cco_action_cco__cco_nek_change (cp_t *ctx)
+{
+}
+
+void
+cp_cco_action_tei_release (cp_t *ctx, u8 tei)
+{
+}
+
+void
+cp_av_cco_action__drv_mac_stop (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_tei_in_use (cp_t *ctx, cp_tei_t tei)
+{
+}
+
+void
+cp_av_cco_action_cco__cco_nek_change__nek_provide (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_cco__cco_nek_change__nek_timeout__wait (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_cm_set_key_cnf_receive (cp_t *ctx, cp_mme_rx_t *mme)
+{
+}
+
+void
+cp_av_cco_action_cco__cco_nek_change__timeout (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_nek_change_prevent (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_cco_selection__clear (cp_t *ctx)
+{
+}
+
+void
+cp_av_cco_action_cco__cm_get_key_req_pid1 (cp_t *ctx, cp_mme_rx_t * assoc_req)
+{
+}
+
+void
+cp_av_cco_action_cco__cc_discover_list_req (
+ cp_t *ctx, cp_net_t *net, cp_sta_t *sta) __attribute__ ((weak));
+
+void
+cp_av_cco_action_cco__cc_discover_list_req (
+ cp_t *ctx, cp_net_t *net, cp_sta_t *sta) {}
+
+void
+cp_av_cco_action_ucco_start (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_ucco_start);
+}
+
+void
+cp_av_cco_action_ucco_stop (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_ucco_stop);
+}
+
+void
+cp_av_cco_action_ucco__to_cco (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_ucco__to_cco);
+}
+
+void
+cp_av_cco_action_ucco__to_stop (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_ucco__to_stop);
+}
+
+void
+cp_av_cco_action_cco__to_ucco (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_cco__to_ucco);
+}
+
+void
+cp_av_cco_action_cco__unassoc_start (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_cco__unassoc_start);
+}
+
+void
+cp_av_cco_action_cco__unassoc_stop (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_cco__unassoc_stop);
+}
+
+void
+cp_av_cco_action_cco__assoc_start (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_cco__assoc_start);
+}
+
+void
+cp_av_cco_action_cco__assoc_stop (cp_t *ctx)
+{
+ scenario_event (cp_av_cco_action_cco__assoc_stop);
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/ce_stub.c b/cesar/cp/av/sta/action/test/utest/src/ce_stub.c
new file mode 100644
index 0000000000..ec7ff29510
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/ce_stub.c
@@ -0,0 +1,24 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/ce_stub.c
+ * \brief CE stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "lib/blk.h"
+#include "ce/rx/rx.h"
+
+extern blk_t* nsr_block;
+
+blk_t *
+ce_rx_get_nsr (ce_rx_t *ce_rx, cp_tei_t tei, uint int_index,
+ uint int_version, u16* tm_ber)
+{
+ return nsr_block;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/core_stub.c b/cesar/cp/av/sta/action/test/utest/src/core_stub.c
new file mode 100644
index 0000000000..dae4a03060
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/core_stub.c
@@ -0,0 +1,42 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/core_stub.c
+ * \brief STA core stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "cp/sta/core/core.h"
+
+#include "lib/scenario/scenario.h"
+
+void
+cp_sta_core_gen_timed_event (
+ cp_t *cp_ctx, cp_sta_core_timed_event_def_t *sta_core_timed_event,
+ cp_fsm_event_t *fsm_event, uint event_delay_ms)
+{
+ dbg_assert (cp_ctx);
+ dbg_assert (sta_core_timed_event);
+ scenario_event (cp_sta_core_gen_timed_event, param);
+ test_fail_unless (event_delay_ms >= param->delay_min_ms);
+ test_fail_unless (event_delay_ms <= param->delay_max_ms);
+}
+
+void
+cp_sta_core_stop_timed_or_cyclic_event(
+ cp_t *cp_ctx, cp_sta_core_timed_event_def_t *sta_core_timed_event)
+{
+ dbg_assert (cp_ctx);
+ dbg_assert (sta_core_timed_event);
+ scenario_event (cp_sta_core_stop_timed_or_cyclic_event);
+}
+
+void
+cp_sta_core_checkpoint (cp_t *ctx)
+{
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/cp_stub.c b/cesar/cp/av/sta/action/test/utest/src/cp_stub.c
new file mode 100644
index 0000000000..5309cd66bb
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/cp_stub.c
@@ -0,0 +1,29 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/cp_stub.c
+ * \brief CP stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "cp/cp.h"
+
+void
+cp_compute_nmk_and_nid_from_npw (cp_t *ctx, const char *npw,
+ cp_security_level_t sl)
+{
+ dbg_assert (ctx);
+ dbg_assert (npw);
+}
+
+u32
+cp_sta_core_get_date_ms (cp_t *ctx)
+{
+ return 0;
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/dataplane_stub.c b/cesar/cp/av/sta/action/test/utest/src/dataplane_stub.c
new file mode 100644
index 0000000000..7ae91e0334
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/dataplane_stub.c
@@ -0,0 +1,140 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/dataplane_stub.c
+ * \brief Data plane layers stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "cl/cl_mactotei.h"
+#include "mac/pbproc/pbproc.h"
+#include "cp/inc/context.h"
+
+cl_mactotei_blk_t *
+cl_mactotei_new (void)
+{
+ if (!scenario.current
+ || (scenario.current->event_id != SCENARIO_EVENT_cl_mactotei_new))
+ return INVALID_PTR;
+ scenario_event (cl_mactotei_new);
+ return INVALID_PTR;
+}
+
+void
+cl_mactotei_copy_except_tag (cl_t *ctx, cl_mactotei_blk_t *table, uint tag)
+{
+ if (!scenario.current
+ || (scenario.current->event_id !=
+ SCENARIO_EVENT_cl_mactotei_copy_except_tag))
+ return; /* Be less strict. */
+ scenario_event (cl_mactotei_copy_except_tag);
+}
+
+void
+cl_mactotei_copy_except_tei (cl_t *ctx, cl_mactotei_blk_t *table, uint tei)
+{
+ if (!scenario.current
+ || (scenario.current->event_id !=
+ SCENARIO_EVENT_cl_mactotei_copy_except_tei))
+ return; /* Be less strict. */
+ scenario_event (cl_mactotei_copy_except_tei);
+}
+
+uint
+cl_mactotei_table_find_tei_from_mac (cl_t *ctx, mac_t mac)
+{
+ return MAC_TEI_STA_MIN;
+}
+
+void
+cl_mactotei_addr_add (cl_mactotei_blk_t *table, mac_t mac, uint tei, uint tag)
+{
+ scenario_event_cl_mactotei_addr_add_t *param =
+ &scenario.current->params.event_cl_mactotei_addr_add;
+
+ if (!scenario.current
+ || (scenario.current->event_id != SCENARIO_EVENT_cl_mactotei_addr_add))
+ return; /* Be less strict. */
+
+ scenario_event (cl_mactotei_addr_add);
+ test_fail_unless (mac == param->mac);
+ test_fail_unless (tag == param->tag);
+}
+
+void
+cl_mactotei_use_table (cl_t *ctx, cl_mactotei_blk_t *table)
+{
+ if (!scenario.current
+ || scenario.current->event_id != SCENARIO_EVENT_cl_mactotei_use_table)
+ return; /* Be less strict. */
+ scenario_event (cl_mactotei_use_table);
+}
+
+void
+cl_mactotei_release_table (cl_t *ctx)
+{
+}
+
+void
+cl_mactotei_cancel (cl_mactotei_blk_t *table)
+{
+ /* No check is done, just emit the event. */
+ scenario_event (cl_mactotei_cancel);
+}
+
+igmp_groups_t *
+cl_get_igmp_groups (cl_t *ctx)
+{
+ scenario_event (cl_get_igmp_groups, param);
+
+ return param->groups;
+}
+
+void
+cl_update_igmp_groups (cl_t *ctx)
+{
+ if (!scenario.current
+ || (scenario.current->event_id != SCENARIO_EVENT_cl_update_igmp_groups))
+ return; /* Be less strict. */
+
+ scenario_event (cl_update_igmp_groups);
+}
+
+void
+sar_activate (sar_t *ctx, bool flag)
+{
+ scenario_event (sar_activate, param);
+ test_fail_unless (flag == param->flag);
+}
+
+void
+sar_cleanup (sar_t *ctx)
+{
+ if (!scenario.current
+ || scenario.current->event_id != SCENARIO_EVENT_sar_cleanup)
+ return; /* Be less strict. */
+ scenario_event (sar_cleanup);
+}
+
+void
+sar_sta_remove (sar_t *ctx, u8 tei)
+{
+ cp_t *cp = (void *) ctx;
+ dbg_check (mac_store_sta_remove (cp->mac_store, tei));
+}
+
+void
+pbproc_activate (pbproc_t *ctx, bool flag)
+{
+ scenario_event (pbproc_activate, param);
+ test_fail_unless (flag == param->flag);
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/drv.c b/cesar/cp/av/sta/action/test/utest/src/drv.c
new file mode 100644
index 0000000000..2fc811ccc1
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/drv.c
@@ -0,0 +1,855 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/drv.c
+ * \brief Test sta/action/drv.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "cp/av/sta/action/poweron.h"
+#include "inc/test_sta_action.h"
+#include "lib/stats.h"
+#include "cl/inc/context.h"
+#include "bsu/aclf/aclf.h"
+
+#include <string.h>
+
+static void
+drv_set_params (cp_t *ctx,
+ mac_t mac,
+ bool cco_pref,
+ bool was_cco,
+ const char *npw,
+ const char *dpw,
+ cp_security_level_t sl,
+ cp_nid_t nid,
+ const char *m_sta_hfid,
+ const char *u_sta_hfid,
+ const char *avln_hfid,
+ const u32 *tonemask,
+ uint carrier_nb)
+{
+ int i;
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (ctx);
+ cp_sta_own_data_set_mac_address (ctx, mac);
+ own->cco_prefered = cco_pref;
+ cp_sta_own_data_set_was_cco (ctx, was_cco);
+ cp_sta_own_data_set_npw (ctx, npw);
+ cp_sta_own_data_set_dpw (ctx, dpw);
+ cp_sta_own_data_set_security_level (ctx, sl);
+ cp_sta_own_data_set_nid (ctx, nid);
+ cp_sta_own_data_set_hfid_manufacturer (ctx, m_sta_hfid);
+ cp_sta_own_data_set_hfid_user (ctx, u_sta_hfid);
+ cp_sta_own_data_set_hfid_avln (ctx, avln_hfid);
+ dbg_assert (tonemask == NULL);
+ for (i = 0; i < PHY_TONEMASK_WORDS; i++)
+ ctx->mac_config->tonemask_info.tonemask[i] = 0;
+ ctx->mac_config->tonemask_info.carrier_nb = carrier_nb;
+}
+
+static void
+drv_check_params (cp_t *ctx,
+ test_t t,
+ mac_t mac,
+ bool cco_pref,
+ bool was_cco,
+ const char *npw,
+ const char *dpw,
+ cp_security_level_t sl,
+ cp_nid_t nid,
+ const char *m_sta_hfid,
+ const char *u_sta_hfid,
+ const char *avln_hfid,
+ const u32 *tonemask,
+ uint carrier_nb)
+{
+ int i;
+ test_within (t);
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (ctx);
+ test_fail_unless (mac == cp_sta_own_data_get_mac_address (ctx));
+ test_fail_unless (cco_pref == own->cco_prefered);
+ test_fail_unless (was_cco == cp_sta_own_data_get_was_cco (ctx));
+ test_fail_unless (strcmp (npw, cp_sta_own_data_get_npw (ctx)) == 0);
+ test_fail_unless (strcmp (dpw, cp_sta_own_data_get_dpw (ctx)) == 0);
+ test_fail_unless (sl == cp_sta_own_data_get_security_level (ctx));
+ test_fail_unless (nid == cp_sta_own_data_get_nid (ctx));
+ test_fail_unless (strcmp (m_sta_hfid, own->hfid_manufacturer) == 0);
+ test_fail_unless (strcmp (u_sta_hfid, own->hfid_user) == 0);
+ test_fail_unless (strcmp (avln_hfid, own->hfid_avln) == 0);
+ if (tonemask == NULL)
+ for (i = 0; i < PHY_TONEMASK_WORDS; i++)
+ test_fail_unless (ctx->mac_config->tonemask_info.tonemask[i]
+ == 0);
+ else
+ for (i = 0; i < PHY_TONEMASK_WORDS; i++)
+ test_fail_unless (ctx->mac_config->tonemask_info.tonemask[i]
+ == tonemask[i]);
+ test_fail_unless (ctx->mac_config->tonemask_info.carrier_nb
+ == carrier_nb);
+}
+
+static void
+drv_basic_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_mme_peer_t peer = CP_MME_PEER (0xaabbccddeeffull, MAC_TEI_FOREIGN);
+ cp_nid_t nid;
+ test_case_begin (t, "basic");
+ test_begin (t, "set")
+ {
+ drv_set_params (&ctx.cp, MAC_BROADCAST, false, false, "", "",
+ CP_SECURITY_LEVEL_SC, 1, "", "", "", NULL, 0);
+ u32 tonemask[PHY_TONEMASK_WORDS];
+ uint i;
+ nid = ((u64) CP_SECURITY_LEVEL_HS) << (HPAV_NID_SIZE_BITS - 2)
+ | 0x002233445566ull;
+ uint carriers_nb = tonemask_default (tonemask);
+ u8 my_param_u8 = 0;
+ u64 my_param_u64 = 0;
+ char config[] = "my_param_u8:42 my_param_u64:0x4242424242";
+ lib_stats_init ();
+ lib_stats_set_stat_value_notype ("my_param_u8", &my_param_u8,
+ LIB_STATS_ACCESS_WRITE_ONLY,
+ LIB_STATS_USER);
+ lib_stats_set_stat_value_notype ("my_param_u64", &my_param_u64,
+ LIB_STATS_ACCESS_READ_WRITE,
+ LIB_STATS_USER);
+ scenario_entry_t entries[] = {
+ /* Set MAC address. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_mac_addr_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_mac_addr_req_receive,
+ .ok = true,
+ .mac = 0x112233445566ull),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_MAC_ADDR_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set CCo preferred flag. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_cco_pref_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_cco_pref_req_receive,
+ .ok = true,
+ .cco_pref = true),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_CCO_PREF_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set was CCo flag. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_was_cco_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_was_cco_req_receive,
+ .ok = true,
+ .was_cco = true),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_WAS_CCO_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set NPW. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_npw_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_npw_req_receive,
+ .ok = true,
+ .npw = "p4ssw0rd"),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_NPW_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set DPW. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_dpw_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_dpw_req_receive,
+ .ok = true,
+ .dpw = "s3cr3t"),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_DPW_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set SL. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_sl_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_sl_req_receive,
+ .ok = true,
+ .sl = CP_SECURITY_LEVEL_HS),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_SL_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set NID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_nid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_nid_req_receive,
+ .ok = true,
+ .nid = nid),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_NID_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set manufacturer STA HFID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_m_sta_hfid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_m_sta_hfid_req_receive,
+ .ok = true,
+ .m_sta_hfid = "the M STA HFID"),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_M_STA_HFID_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set user STA HFID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_u_sta_hfid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_u_sta_hfid_req_receive,
+ .ok = true,
+ .u_sta_hfid = "the U STA HFID"),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_U_STA_HFID_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set AVLN HFID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_avln_hfid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_avln_hfid_req_receive,
+ .ok = true,
+ .avln_hfid = "the AVLN HFID"),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_AVLN_HFID_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set tonemask. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_tonemask_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_tonemask_req_receive,
+ .ok = true,
+ .tonemask = tonemask),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_TONEMASK_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Set config. */
+ SCENARIO_ACTION (drv__drv_sta_set_config_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_config_req_receive,
+ .ok = true,
+ .config = config),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_CONFIG_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ scenario_run (t, entries, &globals);
+ drv_check_params (&ctx.cp, t, 0x112233445566ull, true, true,
+ "p4ssw0rd", "s3cr3t", CP_SECURITY_LEVEL_HS,
+ nid, "the M STA HFID",
+ "the U STA HFID", "the AVLN HFID", tonemask,
+ carriers_nb);
+
+
+ cp_key_t nmk_old = { { 0x0, 0x0, 0x0, 0x0} };
+ cp_key_t nmk = { { 0x11112222, 0x33334444, 0x55556666, 0x77778888 } };
+ ctx.cp.sta_mgr.sta_own_data.nmk = nmk_old;
+ cp_nid_t old_nid = 0x1;
+
+ cp_sta_own_data_set_nid (&ctx.cp, old_nid);
+ cp_sta_own_data_set_security_level (&ctx.cp, 0x0);
+ lib_stats_uninit ();
+ test_fail_if (my_param_u8 != 42);
+ test_fail_if (my_param_u64 != 0x4242424242ull);
+
+ /* Check poweron init set neet_set to false. */
+ cp_av_sta_action_poweron_init (&ctx.cp);
+ test_fail_unless (false == ctx.cp.sta_action.poweron.enter.need_set);
+
+ enum cp_msg_drv_sta_set_key_type_t type =
+ CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_NID;
+ cp_security_level_t sl = 0x1;
+ nid = ((u64) sl) << (HPAV_NID_SIZE_BITS - 2) | 0x123456789abcdull;
+ scenario_entry_t entries2[] = {
+ /* Set KEY. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_key_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_key_req_receive,
+ .ok = true,
+ .nmk = nmk,
+ .type = type,
+ .nid = nid,
+ .sl = sl),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_KEY_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_run (t, entries2, &globals);
+
+ /* nid and nmk have not changed yet. */
+ cp_key_t nmk_new = cp_sta_own_data_get_nmk (&ctx.cp);
+ for (i = 0; i < COUNT (nmk_new.key); i++)
+ test_fail_unless (nmk_new.key[i] == nmk_old.key[i]);
+ test_fail_unless (cp_sta_own_data_get_nid (&ctx.cp) ==
+ old_nid);
+ /* But new values are set in context. */
+ test_fail_unless (true == ctx.cp.sta_action.poweron.enter.need_set);
+ for (i = 0; i < COUNT (nmk.key); i++)
+ test_fail_unless (nmk.key[i] ==
+ ctx.cp.sta_action.poweron.enter.nmk.key[i]);
+ test_fail_unless (nid == ctx.cp.sta_action.poweron.enter.nid);
+
+ nid = 1;
+ cp_sta_own_data_set_nid (&ctx.cp, nid);
+ cp_key_t new_nmk = { { 0x11112222, 0x33334444, 0x55556666, 0x77778889 } };
+
+ type = CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_SECURITY_LEVEL;
+ scenario_entry_t entries3[] = {
+ /* Set KEY. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_key_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_key_req_receive,
+ .ok = true,
+ .nmk = new_nmk,
+ .type = type,
+ .nid = nid,
+ .sl = sl),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_KEY_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_key_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_key_req_receive,
+ .ok = false,
+ .nmk = new_nmk,
+ .type = type,
+ .nid = nid,
+ .sl = sl),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_KEY_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_run (t, entries3, &globals);
+
+ nid = cp_secu_nmk2nid (&ctx.cp, new_nmk, sl);
+ test_fail_unless ((cp_sta_own_data_get_nid (&ctx.cp)) == old_nid);
+
+ /* SET DAK. */
+ cp_key_t dak = {{ 0x11111111, 0x22222222, 0x33333333, 0x44444444}};
+ cp_key_t own_dak;
+ scenario_entry_t entries4[] = {
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_dak_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_dak_req_receive,
+ .ok = true,
+ .dak = dak),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_DAK_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_run (t, entries4, &globals);
+
+ own_dak = cp_sta_own_data_get_dak (&ctx.cp);
+ for (i = 0; i < COUNT (dak.key); i++)
+ test_fail_unless (dak.key[i] == own_dak.key[i]);
+
+ memset (&dak, 0, sizeof (cp_key_t));
+ scenario_entry_t entries5[] = {
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_dak_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_dak_req_receive,
+ .ok = false,
+ .dak = dak),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_DAK_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_run (t, entries5, &globals);
+
+ own_dak = cp_sta_own_data_get_dak (&ctx.cp);
+ for (i = 0; i < COUNT (dak.key); i++)
+ test_fail_unless (dak.key[i] != own_dak.key[i]);
+ } test_end;
+ test_begin (t, "set error")
+ {
+ drv_set_params (&ctx.cp, MAC_BROADCAST, false, false, "", "",
+ CP_SECURITY_LEVEL_SC, 1, "", "", "", NULL, 0);
+ scenario_entry_t entries[] = {
+ /* Set MAC address. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_mac_addr_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_mac_addr_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_MAC_ADDR_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set CCo preferred flag. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_cco_pref_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_cco_pref_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_CCO_PREF_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set was CCo flag. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_was_cco_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_was_cco_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_WAS_CCO_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set NPW. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_npw_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_npw_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_NPW_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set DPW. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_dpw_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_dpw_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_DPW_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set SL. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_sl_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_sl_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_SL_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set NID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_nid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_nid_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_NID_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set manufacturer STA HFID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_m_sta_hfid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_m_sta_hfid_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_M_STA_HFID_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set user STA HFID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_u_sta_hfid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_u_sta_hfid_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_U_STA_HFID_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set AVLN HFID. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_avln_hfid_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_avln_hfid_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_AVLN_HFID_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ /* Set tonemask. */
+ SCENARIO_ACTION (drv__stopped__drv_sta_set_tonemask_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_tonemask_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_SET_TONEMASK_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ scenario_run (t, entries, &globals);
+ drv_check_params (&ctx.cp, t, MAC_BROADCAST, false, false, "", "",
+ CP_SECURITY_LEVEL_SC, 1, "", "", "", NULL, 0);
+ } test_end;
+ test_begin (t, "start")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__stopped__drv_sta_mac_start_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_mac_start_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_poweron),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_MAC_START_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "start error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__stopped__drv_sta_mac_start_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_mac_start_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_MAC_START_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "stop")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__started__drv_sta_mac_stop_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_mac_stop_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ /* ... */
+ SCENARIO_ACTION (drv__stopping__stopped),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_STA_MAC_STOP_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_sta_action_uninit (&ctx);
+}
+
+void
+drv_get_key_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_case_begin (t, "DRV_GET_KEY");
+
+ test_begin (t, "Good and bad")
+ {
+ cp_key_t nmk = { { 0x11112222, 0x33334444, 0x55556666, 0x77778888 } };
+ cp_security_level_t sl = 0x1;
+ cp_nid_t nid = (((u64) sl) << (HPAV_NID_SIZE_BITS - 2)) | 0x123456789abcdull;
+ cp_mme_peer_t peer = CP_MME_PEER (0x012345, MAC_TEI_UNASSOCIATED);
+ test_sta_action_init (&ctx);
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ /* Set NID, sl, and nmk. */
+ ctx.cp.sta_mgr.sta_own_data.nmk = nmk;
+ cp_sta_own_data_set_security_level (&ctx.cp, sl);
+ cp_sta_own_data_set_nid (&ctx.cp, nid);
+
+ cp_key_t nmk_null = { {0, 0, 0, 0}};
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__drv_sta_get_key_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_get_key_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_drv_sta_get_key_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_DRV_RESULT_SUCCESS,
+ .nmk = nmk,
+ .nid = nid,
+ .sl = sl),
+ SCENARIO_ACTION (drv__drv_sta_get_key_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_get_key_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_sta_get_key_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_DRV_RESULT_FAILURE,
+ .nmk = nmk_null,
+ .nid = 0,
+ .sl = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ }
+ test_end;
+}
+
+
+void
+drv_get_sta_status_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_case_begin (t, "DRV_GET_STA_STATUS");
+ cp_mme_peer_t peer = CP_MME_PEER(0x1, MAC_TEI_FOREIGN);
+ test_sta_action_init (&ctx);
+ cl_t cl;
+ ctx.cp.cl = &cl;
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ cp_sta_own_data_set_tei (&ctx.cp, 1);
+ cp_sta_own_data_set_security_level (&ctx.cp, CP_SECURITY_LEVEL_HS);
+ *((bsu_aclf_frequency_t*) &ctx.cp.bsu_aclf->frequency) =
+ BSU_ACLF_FREQ_50HZ;
+
+ test_begin (t, "Good and bad")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__drv_sta_status_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_DRV_RESULT_SUCCESS,
+ .status = CP_MSG_DRV_STA_STATUS_STATUS_ASSOC,
+ .cco = CP_MSG_DRV_STA_STATUS_CCO_STA,
+ .preferred_cco = false,
+ .backup_cco = false,
+ .simple_connect = false,
+ .pwl_sync_frequency = BSU_ACLF_FREQ_50HZ),
+ SCENARIO_ACTION (drv__drv_sta_status_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_req_receive,
+ .ok = false),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_DRV_RESULT_FAILURE,
+ .status = 0,
+ .cco = 0,
+ .preferred_cco = false,
+ .backup_cco = false,
+ .simple_connect = false,
+ .pwl_sync_frequency = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ }
+ test_end;
+ test_begin (t, "UCCo/CCo status")
+ {
+ scenario_entry_t entries_ucco[] = {
+ SCENARIO_ACTION (drv__drv_sta_status_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_DRV_RESULT_SUCCESS,
+ .status = CP_MSG_DRV_STA_STATUS_STATUS_UNASSOC,
+ .cco = CP_MSG_DRV_STA_STATUS_CCO_CCO,
+ .preferred_cco = false,
+ .backup_cco = false,
+ .simple_connect = false,
+ .pwl_sync_frequency = BSU_ACLF_FREQ_50HZ),
+ SCENARIO_END
+ };
+ /* Set our AVLN. */
+ cp_snid_t snid = cp_sta_own_data_get_snid (&ctx.cp);
+ cp_nid_t nid = cp_sta_own_data_get_nid (&ctx.cp);
+ cp_net_t *net = cp_sta_mgr_add_avln (&ctx.cp, snid, nid);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+ cp_sta_own_data_set_cco_status (&ctx.cp, true);
+ net->num_associated_stas = 0;
+ scenario_run (t, entries_ucco, &globals);
+
+ scenario_entry_t entries_cco[] = {
+ SCENARIO_ACTION (drv__drv_sta_status_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_drv_sta_status_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_DRV_RESULT_SUCCESS,
+ .status = CP_MSG_DRV_STA_STATUS_STATUS_AUTH,
+ .cco = CP_MSG_DRV_STA_STATUS_CCO_CCO,
+ .preferred_cco = false,
+ .backup_cco = false,
+ .simple_connect = false,
+ .pwl_sync_frequency = BSU_ACLF_FREQ_50HZ),
+ SCENARIO_END
+ };
+ /* Set our AVLN. */
+ net->num_associated_stas = 1;
+ scenario_run (t, entries_cco, &globals);
+ }
+ test_end;
+}
+
+static void
+drv_mcast_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_mme_peer_t peer = CP_MME_PEER (0xaabbccddeeffull, MAC_TEI_FOREIGN);
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ igmp_groups_t igmp_groups;
+
+ test_case_begin (t, "igmp");
+ test_begin (t, "set")
+ {
+ int nb_groups;
+ mac_t groups[MCAST_GROUP_MAX_NB];
+ int nb_members[MCAST_GROUP_MAX_NB];
+ mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+
+ nb_groups = 2;
+ groups[0] = 0xAAAAB15E0001ull;
+ groups[1] = 0xAAAAB25E0001ull;
+ nb_members[0] = 1;
+ nb_members[1] = 1;
+ members[0][0] = 0x112233445566ull;
+ members[1][0] = 0x112233445576ull;
+
+ /* Set multicast set list. */
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__drv_mcast_set_list_req, .peer = peer),
+ SCENARIO_EVENT (cl_get_igmp_groups,
+ .groups = &igmp_groups),
+ SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
+ .ok = true,
+ .nb_groups = nb_groups,
+ .groups = groups,
+ .nb_members = nb_members,
+ .members = (mac_t*)members),
+ SCENARIO_EVENT (cl_mactotei_new),
+ SCENARIO_EVENT (cl_mactotei_copy_except_tei),
+ SCENARIO_EVENT (cl_mactotei_addr_add, .mac = groups[0],
+ .tag = 0),
+ SCENARIO_EVENT (cl_mactotei_addr_add, .mac = groups[1],
+ .tag = 1),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_EVENT (cl_update_igmp_groups),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_MCAST_SET_LIST_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ }
+ test_end;
+
+ test_begin (t, "set with no list")
+ {
+ int nb_groups;
+ mac_t groups[MCAST_GROUP_MAX_NB];
+ int nb_members[MCAST_GROUP_MAX_NB];
+ mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+
+ nb_groups = 0;
+
+ /* Set multicast set list. */
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__drv_mcast_set_list_req, .peer = peer),
+ SCENARIO_EVENT (cl_get_igmp_groups,
+ .groups = &igmp_groups),
+ SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
+ .ok = true, .nb_groups = nb_groups,
+ .groups = groups, .nb_members = nb_members,
+ .members = (mac_t*)members),
+ SCENARIO_EVENT (cl_mactotei_new),
+ SCENARIO_EVENT (cl_mactotei_copy_except_tei),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_EVENT (cl_update_igmp_groups),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_MCAST_SET_LIST_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ }
+ test_end;
+
+ test_begin (t, "ko")
+ {
+ mac_t groups[MCAST_GROUP_MAX_NB];
+ int nb_groups = MCAST_GROUP_MAX_NB + 1;
+ int nb_members[MCAST_GROUP_MAX_NB];
+ mac_t members[MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB];
+
+ /* Set multicast set list. */
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (drv__drv_mcast_set_list_req, .peer = peer),
+ SCENARIO_EVENT (cl_get_igmp_groups,
+ .groups = &igmp_groups),
+ SCENARIO_EVENT (cp_msg_drv_mcast_set_list_req_receive,
+ .ok = false, .nb_groups = nb_groups,
+ .groups = groups, .nb_members = nb_members,
+ .members = (mac_t*)members),
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send,
+ .peer = peer,
+ .mmtype = DRV_MCAST_SET_LIST_CNF,
+ .result = CP_MSG_DRV_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ /* Set our AVLN. */
+ scenario_run (t, entries, &globals);
+ }
+ test_end;
+}
+
+void
+drv_test_suite (test_t t)
+{
+ test_suite_begin (t, "drv");
+ drv_basic_test_case (t);
+ drv_get_key_test_case (t);
+ drv_get_sta_status_test_case (t);
+ drv_mcast_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/fsm_stub.c b/cesar/cp/av/sta/action/test/utest/src/fsm_stub.c
new file mode 100644
index 0000000000..7b2085458b
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/fsm_stub.c
@@ -0,0 +1,58 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/fsm_stub.c
+ * \brief FSM stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "cp/fsm/fsm.h"
+
+#include "lib/scenario/scenario.h"
+
+cp_fsm_event_t *
+cp_fsm_event_bare_new (cp_t *ctx, cp_fsm_event_type_t type)
+{
+ dbg_assert (ctx);
+ switch (type)
+ {
+ case CP_FSM_EVENT_TYPE_cco__snid_conflict:
+ case CP_FSM_EVENT_TYPE_net_list_empty:
+ case CP_FSM_EVENT_TYPE_ustt_timeout:
+ case CP_FSM_EVENT_TYPE_btt_timeout:
+ case CP_FSM_EVENT_TYPE_join_timeout:
+ case CP_FSM_EVENT_TYPE_assoc_timeout:
+ case CP_FSM_EVENT_TYPE_renew:
+ case CP_FSM_EVENT_TYPE_sta_status_changed:
+ /* Ignore. */
+ return INVALID_PTR;
+ default:
+ ;
+ }
+ scenario_event (cp_fsm_event_bare_new, param);
+ test_fail_unless (type == param->type);
+ return INVALID_PTR;
+}
+
+cp_fsm_event_t *
+cp_fsm_event_mme_new (cp_t *ctx, cp_fsm_event_type_t type, cp_mme_rx_t *mme)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_fsm_event_mme_new, param);
+ test_fail_unless (type == param->type);
+ return INVALID_PTR;
+}
+
+void
+cp_fsm_branch_ (cp_t *ctx, cp_fsm_branch_t branch)
+{
+ dbg_assert (ctx);
+ scenario_event (cp_fsm_branch, param);
+ test_fail_unless (branch == param->branch);
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/handover.c b/cesar/cp/av/sta/action/test/utest/src/handover.c
new file mode 100644
index 0000000000..b3130b587e
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/handover.c
@@ -0,0 +1,289 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/handover.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_sta_action.h"
+
+#include "cp/sta/action/action.h"
+
+void
+handover_test_case__handover (test_t t)
+{
+ cp_sta_own_data_t *own;
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ test_case_begin (t, "Handover req");
+ scenario_entry_t handover_entries[] = {
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_SOFT,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_USER_APPOINT),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_REJECT_SOFT_HANDOVER),
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_SOFT,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_CCO_SELECTION),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_REJECT_SOFT_HANDOVER),
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_SOFT,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_CCO_LEAVING),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_REJECT_SOFT_HANDOVER),
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_HARD,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_USER_APPOINT),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result = CP_MSG_CC_HANDOVER_CNF_RESULT_ACCEPT),
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_HARD,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_CCO_SELECTION),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (STA_HANDOVER_IDLE, STA_HANDOVER_START, hard)),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_HANDOVER_TIMEOUT),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_TIMEOUT_MS - 1,
+ .delay_max_ms = CP_TIMEOUT_MS + 1
+ ),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_ACCEPT),
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_HARD,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_CCO_LEAVING),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (STA_HANDOVER_IDLE,
+ STA_HANDOVER_START, hard)),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_HANDOVER_TIMEOUT),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_TIMEOUT_MS - 1,
+ .delay_max_ms = CP_TIMEOUT_MS + 1
+ ),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_ACCEPT),
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = false,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_HARD,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_CCO_LEAVING),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_REJECT_ANY_HANDOVER),
+ SCENARIO_END
+ };
+
+ scenario_entry_t handover_entries2[] = {
+ SCENARIO_ACTION (handover__start, .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_msg_cc_handover_req_receive,
+ .ok = true,
+ .soft_hard = CP_MSG_CC_HANDOVER_REQ_HANDOVER_HARD,
+ .reason = CP_MSG_CC_HANDOVER_REQ_REASON_USER_APPOINT),
+ SCENARIO_EVENT (cp_msg_cc_handover_cnf_send,
+ .peer = CP_MME_PEER (1 ,1),
+ .result =
+ CP_MSG_CC_HANDOVER_CNF_RESULT_ACCEPT),
+ SCENARIO_END
+ };
+
+ test_begin (t, "STA")
+ {
+ scenario_run (t, handover_entries, &globals);
+
+ own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ own->cco_prefered = false;
+ scenario_run (t, handover_entries2, &globals);
+
+ test_fail_unless (own->cco_prefered == true);
+ }
+ test_end;
+
+}
+
+void
+handover_test_case__handover_info_recv (test_t t)
+{
+ cp_net_t *net;
+ cp_sta_t *sta;
+
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ test_case_begin (t, "Test handover info recv");
+
+ net = cp_sta_mgr_add_avln (&ctx.cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&ctx.cp, net);
+
+ scenario_entry_t info_recv_entries[] = {
+ SCENARIO_ACTION (handover__handover_info_ind_receive, .peer =
+ CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_ind_receive_begin,
+ .ok = true,
+ .rsc = CP_MSG_CC_HANDOVER_INFO_IND_RSC_HOIP,
+ .bcco = MAC_TEI_UNASSOCIATED,
+ .num_sta = 0),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_rsp_send,
+ .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_ACTION (handover__handover_info_ind_receive, .peer =
+ CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_ind_receive_begin,
+ .ok = true,
+ .rsc = CP_MSG_CC_HANDOVER_INFO_IND_RSC_UPDATE_BCCO,
+ .bcco = MAC_TEI_UNASSOCIATED,
+ .num_sta = 0),
+ SCENARIO_ACTION (handover__handover_info_ind_receive, .peer =
+ CP_MME_PEER (1, 1)),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_ind_receive_begin,
+ .ok = true,
+ .rsc = CP_MSG_CC_HANDOVER_INFO_IND_RSC_HOIP,
+ .bcco = MAC_TEI_UNASSOCIATED,
+ .num_sta = 1),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_ind_receive,
+ .ok = true,
+ .tei = 2,
+ .mac_addr = 2,
+ .status = true,
+ .ptei = MAC_TEI_UNASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_handover_info_rsp_send,
+ .peer = CP_MME_PEER (1, 1)),
+ SCENARIO_END
+ };
+
+ test_begin (t, "Network status")
+ {
+ ctx.cp.handover.reason = 0;
+ ctx.cp.handover.soft_hard = 0;
+ scenario_run (t, info_recv_entries, &globals);
+ test_fail_unless (cp_net_get_num_stas (&ctx.cp, net) == 1);
+ sta = cp_sta_mgr_sta_get_assoc (&ctx.cp, net, 2);
+ test_fail_unless (sta != NULL);
+ test_fail_unless (cp_sta_get_tei (sta) == 2);
+ test_fail_unless (cp_sta_get_mac_address (sta) == 2);
+ test_fail_unless (cp_sta_get_authenticated (&ctx.cp, sta) == true);
+ test_fail_unless (sta->pco == MAC_TEI_UNASSOCIATED);
+
+ slab_release (sta);
+ }
+ test_end;
+
+ cp_sta_mgr_uninit (&ctx.cp);
+}
+
+
+void
+handover_test_case__handover_expires (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ test_case_begin (t, "Test handover ended");
+
+ scenario_entry_t expires[] = {
+ SCENARIO_ACTION (handover__handover_ended),
+ SCENARIO_EVENT (cp_av_cco_action_cco__assoc_start),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_HANDOVER_SUCCESS),
+ SCENARIO_END
+ };
+
+ test_begin (t, "Expires")
+ {
+ cp_sta_t *sta;
+ cp_net_t *net;
+ ctx.cp.handover.reason = 0;
+ test_sta_action_create_our_net (&ctx, 1, 1);
+ net = cp_sta_mgr_get_our_avln (&ctx.cp);
+ sta = cp_sta_mgr_sta_add (&ctx.cp, net, 2, 2);
+ cp_net_set_cco (&ctx.cp, net, 2);
+
+ scenario_run (t, expires, &globals);
+
+ test_fail_unless (cp_net_get_cco (&ctx.cp, net) == NULL);
+ test_fail_unless (cp_sta_get_cco_status (sta) == false);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove_from_mac (&ctx.cp, 2);
+ }
+ test_end;
+}
+
+void
+handover_test_cases (test_t t)
+{
+ handover_test_case__handover (t);
+ handover_test_case__handover_info_recv (t);
+ handover_test_case__handover_expires (t);
+}
+
+void
+handover_test_suite (test_t t)
+{
+ test_suite_begin (t, "handover");
+ handover_test_cases (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/info.c b/cesar/cp/av/sta/action/test/utest/src/info.c
new file mode 100644
index 0000000000..e90d4d45cd
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/info.c
@@ -0,0 +1,675 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/info.c
+ * \brief Test sta/action/info.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_sta_action.h"
+
+#include "lib/slab.h"
+
+struct info_set_tei_map_check_t
+{
+ cp_tei_t tei;
+ mac_t mac;
+ bool authenticated;
+};
+typedef struct info_set_tei_map_check_t info_set_tei_map_check_t;
+#define INFO_SET_TEI_MAP_CHECK_END { 0xff, 0, false }
+
+static void
+info_set_tei_map_check (test_t t, cp_t *cp, info_set_tei_map_check_t *check)
+{
+ test_within (t);
+ cp_tei_t tei;
+ info_set_tei_map_check_t *p;
+ cp_net_t *our_net;
+ our_net = cp_sta_mgr_get_our_avln (cp);
+ for (tei = 1, p = check; tei < 0xff; tei++)
+ {
+ cp_sta_t *sta = cp_sta_mgr_sta_get_assoc (cp, our_net, tei);
+ if (tei == p->tei)
+ {
+ test_fail_unless (sta, "station %d: should exist", tei);
+ cp_tei_t sta_tei = cp_sta_get_tei (sta);
+ mac_t sta_mac = cp_sta_get_mac_address (sta);
+ bool sta_authenticated =
+ cp_sta_get_authenticated (cp, sta);
+ slab_release (sta);
+ test_fail_unless (sta_tei == p->tei);
+ test_fail_unless (sta_mac == p->mac,
+ "station %d: bad mac", tei);
+ test_fail_unless (sta_authenticated == p->authenticated,
+ "station %d: bad authenticated status", tei);
+ p++;
+ }
+ else
+ {
+ bool sta_present = !!sta;
+ if (sta)
+ slab_release (sta);
+ test_fail_unless (!sta_present, "station %d: should not exist",
+ tei);
+ }
+ }
+}
+
+static void
+info_set_tei_map_test_cases (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ test_sta_action_create_our_net (&ctx, 0x123456ull, 12);
+ cp_tei_t our_tei = 0xfd;
+ cp_sta_own_data_set_tei (&ctx.cp, our_tei);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_mme_peer_t peer = CP_MME_PEER (0xaabbccddeeffull, 1);
+ test_case_begin (t, "set_tei_map");
+ test_begin (t, "add first")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_ADD,
+ .sta_nb = 1),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 1, .mac = 0x111111111111ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 1, 0x111111111111ull, true },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "add second and third")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_ADD,
+ .sta_nb = 2),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 3, .mac = 0x333333333333ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 2, .mac = 0x222222222222ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 1, 0x111111111111ull, true },
+ { 2, 0x222222222222ull, false },
+ { 3, 0x333333333333ull, true },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "delete")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_DELETE,
+ .sta_nb = 1),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 1, .mac = 0x111111111111ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_DISASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0x222222222222ull, false },
+ { 3, 0x333333333333ull, true },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "update")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 2),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 4, .mac = 0x444444444444ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 2, .mac = 0xbbbbbbbbbbbbull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0xbbbbbbbbbbbbull, true },
+ { 4, 0x444444444444ull, false },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "update add specials")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 8),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 4, .mac = 0x444444444444ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 2, .mac = 0xbbbbbbbbbbbbull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 0x01, .mac = 0x010101010101ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 0x1f, .mac = 0x1f1f1f1f1f1full, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 0x20, .mac = 0x202020202020ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 0xdf, .mac = 0xdfdfdfdfdfdfull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 0xe0, .mac = 0xe0e0e0e0e0e0ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 0xfe, .mac = 0xfefefefefefeull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 0x01, 0x010101010101ull, true },
+ { 2, 0xbbbbbbbbbbbbull, false },
+ { 4, 0x444444444444ull, true },
+ { 0x1f, 0x1f1f1f1f1f1full, false },
+ { 0x20, 0x202020202020ull, true },
+ { 0xdf, 0xdfdfdfdfdfdfull, false },
+ { 0xe0, 0xe0e0e0e0e0e0ull, true },
+ { 0xfe, 0xfefefefefefeull, false },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "update remove specials")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 2),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 4, .mac = 0x444444444444ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 2, .mac = 0xbbbbbbbbbbbbull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0xbbbbbbbbbbbbull, true },
+ { 4, 0x444444444444ull, false },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "update with our tei")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 3),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 4, .mac = 0x444444444444ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 2, .mac = 0xbbbbbbbbbbbbull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = our_tei, .mac = 0xccccccccccccull,
+ .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_end,
+ .ok = true),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0xbbbbbbbbbbbbull, true },
+ { 4, 0x444444444444ull, false },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_case_begin (t, "set_tei_map errors");
+ test_begin (t, "initial error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = false,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 2),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0xbbbbbbbbbbbbull, true },
+ { 4, 0x444444444444ull, false },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "add error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 2),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 5, .mac = 0x555555555555ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_ASSOCIATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = false,
+ .tei = 6, .mac = 0x666666666666ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0xbbbbbbbbbbbbull, true },
+ { 4, 0x444444444444ull, false },
+ { 5, 0x555555555555ull, false },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_begin (t, "update error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_set_tei_map_ind, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_begin,
+ .ok = true,
+ .mode = CP_MSG_CC_SET_TEI_MAP_IND_MODE_UPDATE,
+ .sta_nb = 2),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = true,
+ .tei = 5, .mac = 0x555555555555ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cp_msg_cc_set_tei_map_ind_receive_sta,
+ .ok = false,
+ .tei = 6, .mac = 0x666666666666ull, .status =
+ CP_MSG_CC_SET_TEI_MAP_IND_STATUS_AUTHENTICATED),
+ SCENARIO_EVENT (cl_mactotei_use_table),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_set_tei_map_check_t stmc[] = {
+ { 2, 0xbbbbbbbbbbbbull, true },
+ { 4, 0x444444444444ull, false },
+ { 5, 0x555555555555ull, true },
+ INFO_SET_TEI_MAP_CHECK_END
+ };
+ info_set_tei_map_check (t, &ctx.cp, stmc);
+ } test_end;
+ test_sta_action_uninit (&ctx);
+}
+
+struct info_unassociated_sta_check_t
+{
+ mac_t mac;
+ cp_nid_t nid;
+ u8 cco_cap;
+ bool present;
+};
+typedef struct info_unassociated_sta_check_t info_unassociated_sta_check_t;
+#define INFO_UNASSOCIATED_STA_CHECK_END { MAC_ZERO, 0, 0, false }
+
+static void
+info_unassociated_sta_check (test_t t, cp_t *cp,
+ info_unassociated_sta_check_t *check)
+{
+ test_within (t);
+ info_unassociated_sta_check_t *p;
+ for (p = check; p->mac; p++)
+ {
+ cp_net_t *net = cp_sta_mgr_get_avln (cp, 0, p->nid);
+ test_fail_unless (net || !p->present, "missing net 0x%llx", p->nid);
+ if (net)
+ {
+ cp_sta_t *sta = cp_sta_mgr_sta_get_from_mac (cp, p->mac);
+ bool present = !!sta;
+ u8 cco_cap = sta ? sta->cco_cap : 0xff;
+ if (sta)
+ slab_release (sta);
+ test_fail_unless (present == p->present);
+ test_fail_unless (cco_cap == p->cco_cap || !p->present);
+ }
+ }
+}
+
+static void
+info_unassociated_sta_test_cases (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ test_case_begin (t, "unassociated_sta");
+ test_begin (t, "add one")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x111111111111ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf11111111111ull, .cco_cap = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_unassociated_sta_check_t usc[] = {
+ { 0x111111111111ull, 0xf11111111111ull, 0, true },
+ INFO_UNASSOCIATED_STA_CHECK_END
+ };
+ info_unassociated_sta_check (t, &ctx.cp, usc);
+ } test_end;
+ test_begin (t, "add more")
+ {
+ scenario_entry_t entries[] = {
+ /* More STA. */
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x222222222222ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf22222222222ull, .cco_cap = 1),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x333333333333ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf33333333333ull, .cco_cap = 2),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x444444444444ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf44444444444ull, .cco_cap = 0),
+ /* More STA with the same NID. */
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0xaaaaaaaaaaaaull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf11111111111ull, .cco_cap = 1),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0xbbbbbbbbbbbbull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf22222222222ull, .cco_cap = 2),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_unassociated_sta_check_t usc[] = {
+ { 0x111111111111ull, 0xf11111111111ull, 0, true },
+ { 0x222222222222ull, 0xf22222222222ull, 1, true },
+ { 0x333333333333ull, 0xf33333333333ull, 2, true },
+ { 0x444444444444ull, 0xf44444444444ull, 0, true },
+ { 0xaaaaaaaaaaaaull, 0xf11111111111ull, 1, true },
+ { 0xbbbbbbbbbbbbull, 0xf22222222222ull, 2, true },
+ INFO_UNASSOCIATED_STA_CHECK_END
+ };
+ info_unassociated_sta_check (t, &ctx.cp, usc);
+ } test_end;
+ test_begin (t, "updates")
+ {
+ scenario_entry_t entries[] = {
+ /* Change of cco_cap. */
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x111111111111ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf11111111111ull, .cco_cap = 2),
+ /* Update, no change. */
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x222222222222ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf22222222222ull, .cco_cap = 1),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_unassociated_sta_check_t usc[] = {
+ { 0x111111111111ull, 0xf11111111111ull, 2, true },
+ { 0x222222222222ull, 0xf22222222222ull, 1, true },
+ { 0x333333333333ull, 0xf33333333333ull, 2, true },
+ { 0x444444444444ull, 0xf44444444444ull, 0, true },
+ { 0xaaaaaaaaaaaaull, 0xf11111111111ull, 1, true },
+ { 0xbbbbbbbbbbbbull, 0xf22222222222ull, 2, true },
+ INFO_UNASSOCIATED_STA_CHECK_END
+ };
+ info_unassociated_sta_check (t, &ctx.cp, usc);
+ } test_end;
+ /* TODO: NID change? */
+ test_case_begin (t, "unassociated_sta errors");
+ test_begin (t, "mme error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = false,
+ .nid = 0xf88888888888ull, .cco_cap = 2),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_unassociated_sta_check_t usc[] = {
+ { 0x111111111111ull, 0xf11111111111ull, 2, true },
+ { 0x222222222222ull, 0xf22222222222ull, 1, true },
+ { 0x333333333333ull, 0xf33333333333ull, 2, true },
+ { 0x444444444444ull, 0xf44444444444ull, 0, true },
+ { 0xaaaaaaaaaaaaull, 0xf11111111111ull, 1, true },
+ { 0xbbbbbbbbbbbbull, 0xf22222222222ull, 2, true },
+ { 0x888888888888ull, 0xf88888888888ull, 0, false },
+ INFO_UNASSOCIATED_STA_CHECK_END
+ };
+ info_unassociated_sta_check (t, &ctx.cp, usc);
+ } test_end;
+ test_begin (t, "no room error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x555555555555ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf55555555555ull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x666666666666ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf66666666666ull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x777777777777ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf77777777777ull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf88888888888ull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xfaaaaaaaaaaaull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xfbbbbbbbbbbbull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xfcccccccccccull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xfdccccccccccull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xfeccccccccccull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xfdddddddddddull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xffffffffffffull, .cco_cap = 0),
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x888888888888ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf00000000000ull, .cco_cap = 0),
+ /* No more room. */
+ SCENARIO_ACTION (process_cm_unassociated_sta_ind,
+ .peer = CP_MME_PEER (0x999999999999ull,
+ MAC_TEI_UNASSOCIATED)),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_receive,
+ .ok = true,
+ .nid = 0xf99999999999ull, .cco_cap = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ info_unassociated_sta_check_t usc[] = {
+ { 0x111111111111ull, 0xf11111111111ull, 2, true },
+ { 0x222222222222ull, 0xf22222222222ull, 1, true },
+ { 0x333333333333ull, 0xf33333333333ull, 2, true },
+ { 0x444444444444ull, 0xf44444444444ull, 0, true },
+ { 0xaaaaaaaaaaaaull, 0xf11111111111ull, 1, true },
+ { 0xbbbbbbbbbbbbull, 0xf22222222222ull, 2, true },
+ { 0x555555555555ull, 0xf55555555555ull, 0, true },
+ { 0x666666666666ull, 0xf66666666666ull, 0, true },
+ { 0x777777777777ull, 0xf77777777777ull, 0, true },
+ { 0x888888888888ull, 0xf88888888888ull, 0, true },
+ { 0x888888888888ull, 0xfaaaaaaaaaaaull, 0, true },
+ { 0x888888888888ull, 0xfbbbbbbbbbbbull, 0, true },
+ { 0x888888888888ull, 0xfcccccccccccull, 0, true },
+ { 0x888888888888ull, 0xfdccccccccccull, 0, true },
+ { 0x888888888888ull, 0xfeccccccccccull, 0, true },
+ { 0x888888888888ull, 0xffffffffffffull, 0, true },
+ { 0x999999999999ull, 0xf99999999999ull, 0, false },
+ INFO_UNASSOCIATED_STA_CHECK_END
+ };
+ info_unassociated_sta_check (t, &ctx.cp, usc);
+ } test_end;
+ test_sta_action_uninit (&ctx);
+}
+
+void
+info_test_suite (test_t t)
+{
+ test_suite_begin (t, "info");
+ info_set_tei_map_test_cases (t);
+ info_unassociated_sta_test_cases (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/key.c b/cesar/cp/av/sta/action/test/utest/src/key.c
new file mode 100644
index 0000000000..a8bc533007
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/key.c
@@ -0,0 +1,80 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/key.c
+ * \brief Test sta/action/key.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_sta_action.h"
+
+void
+key_basic_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445566ull, 1);
+ test_case_begin (t, "basic");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_set_key_req, .peer = peer, .pid = 1),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_SET_KEY_REQ_PID1),
+ SCENARIO_ACTION (process_cm_set_key_cnf, .peer = peer, .pid = 1),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_SET_KEY_CNF_PID1),
+ SCENARIO_ACTION (process_cm_get_key_req, .peer = peer, .pid = 0),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_GET_KEY_REQ_PID0),
+ SCENARIO_ACTION (process_cm_get_key_cnf, .peer = peer, .pid = 0),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_GET_KEY_CNF_PID0),
+ SCENARIO_ACTION (process_cm_set_key_req, .peer = peer, .pid = 3),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_SET_KEY_REQ_PID3),
+ SCENARIO_ACTION (process_cm_set_key_cnf, .peer = peer, .pid = 3),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_SET_KEY_CNF_PID3),
+ SCENARIO_ACTION (process_cm_get_key_req, .peer = peer, .pid = 1),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_GET_KEY_REQ_PID1),
+ SCENARIO_ACTION (process_cm_get_key_cnf, .peer = peer, .pid = 1),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_GET_KEY_CNF_PID1),
+ SCENARIO_ACTION (process_cm_get_key_req, .peer = peer, .pid = 3),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_GET_KEY_REQ_PID3),
+ SCENARIO_ACTION (process_cm_get_key_cnf, .peer = peer, .pid = 3),
+ SCENARIO_EVENT (cp_fsm_event_mme_new, .type =
+ CP_FSM_EVENT_TYPE_CM_GET_KEY_CNF_PID3),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+key_test_suite (test_t t)
+{
+ test_suite_begin (t, "key");
+ key_basic_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/mac_sar_interface_stub.c b/cesar/cp/av/sta/action/test/utest/src/mac_sar_interface_stub.c
new file mode 100644
index 0000000000..7670aca0aa
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/mac_sar_interface_stub.c
@@ -0,0 +1,35 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/mac_sar_interface_stub.c
+ * \brief SAR interface stub functions.
+ * \ingroup cp_msg
+ *
+ * « long description »
+ */
+#include "common/std.h"
+
+#include "mac/sar/sar.h"
+#include "mac/sar/sar_pb_stats.h"
+
+static sar_pb_stats_entry_t fake;
+
+sar_pb_stats_entry_t*
+sar_read_pb_stats_entry (sar_t *ctx, uint index)
+{
+ int i;
+ fake.ntb_clock = 0;
+ fake.stei = 0;
+ fake.pb_nb = 0;
+ fake.fl_av = 0;
+
+ for (i=0; i<PB_STATS_BITMAP_SIZE; i++)
+ fake.pb_bitmap[i] = 0;
+
+ return &fake;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/misc.c b/cesar/cp/av/sta/action/test/utest/src/misc.c
new file mode 100644
index 0000000000..9f752f4db5
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/misc.c
@@ -0,0 +1,2074 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/misc.c
+ * \brief Test sta/action/misc.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_sta_action.h"
+
+#include "mac/common/ntb.h" /* for mac_ntb_init */
+
+#include "common/defs/spidcom.h"
+#include "mac/common/timings.h"
+#include "cp/sta/action/action.h"
+
+#include "build_info.h"
+
+void
+misc_whoru_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_t *cp = &ctx.cp;
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445566ull, 2);
+ const cp_nid_t nid = 0x111111111111ull;
+ const mac_t mac = 0x111111111111ull;
+ cp_sta_own_data_set_mac_address (cp, mac);
+ char *avln_hfid = "AVLN";
+ cp_sta_own_data_set_hfid_avln (cp, avln_hfid);
+ cp_sta_own_data_set_tei (cp, 1);
+ test_sta_action_create_our_net (&ctx, nid, 12);
+ test_case_begin (t, "whoru");
+ test_begin (t, "ok cco")
+ {
+ cp_sta_own_data_set_cco_status (cp, true);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_who_ru_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_receive, .ok = true,
+ .nid = nid),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_cnf_send, .peer = peer,
+ .nid = nid, .cco_mac = mac,
+ .avln_hfid = avln_hfid),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "nok mme")
+ {
+ cp_sta_own_data_set_cco_status (cp, true);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_who_ru_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_receive, .ok = false,
+ .nid = nid + 1),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "nok nid")
+ {
+ cp_sta_own_data_set_cco_status (cp, true);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_who_ru_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_receive, .ok = true,
+ .nid = nid + 1),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_cc_discover_list_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_t *cp = &ctx.cp;
+ const cp_nid_t nid = 0x111111111111ull;
+ const mac_t mac = 0x111111111111ull;
+ const cp_snid_t snid = 1;
+ const cp_tei_t tei = 1;
+
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_case_begin (t, "cc_discover_list");
+
+ test_begin (t, "receive ko")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_msg_cc_discover_list_ctx_t disc_ctx;
+
+ test_begin (t, "no station and no network")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_begin,
+ .nb_sta = 0, .nb_net = 0, .disc_ctx = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* no own network yet but one network and station discovered. */
+ cp_net_t *other_net = cp_sta_mgr_add_avln (cp, snid, nid);
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, other_net, tei, mac);
+
+ test_begin (t, "one station and one network")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_begin,
+ .nb_sta = 1, .nb_net = 1, .disc_ctx = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac,
+ .tei = tei,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net,
+ .nid = nid,
+ .snid = snid,
+ .access = 0,
+ .hm = other_net->hm,
+ .numslots = other_net->avln_num_slots,
+ .coordinated_status =
+ CC_DISCOVER_LIST_COORD_NON_COORDINATED,
+ .offset = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Our network is created. */
+ test_sta_action_create_our_net (&ctx, nid + 1, snid + 1);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+ cp_sta_own_data_set_mac_address (cp, mac + 1);
+ cp_sta_own_data_set_tei (cp, tei);
+
+ test_begin (t, "one station and one network")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_begin,
+ .nb_sta = 1, .nb_net = 1, .disc_ctx = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac,
+ .tei = tei,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net,
+ .nid = nid,
+ .snid = snid,
+ .access = 0,
+ .hm = other_net->hm,
+ .numslots = other_net->avln_num_slots,
+ .coordinated_status =
+ CC_DISCOVER_LIST_COORD_NON_COORDINATED,
+ .offset = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /** One station is created in our network with no interval and
+ * default tmi = 0. */
+ cp_sta_t *sta_2 = cp_sta_mgr_sta_add (cp, my_net, tei + 2, mac + 2);
+ other_net->network_mode = MAC_NM_COORDINATED;
+ other_net->avln_slot_id = 2;
+ my_net->avln_slot_id = 1;
+ sta_t *sta2 = mac_store_sta_get (cp->mac_store, tei+2);
+ sta2->tx_tonemaps->intervals->intervals_nb = 0;
+ sta2->tx_tonemaps->default_tmi = PHY_MOD_ROBO;
+ cp->mac_config->tonemask_info.tonemap_robo[PHY_MOD_ROBO].ble = 0x12;
+
+ /** One station is created in our network with tei = 0. */
+ cp_sta_t *sta_5 = cp_sta_mgr_sta_add (cp, my_net, 0, mac + 5);
+
+ test_begin (t, "3 stations and one network")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_begin,
+ .nb_sta = 3, .nb_net = 1, .disc_ctx = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac,
+ .tei = tei,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+5,
+ .tei = 0,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+2,
+ .tei = tei + 2,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0x12),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net,
+ .nid = nid,
+ .snid = snid,
+ .access = 0,
+ .hm = other_net->hm,
+ .numslots = other_net->avln_num_slots,
+ .coordinated_status =
+ CC_DISCOVER_LIST_COORD_COORDINATED_GROUP_UNKNOWN,
+ .offset = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /** A new station is created in our network with no interval and
+ * negociated default tmi. */
+ cp_sta_t *sta_3 = cp_sta_mgr_sta_add (cp, my_net, tei + 3, mac + 3);
+
+ sta_t *sta3 = mac_store_sta_get (cp->mac_store, tei+3);
+ sta3->tx_tonemaps->intervals->intervals_nb = 0;
+ sta3->tx_tonemaps->default_tmi = TONEMAP_INDEX_NEGOTIATED_FIRST;
+ sta3->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST] = tonemap_alloc ();
+ sta3->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST]->ble = 0x23;
+
+ /** A new station is created in our network with 6 intervals . */
+ cp_sta_t *sta_4 = cp_sta_mgr_sta_add (cp, my_net, tei + 4, mac + 4);
+
+ sta_t *sta4 = mac_store_sta_get (cp->mac_store, tei+4);
+ sta4->tx_tonemaps->intervals->intervals_nb = 6;
+ sta4->tx_tonemaps->default_tmi = TONEMAP_INDEX_NEGOTIATED_FIRST;
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST] = tonemap_alloc ();
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST]->ble = 0xFF;
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 1] = tonemap_alloc ();
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 1]->ble = 0x00;
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 2] = tonemap_alloc ();
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 2]->ble = 0x08;
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 3] = tonemap_alloc ();
+ sta4->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 3]->ble = 0x0F;
+ /* The 3rd and 6th intervals have no tonemap. */
+
+ sta4->tx_tonemaps->intervals->interval[0].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST;
+ sta4->tx_tonemaps->intervals->interval[0].end_offset_atu = 10;
+ sta4->tx_tonemaps->intervals->interval[1].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 1;
+ sta4->tx_tonemaps->intervals->interval[1].end_offset_atu = 100;
+ sta4->tx_tonemaps->intervals->interval[2].tmi = 0xFF;
+ sta4->tx_tonemaps->intervals->interval[2].end_offset_atu = 500;
+ sta4->tx_tonemaps->intervals->interval[3].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 2;
+ sta4->tx_tonemaps->intervals->interval[3].end_offset_atu = 800;
+ sta4->tx_tonemaps->intervals->interval[4].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 3;
+ sta4->tx_tonemaps->intervals->interval[4].end_offset_atu = 900;
+ sta4->tx_tonemaps->intervals->interval[5].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 4;
+ sta4->tx_tonemaps->intervals->interval[5].end_offset_atu = 950;
+
+ test_begin (t, "5 stations and one network")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_begin,
+ .nb_sta = 5, .nb_net = 1, .disc_ctx = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac,
+ .tei = tei,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+5,
+ .tei = 0,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+2,
+ .tei = tei+2,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0x12),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+3,
+ .tei = tei+3,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0x23),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+4,
+ .tei = tei+4,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0x05),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net,
+ .nid = nid,
+ .snid = snid,
+ .access = 0,
+ .hm = other_net->hm,
+ .numslots = other_net->avln_num_slots,
+ .coordinated_status =
+ CC_DISCOVER_LIST_COORD_COORDINATED_GROUP_UNKNOWN,
+ .offset = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Remove the tonemaps. */
+ tonemap_release_list_t tm_release_list;
+ tonemap_release_list_init (&tm_release_list);
+ tonemap_release (sta3->tx_tonemaps, TONEMAP_INDEX_NEGOTIATED_FIRST, &tm_release_list);
+ tonemap_release (sta4->tx_tonemaps, TONEMAP_INDEX_NEGOTIATED_FIRST, &tm_release_list);
+ tonemap_release (sta4->tx_tonemaps, TONEMAP_INDEX_NEGOTIATED_FIRST+1, &tm_release_list);
+ tonemap_release (sta4->tx_tonemaps, TONEMAP_INDEX_NEGOTIATED_FIRST+2, &tm_release_list);
+ tonemap_release (sta4->tx_tonemaps, TONEMAP_INDEX_NEGOTIATED_FIRST+3, &tm_release_list);
+ while (!tonemap_release_list_clean (&tm_release_list))
+ ;
+
+ test_begin (t, "Invalid tonemaps")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_begin,
+ .nb_sta = 5, .nb_net = 1, .disc_ctx = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac,
+ .tei = tei,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+5,
+ .tei = 0,
+ .same_network =
+ CC_DISCOVER_LIST_NET_DIFFERENT_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+2,
+ .tei = tei+2,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0x12),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+3,
+ .tei = tei+3,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_station,
+ .mac_addr = mac+4,
+ .tei = tei+4,
+ .same_network = CC_DISCOVER_LIST_NET_SAME_NETWORK,
+ .snid = snid+1,
+ .access = 0,
+ .cco_cap = 0,
+ .proxy_cap = 0,
+ .backup_cco_cap = 0,
+ .cco_status = 0,
+ .pco_status = 0,
+ .backup_cco_status = 0,
+ .signal_level = 0,
+ .average_ble = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net_begin,
+ .disc_ctxc = &disc_ctx),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_net,
+ .nid = nid,
+ .snid = snid,
+ .access = 0,
+ .hm = other_net->hm,
+ .numslots = other_net->avln_num_slots,
+ .coordinated_status =
+ CC_DISCOVER_LIST_COORD_COORDINATED_GROUP_UNKNOWN,
+ .offset = 0),
+ SCENARIO_EVENT (cp_msg_cc_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Cleanup. */
+ blk_release (sta4);
+ blk_release (sta3);
+ blk_release (sta2);
+ slab_release (sta_1);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac);
+ slab_release (sta_2);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac + 2);
+ slab_release (sta_3);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac + 3);
+ slab_release (sta_4);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac + 4);
+ slab_release (sta_5);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac + 5);
+
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_relay_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_t *cp = &ctx.cp;
+ const cp_nid_t nid = 0x111111111111ull;
+ cp_sta_own_data_set_tei (cp, 2);
+ test_sta_action_create_our_net (&ctx, nid, 1);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (cp);
+ mac_t cco_mac = 0x111111111111ull;
+ cp_tei_t cco_tei = 1;
+ cp_sta_t *cco = cp_sta_mgr_sta_add (cp, our_net, cco_tei, cco_mac);
+ cp_net_set_cco (cp, our_net, cco_tei);
+ slab_release (cco);
+ cp_mme_peer_t unapeer = CP_MME_PEER (0x000000000001ull, 0);
+ cp_mme_peer_t apeer = CP_MME_PEER (0x333333333333ull, 3);
+ test_case_begin (t, "relay");
+ test_begin (t, "error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "encrypted payload")
+ {
+ scenario_entry_t entries[] = {
+ /* Unassociated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CM_ENCRYPTED_PAYLOAD_IND),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = MAC_TEI_BCAST,
+ .osa = unapeer.mac, .stei = unapeer.tei,
+ .length = 1234),
+ /* Associated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CM_ENCRYPTED_PAYLOAD_IND),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = MAC_TEI_BCAST,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ /* Authenticated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer,
+ .encrypt = true),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CM_ENCRYPTED_PAYLOAD_IND),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = MAC_TEI_BCAST,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "assoc.req")
+ {
+ scenario_entry_t entries[] = {
+ /* Unassociated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_ASSOC_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = unapeer.mac, .stei = unapeer.tei,
+ .length = 1234),
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = MAC_BROADCAST, .ftei = MAC_TEI_BCAST,
+ .length = 1234,
+ .mmtype = CC_ASSOC_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = unapeer.mac, .stei = unapeer.tei,
+ .length = 1234),
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = MAC_BROADCAST, .ftei = 1,
+ .length = 1234,
+ .mmtype = CC_ASSOC_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = MAC_BROADCAST, .ftei = 1,
+ .osa = unapeer.mac, .stei = unapeer.tei,
+ .length = 1234),
+ /* Associated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_ASSOC_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = MAC_BROADCAST, .ftei = MAC_TEI_BCAST,
+ .length = 1234,
+ .mmtype = CC_ASSOC_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = MAC_BROADCAST, .ftei = MAC_TEI_BCAST,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "unassociated ok")
+ {
+ scenario_entry_t entries[] = {
+ /* Unassociated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_WHO_RU_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = unapeer.mac, .stei = unapeer.tei,
+ .length = 1234),
+ /* Associated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_WHO_RU_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ /* Authenticated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer,
+ .encrypt = true),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_WHO_RU_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "associated ok")
+ {
+ scenario_entry_t entries[] = {
+ /* Unassociated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CM_SET_KEY_REQ),
+ /* Associated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CM_SET_KEY_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ /* Authenticated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer,
+ .encrypt = true),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CM_SET_KEY_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "authenticated ok")
+ {
+ scenario_entry_t entries[] = {
+ /* Unassociated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = unapeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_HANDOVER_REQ),
+ /* Associated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_HANDOVER_REQ),
+ /* Authenticated. */
+ SCENARIO_ACTION (process_cc_relay_req, .peer = apeer,
+ .encrypt = true),
+ SCENARIO_EVENT (cp_msg_cc_relay_req_receive, .ok = true,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .length = 1234,
+ .mmtype = CC_HANDOVER_REQ),
+ SCENARIO_EVENT (cp_msg_cc_relay_ind_send,
+ .mac_fa = cco_mac, .ftei = cco_tei,
+ .osa = apeer.mac, .stei = apeer.tei,
+ .length = 1234),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_hfid_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_av_sta_action_init (&ctx.cp);
+
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_t *cp = &ctx.cp;
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445566ull, 2);
+ cp_mme_peer_t drvpeer = CP_MME_PEER (0x112233445566ull, MAC_TEI_FOREIGN);
+ const cp_nid_t nid = 0x111111111111ull;
+ const mac_t mac = 0x111111111111ull;
+ cp_mme_peer_t hlepeer = CP_MME_PEER (mac, MAC_TEI_FOREIGN);
+ cp_sta_own_data_set_mac_address (cp, mac);
+ char *manufacturer_hfid = "MANUFACTURER";
+ cp_sta_own_data_set_hfid_manufacturer (cp, manufacturer_hfid);
+ char *user_hfid = "USER";
+ cp_sta_own_data_set_hfid_user (cp, user_hfid);
+ char *avln_hfid = "AVLN";
+ cp_sta_own_data_set_hfid_avln (cp, avln_hfid);
+ cp_sta_own_data_set_tei (cp, 1);
+ test_sta_action_create_our_net (&ctx, nid, 12);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+
+ test_case_begin (t, "hfid");
+
+ /* Check reply parameters at init. */
+ test_begin (t, "avln hfid reply parameters init")
+ {
+ test_fail_unless (cp->sta_action.cm_hfid_reply_peer.mac == 0);
+ } test_end;
+
+ /* Check get avln hfid when we are cco. */
+ cp_sta_own_data_set_cco_status (cp, true);
+
+ test_begin (t, "get avln hfid ok when cco")
+ {
+ scenario_entry_t entries[] = {
+ /* User HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid,
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_PROVIDE_NETWORK_HFID,
+ .hfid = avln_hfid,
+ ),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ /* Check HFID values. */
+ test_fail_unless (strcmp (own_data->hfid_avln, avln_hfid) == 0);
+ /* Check reply parameters in cp_sta_action context. */
+ test_fail_unless (cp->sta_action.cm_hfid_reply_peer.mac == 0);
+ } test_end;
+
+ cp_sta_own_data_set_cco_status (cp, false);
+
+ /** Configure the cco. */
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (cp);
+ mac_t cco_mac = 0x111111111112ull;
+ cp_tei_t cco_tei = 2;
+ cp_sta_t *cco = cp_sta_mgr_sta_add (cp, our_net, cco_tei, cco_mac);
+ cp_net_set_cco (cp, our_net, cco_tei);
+ cp_mme_peer_t cco_peer;
+ cp_mme_peer_t wrong_peer;
+
+ cco_peer.mac = cco_mac;
+ cco_peer.tei = cco_tei;
+ cco_peer.eth_type = HPAV_MTYPE_MME;
+ cco_peer.vlan_tci = 0;
+
+ wrong_peer.mac = cco_mac + 1;
+ wrong_peer.tei = cco_tei + 1;
+ wrong_peer.eth_type = HPAV_MTYPE_MME;
+ wrong_peer.vlan_tci = 0;
+
+ slab_release (cco);
+
+ test_begin (t, "get ok")
+ {
+ scenario_entry_t entries[] = {
+ /* Manufacturer HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_MANUFACTURER_SET_HFID,
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_PROVIDE_MANUFACTURER_SET_HFID,
+ .hfid = manufacturer_hfid,
+ ),
+ /* User HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_USER_SET_HFID,
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_PROVIDE_USER_SET_HFID,
+ .hfid = user_hfid,
+ ),
+ /* AVLN HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid,
+ ),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_send, .peer = cco_peer,
+ .nid = nid,),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_whoru_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_TIMEOUT_MS,
+ .delay_max_ms = CP_TIMEOUT_MS),
+ SCENARIO_ACTION (process_cc_who_ru_cnf, .peer = cco_peer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (
+ cp_msg_cc_who_ru_cnf_receive, .ok = true,
+ .nid = nid,
+ .cco_mac = cco_mac,
+ .avln_hfid = avln_hfid,
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_PROVIDE_NETWORK_HFID,
+ .hfid = avln_hfid,
+ ),
+ /* Get Who_ru.cnf from the wrong peer. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid,
+ ),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_send, .peer = cco_peer,
+ .nid = nid,),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_whoru_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_TIMEOUT_MS,
+ .delay_max_ms = CP_TIMEOUT_MS),
+ SCENARIO_ACTION (process_cc_who_ru_cnf, .peer = wrong_peer),
+ SCENARIO_ACTION (process_cc_who_ru_cnf, .peer = cco_peer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (
+ cp_msg_cc_who_ru_cnf_receive, .ok = true,
+ .nid = nid,
+ .cco_mac = cco_mac,
+ .avln_hfid = avln_hfid,
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_PROVIDE_NETWORK_HFID,
+ .hfid = avln_hfid,
+ ),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ /* Check HFID values. */
+ test_fail_unless (strcmp (own_data->hfid_avln, avln_hfid) == 0);
+ test_fail_unless (strcmp (own_data->hfid_user, user_hfid) == 0);
+ test_fail_unless (strcmp (own_data->hfid_manufacturer,
+ manufacturer_hfid) == 0);
+ /* Check reply parameters in cp_sta_action context. */
+ test_fail_unless (cp->sta_action.cm_hfid_reply_peer.mac == 0);
+ } test_end;
+ test_begin (t, "get error")
+ {
+ scenario_entry_t entries[] = {
+ /* Bad MME. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_hfid_req_receive, .ok = false),
+ /* Bad NID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid + 1,
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_FAILURE,
+ .hfid = "",
+ ),
+ /* WHO_RU timeout */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid,),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_send, .peer = cco_peer,
+ .nid = nid,),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_whoru_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_TIMEOUT_MS,
+ .delay_max_ms = CP_TIMEOUT_MS),
+ SCENARIO_ACTION (whoru_timeout_process),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_FAILURE,
+ .hfid = "",),
+ /* Avln request while previous one is still in progress. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid,),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_req_send, .peer = cco_peer,
+ .nid = nid,),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_whoru_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_TIMEOUT_MS,
+ .delay_max_ms = CP_TIMEOUT_MS),
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_PROVIDE_NETWORK_HFID,
+ .nid = nid + 1,),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_FAILURE,
+ .hfid = "",),
+ SCENARIO_ACTION (process_cc_who_ru_cnf, .peer = cco_peer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_msg_cc_who_ru_cnf_receive, .ok = true,
+ .nid = nid, .cco_mac = cco_mac,
+ .avln_hfid = avln_hfid,),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_PROVIDE_NETWORK_HFID,
+ .hfid = avln_hfid,),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ /* Check HFID values. */
+ test_fail_unless (strcmp (own_data->hfid_avln, avln_hfid) == 0);
+ test_fail_unless (strcmp (own_data->hfid_user, user_hfid) == 0);
+ test_fail_unless (strcmp (own_data->hfid_manufacturer,
+ manufacturer_hfid) == 0);
+ /* Check reply parameters in cp_sta_action context. */
+ test_fail_unless (cp->sta_action.cm_hfid_reply_peer.mac == 0);
+ } test_end;
+ cp_sta_own_data_set_cco_status (cp, true);
+ test_begin (t, "set ok")
+ {
+ scenario_entry_t entries[] = {
+ /* User HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = drvpeer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_SET_USER_SET_HFID,
+ .hfid = "new user",
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = drvpeer,
+ .restype = CM_HFID_CNF_RESTYPE_SET_USER_SET_HFID,
+ .hfid = "new user",
+ ),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_u_sta_hfid_ind_send,
+ .peer = hlepeer, .u_sta_hfid = "new user",),
+ /* AVLN HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = drvpeer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_SET_NETWORK_HFID,
+ .nid = nid,
+ .hfid = "new avln",
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = drvpeer,
+ .restype = CM_HFID_CNF_RESTYPE_SET_NETWORK_HFID,
+ .hfid = "new avln",
+ ),
+ SCENARIO_EVENT (cp_msg_drv_sta_set_avln_hfid_ind_send,
+ .peer = hlepeer, .avln_hfid = "new avln",),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ /* Check HFID values. */
+ test_fail_unless (strcmp (own_data->hfid_avln, "new avln") == 0);
+ test_fail_unless (strcmp (own_data->hfid_user, "new user") == 0);
+ test_fail_unless (strcmp (own_data->hfid_manufacturer,
+ manufacturer_hfid) == 0);
+ /* Restore HFID. */
+ cp_sta_own_data_set_hfid_user (cp, user_hfid);
+ cp_sta_own_data_set_hfid_avln (cp, avln_hfid);
+ } test_end;
+ test_begin (t, "set error")
+ {
+ scenario_entry_t entries[] = {
+ /* Forbidden for user HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_SET_USER_SET_HFID,
+ .hfid = "new user error",
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_FAILURE,
+ .hfid = user_hfid,
+ ),
+ /* Forbidden for AVLN HFID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = peer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_SET_NETWORK_HFID,
+ .nid = nid,
+ .hfid = "new avln error",
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = peer,
+ .restype = CM_HFID_CNF_RESTYPE_FAILURE,
+ .hfid = avln_hfid,
+ ),
+ /* Bad NID. */
+ SCENARIO_ACTION (process_cm_hfid_req, .peer = drvpeer),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_req_receive, .ok = true,
+ .req_type = CM_HFID_REQ_REQTYPE_SET_NETWORK_HFID,
+ .nid = nid + 1,
+ .hfid = "new avln error",
+ ),
+ SCENARIO_EVENT (
+ cp_msg_cm_hfid_cnf_send, .peer = drvpeer,
+ .restype = CM_HFID_CNF_RESTYPE_FAILURE,
+ .hfid = avln_hfid,
+ ),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ /* Check HFID values. */
+ test_fail_unless (strcmp (own_data->hfid_avln, avln_hfid) == 0);
+ test_fail_unless (strcmp (own_data->hfid_user, user_hfid) == 0);
+ test_fail_unless (strcmp (own_data->hfid_manufacturer,
+ manufacturer_hfid) == 0);
+ } test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_mme_error_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445566ull, 2);
+ test_case_begin (t, "mme_error");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_mme_error_ind, .peer = peer),
+#if CONFIG_TRACE
+ SCENARIO_EVENT (cp_msg_cm_mme_error_ind_receive, .ok = true,
+ .reason =
+ CP_MSG_CM_MME_ERROR_IND_REASON_MME_NOT_SUPPORTED,
+ .rx_mmv = 42, .rx_mmtype = 4242, .offset = 424242),
+#endif
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "error")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_mme_error_ind, .peer = peer),
+#if CONFIG_TRACE
+ SCENARIO_EVENT (cp_msg_cm_mme_error_ind_receive, .ok = false,
+ .reason =
+ CP_MSG_CM_MME_ERROR_IND_REASON_MME_NOT_SUPPORTED,
+ .rx_mmv = 42, .rx_mmtype = 4242, .offset = 424242),
+#endif
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_nw_stats_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ const cp_tei_t my_tei = 2;
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ /* Init mac ntb */
+ mac_config_t mac_config;
+ mac_ntb_init (&mac_config);
+
+ test_case_begin (t, "nw_stats_req when no avln");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_begin, .peer = peer,
+ .num_stats = 0),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create our net/AVLN. */
+ test_sta_action_create_our_net (&ctx, 0xAB, my_tei);
+ cp_sta_own_data_set_tei (cp, my_tei);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+ const cp_tei_t tei_1 = 10;
+ const cp_tei_t tei_2 = 11;
+ const mac_t mac_1 = 0x111111111111ull;
+ const mac_t mac_2 = 0x222222222222ull;
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, my_net, tei_1, mac_1);
+ cp_sta_t *sta_2 = cp_sta_mgr_sta_add (cp, my_net, tei_2, mac_2);
+
+ test_case_begin (t, "nw_stats_req with avln but no authentication");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_begin, .peer = peer,
+ .num_stats = 0),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_sta_set_authenticated(cp, sta_1, true);
+ cp_sta_set_authenticated(cp, sta_2, true);
+
+ sta_t *sta1 = mac_store_sta_get (cp->mac_store, tei_1);
+ sta1->tx_tonemaps->intervals->intervals_nb = 0;
+ sta1->tx_tonemaps->default_tmi = PHY_MOD_ROBO;
+ sta1->rx_tonemaps->intervals->intervals_nb = 0;
+ sta1->rx_tonemaps->default_tmi = PHY_MOD_HS_ROBO;
+ cp->mac_config->tonemask_info.tonemap_robo[PHY_MOD_ROBO].ble = 0x15;
+ cp->mac_config->tonemask_info.tonemap_robo[PHY_MOD_HS_ROBO].ble = 0x16;
+
+ sta_t *sta2 = mac_store_sta_get (cp->mac_store, tei_2);
+ sta2->tx_tonemaps->intervals->intervals_nb = 0;
+ sta2->tx_tonemaps->default_tmi = TONEMAP_INDEX_NEGOTIATED_FIRST;
+
+ sta2->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST] = tonemap_alloc ();
+ sta2->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST]->ble = 0x23;
+
+ sta2->rx_tonemaps->intervals->intervals_nb = 4;
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST] = tonemap_alloc ();
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST]->ble = 0xFF;
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 1] = tonemap_alloc ();
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 1]->ble = 0x00;
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 2] = tonemap_alloc ();
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 2]->ble = 0x08;
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 3] = tonemap_alloc ();
+ sta2->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 3]->ble = 0x0F;
+
+ sta2->rx_tonemaps->intervals->interval[0].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST;
+ sta2->rx_tonemaps->intervals->interval[0].end_offset_atu = 10;
+ sta2->rx_tonemaps->intervals->interval[1].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 1;
+ sta2->rx_tonemaps->intervals->interval[1].end_offset_atu = 100;
+ sta2->rx_tonemaps->intervals->interval[2].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 2;
+ sta2->rx_tonemaps->intervals->interval[2].end_offset_atu = 400;
+ sta2->rx_tonemaps->intervals->interval[3].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 3;
+ sta2->rx_tonemaps->intervals->interval[3].end_offset_atu = 500;
+
+ test_case_begin (t, "nw_stats_req with two stations authenticated");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_begin, .peer = peer,
+ .num_stats = 2),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send,
+ .mac = mac_1, .phy_dr_tx = 69, .phy_dr_rx = 138),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send,
+ .mac = mac_2, .phy_dr_tx = 18, .phy_dr_rx = 65),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_sta_set_authenticated(cp, sta_1, false);
+
+ test_case_begin (t, "nw_stats_req with not all stations authenticated");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_begin, .peer = peer,
+ .num_stats = 1),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send,
+ .mac = mac_2, .phy_dr_tx = 18, .phy_dr_rx = 65),
+ SCENARIO_EVENT (cp_msg_cm_nw_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Cleanup. */
+ mac_ntb_uninit ();
+ blk_release (sta1);
+ blk_release (sta2);
+ slab_release (sta_1);
+ slab_release (sta_2);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_1);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_2);
+ cp_sta_mgr_remove_avln (cp, 0xAB, my_tei);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_nw_info_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ test_sta_action_init (&ctx);
+
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_case_begin (t, "nw_info_req when no avln");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_info_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send_begin, .peer = peer,
+ .num_nw = 0),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create our net/AVLN. */
+ cp_snid_t snid = 0x34;
+ cp_nid_t nid = 0x111111111111ull;
+
+ test_sta_action_create_our_net (&ctx, nid, snid);
+
+ mac_t mac = 0x111111111111ull;
+ mac_t cco_mac = 0x111111111110ull;
+ cp_tei_t tei = 2;
+ cp_tei_t cco_tei = 1;
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+
+ /* Set cco */
+ cp_sta_t *cco = cp_sta_mgr_sta_add (cp, my_net, cco_tei, cco_mac);
+ cp_net_set_cco (cp, my_net, cco_tei);
+ slab_release (cco);
+ cp_net_set_access (cp, my_net, HPAV_ACCESS_IN_HOME);
+
+ cp_sta_own_data_set_mac_address (cp, mac);
+ cp_sta_own_data_set_tei (cp, tei);
+ cp_sta_own_data_set_authenticated_status (cp, true);
+
+ test_case_begin (t, "nw_info_req with avln");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_info_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send_begin, .peer = peer,
+ .num_nw = 1),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send, .nid = nid,
+ .snid = snid, .tei = tei,
+ .sta_role = CM_NW_INFO_CNF_STA_ROLE_STA,
+ .cco_mac = cco_mac, .access = HPAV_ACCESS_IN_HOME,
+ .num_coord_nets = 0),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* change the role of the station : the station is the cco
+ * change the access mode */
+ cco = cp_sta_mgr_sta_add (cp, my_net, tei, mac);
+ cp_net_set_cco (cp, my_net, tei);
+ slab_release (cco);
+ cp_net_set_access (cp, my_net, HPAV_ACCESS_ACCESS);
+
+ cp_sta_own_data_set_authenticated_status (cp, true);
+
+ test_case_begin (t, "nw_info_req with avln");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_nw_info_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send_begin, .peer = peer,
+ .num_nw = 1),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send, .nid = nid,
+ .snid = snid, .tei = tei,
+ .sta_role = CM_NW_INFO_CNF_STA_ROLE_CCO,
+ .cco_mac = mac, .access = HPAV_ACCESS_ACCESS,
+ .num_coord_nets = 0),
+ SCENARIO_EVENT (cp_msg_cm_nw_info_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Cleanup. */
+ cp_sta_mgr_remove_avln (cp, snid, nid);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_link_stats_test_case_common (test_t t,
+ cp_msg_cm_link_stats_tlflag_t transmit)
+{
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+ char msg [10];
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+ test_sta_action_init (&ctx);
+ cp_net_t *my_net = cp_sta_mgr_add_avln (cp, 1, 1);
+ cp_sta_mgr_set_our_avln (cp, my_net);
+ if (transmit == CM_LINK_STATS_TLFLAG_TRANSMIT)
+ strcpy (msg, "TX");
+ else
+ strcpy (msg, "RX");
+ test_begin (t, msg)
+ {
+ uint lid;
+ bool added;
+ cp_sta_t *my_sta = cp_sta_mgr_sta_add (cp, my_net, 254,
+ MAC_ADDRESS (0x00, 0x13, 0xd7, 0x01, 0x11, 0x12));
+ for (lid = 0; lid <= 0xff; lid++)
+ {
+ if (MAC_LID_IS_XLID (lid))
+ {
+ mfs_t *mfs = mac_store_mfs_add (
+ cp->mac_store, !transmit, false, false, lid,
+ cp_sta_get_tei (my_sta),
+ &added);
+ test_fail_unless (added);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive,
+ .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET,
+ .req_id = 0,
+ .nid = cp_net_get_nid (cp, my_net),
+ .lid = lid,
+ .transmit = transmit,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT,
+ .mac = cp_sta_get_mac_address (my_sta)),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 0,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = mfs,
+ .transmit = transmit),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ mac_store_mfs_remove (cp->mac_store, mfs);
+ blk_release (mfs);
+ }
+ else
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive,
+ .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET,
+ .req_id = 0,
+ .nid = cp_net_get_nid (cp, my_net),
+ .lid = lid,
+ .transmit = transmit,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT,
+ .mac = cp_sta_get_mac_address (my_sta)),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 0,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ }
+ }
+ cp_sta_mgr_sta_remove (cp, my_sta);
+ slab_release (my_sta);
+ test_sta_action_uninit (&ctx);
+ }
+ test_end;
+}
+
+void
+misc_link_stats_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+ const cp_tei_t tei_1 = 10;
+ const mac_t mac_1 = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x01);
+ u8 lid_tx = 0;
+ u8 lid_rx = 1;
+ cp_nid_t our_nid = 0x4242;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ const cp_tei_t my_tei = 2;
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_case_begin (t, "link_stats_req invalid message");
+ test_begin (t, "nok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = false,
+ .req_id = 1,
+ .req_type = CM_LINK_STATS_REQTYPE_GET),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 0,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create our net/AVLN. */
+ test_sta_action_create_our_net (&ctx, our_nid, my_tei);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+
+ test_case_begin (t, "link_stats_req invalid nid");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 1,
+ .nid = 42, .lid = lid_tx, .transmit = true,
+ .mgmt_flag = false, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 1,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "link_stats_req unknown mac");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 2,
+ .nid = our_nid, .lid = lid_tx,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 2,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create a station in the network */
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, my_net, tei_1, mac_1);
+
+ test_case_begin (t, "link_stats_req unknown link");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 3,
+ .nid = our_nid, .lid = lid_tx,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 3,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create a tx link (tx=true, broadcast=false, mme=false) */
+ bool added = false;
+ mfs_t *m_tx = mac_store_mfs_add (cp->mac_store, true, false, false,
+ lid_tx, tei_1, &added);
+
+ test_case_begin (t, "link_stats_req valid tx link req");
+ test_begin (t, "ok")
+ {
+ test_fail_unless (added == true);
+
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 4,
+ .nid = our_nid, .lid = lid_tx,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 4,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = m_tx, .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ mac_store_mfs_remove (cp->mac_store, m_tx);
+ blk_release (m_tx);
+
+ /* Create a tx link (tx=true, broadcast=true, mme=false) */
+ added = false;
+ m_tx = mac_store_mfs_add (cp->mac_store, true, true, false,
+ 0, 0xff, &added);
+ dbg_check (added);
+
+ test_case_begin (t, "link_stats_req valid tx link req");
+ test_begin (t, "ok")
+ {
+ test_fail_unless (added == true);
+
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 4,
+ .nid = our_nid, .lid = 0,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT,
+ .mac = MAC_ADDRESS (0xff, 0xff, 0xff, 0xff, 0xff, 0xff)),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 4,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ mac_store_mfs_remove (cp->mac_store, m_tx);
+ blk_release (m_tx);
+
+ /* Create a tx link (tx=true, broadcast=false, mme=true) */
+ added = false;
+ m_tx = mac_store_mfs_add (cp->mac_store, true, false, true,
+ MAC_LID_NONE, tei_1, &added);
+ dbg_check (added);
+
+ test_case_begin (t, "link_stats_req valid tx link req");
+ test_begin (t, "ok")
+ {
+ test_fail_unless (added == true);
+
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 4,
+ .nid = our_nid, .lid = MAC_LID_NONE,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 4,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = m_tx, .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ mac_store_mfs_remove (cp->mac_store, m_tx);
+ blk_release (m_tx);
+
+ /* Create a rx link (tx=false, broadcast=false, mme=false) */
+ added = false;
+ mfs_t *m_rx = mac_store_mfs_add (cp->mac_store, false, false, false,
+ lid_rx, tei_1, &added);
+ dbg_check (added);
+ mfs_t *mme_rx = mac_store_mfs_add (cp->mac_store, false, false, true,
+ MAC_LID_NONE, tei_1, &added);
+ dbg_check (added);
+ mfs_t *bcast_rx = mac_store_mfs_add (cp->mac_store, false, true, false,
+ 0, tei_1, &added);
+ dbg_check (added);
+
+ test_case_begin (t, "link_stats_req valid rx link req");
+ test_begin (t, "multiple rx")
+ {
+ scenario_entry_t entries[] = {
+ /* Unicast link. */
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 5,
+ .nid = our_nid, .lid = lid_rx,
+ .transmit = CM_LINK_STATS_TLFLAG_RECEIVE,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 5,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = m_rx, .transmit = CM_LINK_STATS_TLFLAG_RECEIVE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ /* Unicast MME link. */
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 5,
+ .nid = our_nid, .lid = 124,
+ .transmit = CM_LINK_STATS_TLFLAG_RECEIVE,
+ .mgmt_flag = CM_LINK_STATS_MGMT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 5,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = mme_rx, .transmit = CM_LINK_STATS_TLFLAG_RECEIVE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ /* Bcast link. */
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET, .req_id = 5,
+ .nid = our_nid, .lid = 0,
+ .transmit = CM_LINK_STATS_TLFLAG_RECEIVE,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT,
+ .mac = MAC_BROADCAST),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 5,
+ .res_type = CM_LINK_STATS_RESTYPE_FAILURE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ mac_store_mfs_remove (cp->mac_store, mme_rx);
+ mac_store_mfs_remove (cp->mac_store, bcast_rx);
+ blk_release (mme_rx);
+ blk_release (bcast_rx);
+
+ added = false;
+ m_tx = mac_store_mfs_add (cp->mac_store, true, false, false,
+ lid_tx, tei_1, &added);
+
+ /* Force tx stats value with non-zero values */
+ m_tx->tx.stats.statistics_start_rtc_date = 0xFFFFFFFF;
+ m_tx->tx.stats.num_msdus = 0xFFFFFFFF;
+ m_tx->tx.stats.octets = 0xFFFFFFFF;
+ m_tx->tx.stats.num_segs = 0xFFFFFFFF;
+ m_tx->tx.stats.num_segs_suc = 0xFFFFFFFF;
+ m_tx->tx.stats.num_segs_dropped = 0xFFFFFFFF;
+ m_tx->tx.stats.num_pbs = 0xFFFFFFFF;
+ m_tx->tx.stats.num_mpdus = 0xFFFFFFFF;
+ m_tx->tx.stats.num_bursts = 0xFFFFFFFF;
+ m_tx->tx.stats.num_sacks = 0xFFFFFFFF;
+
+ test_case_begin (t, "link_stats_req valid tx link get and reset");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET_AND_RESET,
+ .req_id = 8, .nid = our_nid, .lid = lid_tx,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 8,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = m_tx, .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ test_fail_unless (m_tx->tx.stats.statistics_start_rtc_date == 0);
+ test_fail_unless (m_tx->tx.stats.num_msdus == 0);
+ test_fail_unless (m_tx->tx.stats.octets == 0);
+ test_fail_unless (m_tx->tx.stats.num_segs == 0);
+ test_fail_unless (m_tx->tx.stats.num_segs_suc == 0);
+ test_fail_unless (m_tx->tx.stats.num_segs_dropped == 0);
+ test_fail_unless (m_tx->tx.stats.num_pbs == 0);
+ test_fail_unless (m_tx->tx.stats.num_mpdus == 0);
+ test_fail_unless (m_tx->tx.stats.num_bursts == 0);
+ test_fail_unless (m_tx->tx.stats.num_sacks == 0);
+ } test_end;
+
+ /* Force tx stats value with non-zero values */
+ m_tx->tx.stats.statistics_start_rtc_date = 0xFFFFFFFF;
+ m_tx->tx.stats.num_msdus = 0xFFFFFFFF;
+ m_tx->tx.stats.octets = 0xFFFFFFFF;
+ m_tx->tx.stats.num_segs = 0xFFFFFFFF;
+ m_tx->tx.stats.num_segs_suc = 0xFFFFFFFF;
+ m_tx->tx.stats.num_segs_dropped = 0xFFFFFFFF;
+ m_tx->tx.stats.num_pbs = 0xFFFFFFFF;
+ m_tx->tx.stats.num_mpdus = 0xFFFFFFFF;
+ m_tx->tx.stats.num_bursts = 0xFFFFFFFF;
+ m_tx->tx.stats.num_sacks = 0xFFFFFFFF;
+
+ test_case_begin (t, "link_stats_req valid tx link reset");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_RESET, .req_id = 9,
+ .nid = our_nid, .lid = lid_tx,
+ .transmit = CM_LINK_STATS_TLFLAG_TRANSMIT,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 9,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ test_fail_unless (m_tx->tx.stats.statistics_start_rtc_date == 0);
+ test_fail_unless (m_tx->tx.stats.num_msdus == 0);
+ test_fail_unless (m_tx->tx.stats.octets == 0);
+ test_fail_unless (m_tx->tx.stats.num_segs == 0);
+ test_fail_unless (m_tx->tx.stats.num_segs_suc == 0);
+ test_fail_unless (m_tx->tx.stats.num_segs_dropped == 0);
+ test_fail_unless (m_tx->tx.stats.num_pbs == 0);
+ test_fail_unless (m_tx->tx.stats.num_mpdus == 0);
+ test_fail_unless (m_tx->tx.stats.num_bursts == 0);
+ test_fail_unless (m_tx->tx.stats.num_sacks == 0);
+ } test_end;
+
+ /* Force rx stats value with non-zero values */
+ m_rx->rx.stats.statistics_start_rtc_date = 0xFFFFFFFF;
+ m_rx->rx.stats.num_msdus = 0xFFFFFFFF;
+ m_rx->rx.stats.octets = 0xFFFFFFFF;
+ m_rx->rx.stats.num_segs_suc = 0xFFFFFFFF;
+ m_rx->rx.stats.num_segs_missed = 0xFFFFFFFF;
+ m_rx->rx.stats.num_pbs = 0xFFFFFFFF;
+ m_rx->rx.stats.num_mpdus = 0xFFFFFFFF;
+ m_rx->rx.stats.num_bursts = 0xFFFFFFFF;
+ m_rx->rx.stats.num_icv_fails = 0xFFFFFFFF;
+
+ test_case_begin (t, "link_stats_req valid rx link get and reset");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_GET_AND_RESET,
+ .req_id = 6, .nid = our_nid, .lid = lid_rx,
+ .transmit = CM_LINK_STATS_TLFLAG_RECEIVE,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 6,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send,
+ .mfs = m_rx, .transmit = CM_LINK_STATS_TLFLAG_RECEIVE),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ test_fail_unless (m_rx->rx.stats.statistics_start_rtc_date == 0);
+ test_fail_unless (m_rx->rx.stats.num_msdus == 0);
+ test_fail_unless (m_rx->rx.stats.octets == 0);
+ test_fail_unless (m_rx->rx.stats.num_segs_suc == 0);
+ test_fail_unless (m_rx->rx.stats.num_segs_missed == 0);
+ test_fail_unless (m_rx->rx.stats.num_pbs == 0);
+ test_fail_unless (m_rx->rx.stats.num_mpdus == 0);
+ test_fail_unless (m_rx->rx.stats.num_bursts == 0);
+ test_fail_unless (m_rx->rx.stats.num_icv_fails == 0);
+ } test_end;
+
+ /* Force rx stats value with non-zero values */
+ m_rx->rx.stats.statistics_start_rtc_date = 0xFFFFFFFF;
+ m_rx->rx.stats.num_msdus = 0xFFFFFFFF;
+ m_rx->rx.stats.octets = 0xFFFFFFFF;
+ m_rx->rx.stats.num_segs_suc = 0xFFFFFFFF;
+ m_rx->rx.stats.num_segs_missed = 0xFFFFFFFF;
+ m_rx->rx.stats.num_pbs = 0xFFFFFFFF;
+ m_rx->rx.stats.num_mpdus = 0xFFFFFFFF;
+ m_rx->rx.stats.num_bursts = 0xFFFFFFFF;
+ m_rx->rx.stats.num_icv_fails = 0xFFFFFFFF;
+
+ test_case_begin (t, "link_stats_req valid rx link reset");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_req_receive, .ok = true,
+ .req_type = CM_LINK_STATS_REQTYPE_RESET, .req_id = 7,
+ .nid = our_nid, .lid = lid_rx,
+ .transmit = CM_LINK_STATS_TLFLAG_RECEIVE,
+ .mgmt_flag = CM_LINK_STATS_MGMT_NOT_MGMT, .mac = mac_1),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_begin,
+ .peer = peer, .req_id = 7,
+ .res_type = CM_LINK_STATS_RESTYPE_SUCCESS),
+ SCENARIO_EVENT (cp_msg_cm_link_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ test_fail_unless (m_rx->rx.stats.statistics_start_rtc_date == 0);
+ test_fail_unless (m_rx->rx.stats.num_msdus == 0);
+ test_fail_unless (m_rx->rx.stats.octets == 0);
+ test_fail_unless (m_rx->rx.stats.num_segs_suc == 0);
+ test_fail_unless (m_rx->rx.stats.num_segs_missed == 0);
+ test_fail_unless (m_rx->rx.stats.num_pbs == 0);
+ test_fail_unless (m_rx->rx.stats.num_mpdus == 0);
+ test_fail_unless (m_rx->rx.stats.num_bursts == 0);
+ test_fail_unless (m_rx->rx.stats.num_icv_fails == 0);
+ } test_end;
+ /* Cleanup. */
+ mac_store_mfs_remove (cp->mac_store, m_rx);
+ blk_release (m_rx);
+ mac_store_mfs_remove (cp->mac_store, m_tx);
+ blk_release (m_tx);
+ cp_sta_mgr_sta_remove (cp, sta_1);
+ slab_release (sta_1);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_link_stats_test_case_all_lids (test_t t)
+{
+ test_case_begin (t, "All possible values");
+ misc_link_stats_test_case_common (t, CM_LINK_STATS_TLFLAG_TRANSMIT);
+ misc_link_stats_test_case_common (t, CM_LINK_STATS_TLFLAG_RECEIVE);
+}
+
+
+void
+misc_sta_cap_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ const mac_t mac = 0x111111111111ull;
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+ cp_sta_own_data_set_mac_address (cp, mac);
+
+ test_case_begin (t, "cm_sta_cap_req invalid message");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_sta_cap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_sta_cap_req_receive, .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "valid cm_sta_cap_req");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (process_cm_sta_cap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_cm_sta_cap_req_receive, .ok = true),
+ SCENARIO_EVENT (cp_msg_cm_sta_cap_cnf_send, .peer = peer,
+ .av_version = CP_AV_VERSION,
+ .mac = mac, .oui = SPC_OUI, .auto_connect = CP_ACS_CAP,
+ .smoothing = CP_SMOOTHING_CAP, .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP,
+ .backup_cco_cap = CP_BACKUP_CCO_CAP,
+ .soft_handover = CP_SOFT_HANDOVER_CAP,
+ .two_sym_fc = CP_TWO_SYM_FC_CAP,
+ .max_fl_av = MAC_MAX_FL_MAX_FL,
+ .homeplug_11_cap = CP_HOMEPLUG_AV11,
+ .homeplug_101_int = CP_HOMEPLUG_AV101,
+ .regulatory_cap = CP_REGULATORY_CAP,
+ .bidir_burst = CP_BIDIRECTIONAL_BURSTING_CAP,
+ .implementation_version = BUILD_INFO_IMPLEMENTATION),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+misc_test_suite (test_t t)
+{
+ test_suite_begin (t, "misc");
+ misc_whoru_test_case (t);
+ misc_cc_discover_list_test_case (t);
+ misc_relay_test_case (t);
+ misc_hfid_test_case (t);
+ misc_mme_error_test_case (t);
+ misc_nw_stats_test_case (t);
+ misc_nw_info_test_case (t);
+ misc_link_stats_test_case (t);
+ misc_link_stats_test_case_all_lids (t);
+ misc_sta_cap_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/msg_stub.c b/cesar/cp/av/sta/action/test/utest/src/msg_stub.c
new file mode 100644
index 0000000000..fb877baec5
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/msg_stub.c
@@ -0,0 +1,669 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/msg_stub.c
+ * \brief cp/msg module stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "mac/common/tonemap.h"
+
+#include "cp/inc/context.h"
+#include "cp/msg/msg.h"
+#include "hal/phy/defs.h"
+#include "cp/msg/inc/vs_get_tonemap.h"
+#include "cp/msg/inc/cc_discover_list.h"
+
+#include <string.h>
+
+#define __ptr_(TYPE) PASTE_EXPAND (__ptr__, TYPE)
+#define __ptr__assign *
+#define __ptr__string
+#define __ptr__array
+#define __ptr__string_or_null
+#define __ptr__tonemask
+#define __ptr__hash_key
+
+#define __dim_(TYPE, DIM...) PASTE_EXPAND (__dim__, TYPE) (DIM)
+#define __dim__assign()
+#define __dim__string()
+#define __dim__array(DIM) DIM
+#define __dim__string_or_null()
+#define __dim__tonemask()
+#define __dim__hash_key()
+
+/* Code for MME transmission. */
+#define __ms(EVENT, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ scenario_event (EVENT, param); \
+ __ms_test_peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+}
+
+/* Code for MME transmission complex with a begin. */
+#define __mscb(EVENT, PARAMS...) \
+cp_mme_tx_t * \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ scenario_event (EVENT, param, global); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+ return global->mme; \
+}
+
+/* Code for MME transmission complex (with or without an end). */
+#define __msc(EVENT, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_tx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ scenario_event (EVENT, param); \
+ test_fail_unless (param); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+}
+
+#define __msdc(EVENT, DATA, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_tx_t *mme, const DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __msd_test_, ## PARAMS) \
+}
+
+#define __ms_pdecl_(TYPE, PARAM, KIND) , TYPE PARAM
+#define __ms_test_(TYPE, PARAM, KIND) \
+ PASTE_EXPAND (__ms_test__, KIND) (PARAM)
+#define __ms_test__assign(PARAM) \
+ test_fail_unless (PARAM == param->PARAM);
+#define __ms_test__ignore_pointer(PARAM)
+#define __ms_test__string(PARAM) \
+ test_fail_unless (strcmp (PARAM, param->PARAM) == 0);
+#define __ms_test_peer \
+ test_fail_unless (peer->mac == param->peer.mac); \
+ test_fail_unless (peer->eth_type == param->peer.eth_type); \
+ test_fail_unless (peer->vlan_tci == param->peer.vlan_tci); \
+ test_fail_unless (peer->tei == param->peer.tei); \
+
+/* Code for MME transmission with a data structure. */
+#define __msd(EVENT, DATA, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer, const DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param); \
+ __ms_test_peer \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __msd_test_, ## PARAMS) \
+}
+
+#define __msd_test_(TYPE, PARAM, KIND) \
+ PASTE_EXPAND (__msd_test__, KIND) (PARAM)
+#define __msd_test__assign(PARAM) \
+ test_fail_unless (data->PARAM == param->PARAM);
+#define __msd_test__string(PARAM) \
+ test_fail_unless (strcmp (data->PARAM, param->PARAM) == 0);
+#define __msd_test__hash_key(PARAM) \
+ test_fail_unless (!param->PARAM || memcmp (data->PARAM, param->PARAM, \
+ CP_HASH_KEY_SIZE) == 0);
+#define __msd_test__key(PARAM) \
+ test_fail_unless (memcmp (&data->PARAM, &param->PARAM, \
+ sizeof (cp_key_t)) == 0);
+#define __ms_test__key(PARAM) \
+ test_fail_unless (memcmp (&PARAM, &param->PARAM, \
+ sizeof (cp_key_t)) == 0);
+#define __msd_test__sub_assign(PARAM) \
+ __msd_test__sub_assign_ PARAM
+#define __msd_test__sub_assign_(PARAM, SUBNAME) \
+ test_fail_unless (data->SUBNAME.PARAM == param->PARAM);
+#define __msd_test__ignore_pointer(PARAM) ;
+
+#define __msd_test__array(PARAM) \
+ __msd_test__array_ PARAM
+#define __msd_test__array_(PARAM, SIZE) \
+ test_fail_unless (memcmp (data->PARAM, param->PARAM, SIZE) == 0);
+
+/* Code for MME transmission with a data structure with encryption
+ * information. */
+#define __msk(EVENT, DATA, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_peer_t *peer, cp_mme_peks_t peks, \
+ const cp_secu_protocol_run_t *prun, const DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (peer); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param, global); \
+ __ms_test_peer \
+ test_fail_unless (peks == param->peks); \
+ test_fail_unless (prun->pid == param->pid); \
+ test_fail_unless (prun->pmn == param->pmn); \
+ global->prn = prun->prn; \
+ global->my_nonce = prun->my_nonce; \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __msd_test_, ## PARAMS) \
+}
+
+/* Code for MME transmission for CC_RELAY.IND. */
+#define __msr(EVENT, PARAMS...) \
+void \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ scenario_event (EVENT, param); \
+ test_fail_unless (mme->relay.mac_fa == param->mac_fa); \
+ test_fail_unless (mme->relay.ftei == param->ftei); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __ms_test_, ## PARAMS) \
+}
+
+
+/* Code for MME reception. */
+#define __mr(EVENT, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_assert_, ## PARAMS) \
+ scenario_event (EVENT, param); \
+ if (param->ok) \
+ { \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_copy_, ## PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+#define __mr_pdecl_(TYPE, PARAM, KIND, DIM...) \
+ , TYPE __ptr_ (KIND) PARAM __dim_ (KIND, ## DIM)
+#define __mr_assert_(TYPE, PARAM, KIND, DIM...) dbg_assert_ptr (PARAM);
+#define __mr_copy_(TYPE, PARAM, KIND, DIM...) \
+ PASTE_EXPAND (__mr_copy__, KIND) (PARAM, TYPE, ## DIM)
+
+#define __mr_copy__assign(PARAM, TYPE) *PARAM = param->PARAM;
+#define __mr_copy__string(PARAM, TYPE) strcpy (PARAM, param->PARAM);
+#define __mr_copy__string_or_null(PARAM, TYPE) \
+ if (param->PARAM) strcpy (PARAM, param->PARAM);
+#define __mr_copy__tonemask(PARAM, TYPE) \
+ memcpy (PARAM, param->PARAM, PHY_TONEMASK_SIZE);
+#define __mr_copy__array(PARAM, TYPE, DIM) \
+ memcpy (PARAM, param->PARAM, sizeof(TYPE DIM));
+
+/* Code for MME reception with a data structure. */
+#define __mrd(EVENT, DATA, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme, DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param); \
+ if (param->ok) \
+ { \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mrd_copy_, PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+#define __mrd_copy_(TYPE, PARAM, KIND) \
+ PASTE_EXPAND (__mrd_copy__, KIND) (PARAM)
+
+#define __mrd_copy__assign(PARAM) data->PARAM = param->PARAM;
+#define __mrd_copy__string(PARAM) strcpy (data->PARAM, param->PARAM);
+#define __mrd_copy__tonemask(PARAM) \
+ memcpy (data->PARAM, param->PARAM, PHY_TONEMASK_SIZE);
+#define __mrd_copy__hash_key(PARAM) \
+ if (param->PARAM) memcpy (data->PARAM, param->PARAM, CP_HASH_KEY_SIZE);
+#define __mrd_copy__assign_deref(PARAM) \
+ if (param->PARAM) data->PARAM = *param->PARAM;
+
+/* Code for MME reception with a data structure with encryption
+ * information. */
+#define __mrk(EVENT, DATA, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme, DATA *data) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ dbg_assert (data); \
+ scenario_event (EVENT, param, g); \
+ if (param->ok) \
+ { \
+ mme->peks = param->peks; \
+ if (param->new_prn) g->prn = lib_rnd32 (&ctx->rnd) & 0xffff; \
+ if (param->new_my_nonce) g->my_nonce = lib_rnd32 (&ctx->rnd); \
+ if (param->new_your_nonce) g->your_nonce = lib_rnd32 (&ctx->rnd); \
+ mme->prun.pid = param->pid; \
+ mme->prun.pmn = param->pmn; \
+ mme->prun.prn = g->prn; \
+ mme->prun.my_nonce = g->my_nonce; \
+ mme->prun.your_nonce = g->your_nonce; \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mrd_copy_, PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+/* Code for MME reception for CC_RELAY.REQ. */
+#define __mrr(EVENT, PARAMS...) \
+bool \
+EVENT (cp_t *ctx, cp_mme_rx_t *mme \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_pdecl_, ## PARAMS)) \
+{ \
+ dbg_assert (ctx); \
+ dbg_assert (mme); \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_assert_, ## PARAMS) \
+ scenario_event (EVENT, param); \
+ if (param->ok) \
+ { \
+ mme->relay.mac_fa = param->mac_fa; \
+ mme->relay.ftei = param->ftei; \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, __mr_copy_, ## PARAMS) \
+ return true; \
+ } \
+ else \
+ return false; \
+}
+
+__ms (cp_msg_cc_who_ru_req_send,
+ (cp_nid_t, nid, assign))
+__mr (cp_msg_cc_who_ru_req_receive,
+ (cp_nid_t, nid, assign))
+__msd (cp_msg_cc_who_ru_cnf_send, cp_msg_cc_who_ru_cnf_t,
+ (cp_nid_t, nid, assign),
+ (mac_t, cco_mac, assign),
+ (char *, avln_hfid, string))
+__mrd (cp_msg_cc_who_ru_cnf_receive, cp_msg_cc_who_ru_cnf_t,
+ (cp_nid_t, nid, assign),
+ (mac_t, cco_mac, assign),
+ (char *, avln_hfid, string))
+__mr (cp_msg_cc_discover_list_req_receive)
+__mscb (cp_msg_cc_discover_list_cnf_send_begin,
+ (uint, nb_sta, assign),
+ (uint, nb_net, assign),
+ (cp_msg_cc_discover_list_ctx_t *, disc_ctx, ignore_pointer))
+__msc (cp_msg_cc_discover_list_cnf_send_stations_begin,
+ (cp_msg_cc_discover_list_ctx_t *, disc_ctxc, ignore_pointer))
+__msdc (cp_msg_cc_discover_list_cnf_send_station,
+ cp_msg_cc_discover_list_sta_t,
+ (mac_t, mac_addr, assign),
+ (cp_tei_t, tei, assign),
+ (enum cp_msg_cc_discover_list_same_network_t, same_network, assign),
+ (cp_snid_t, snid, assign),
+ (hpav_access_t, access, assign),
+ (u8, cco_cap, assign),
+ (bool, proxy_cap, assign),
+ (bool, backup_cco_cap, assign),
+ (bool, cco_status, assign),
+ (bool, pco_status, assign),
+ (bool, backup_cco_status, assign),
+ (u8, signal_level, assign),
+ (u8, average_ble, assign))
+__msc (cp_msg_cc_discover_list_cnf_send_net_begin,
+ (cp_msg_cc_discover_list_ctx_t *, disc_ctxc, ignore_pointer))
+__msdc (cp_msg_cc_discover_list_cnf_send_net, cp_msg_cc_discover_list_net_t,
+ (cp_nid_t, nid, assign),
+ (cp_snid_t, snid, assign),
+ (hpav_access_t, access, assign),
+ (u8, hm, assign),
+ (u8, numslots, assign),
+ (enum cp_msg_cc_discover_list_coodinated_status_t, coordinated_status,
+ assign),
+ (u16, offset, assign))
+__msc (cp_msg_cc_discover_list_cnf_send_end)
+
+__msd (cp_msg_cc_assoc_req_send, cp_msg_cc_assoc_req_t,
+ (enum cp_msg_cc_assoc_req_type_t, request_type, assign),
+ (cp_nid_t, nid, assign),
+ (u8, cco_cap, assign),
+ (u8, proxy_cap, assign))
+__mrd (cp_msg_cc_assoc_cnf_receive, cp_msg_cc_assoc_cnf_t,
+ (enum cp_msg_cc_assoc_cnf_result_t *, result, assign),
+ (cp_nid_t, nid, assign),
+ (cp_snid_t, snid, assign),
+ (cp_tei_t, sta_tei, assign),
+ (u16, lease_time_min, assign))
+__ms (cp_msg_cc_leave_req_send,
+ (enum cp_msg_cc_leave_req_reason_t, reason, assign))
+__mr (cp_msg_cc_leave_cnf_receive)
+__mr (cp_msg_cc_leave_ind_receive,
+ (enum cp_msg_cc_leave_ind_reason_t, reason, assign),
+ (cp_nid_t, nid, assign))
+__ms (cp_msg_cc_leave_rsp_send)
+__mr (cp_msg_cc_set_tei_map_ind_receive_begin,
+ (enum cp_msg_cc_set_tei_map_ind_mode_t, mode, assign),
+ (uint, sta_nb, assign))
+__mr (cp_msg_cc_set_tei_map_ind_receive_sta,
+ (cp_tei_t, tei, assign),
+ (mac_t, mac, assign),
+ (enum cp_msg_cc_set_tei_map_ind_status_t, status, assign))
+__mr (cp_msg_cc_set_tei_map_ind_receive_end)
+__mrr (cp_msg_cc_relay_req_receive,
+ (uint, length, assign),
+ (uint, mmtype, assign))
+__msr (cp_msg_cc_relay_ind_send,
+ (mac_t, osa, assign),
+ (cp_tei_t, stei, assign),
+ (uint, length, assign))
+
+__ms (cp_msg_cm_unassociated_sta_ind_send,
+ (cp_nid_t, nid, assign),
+ (u8, cco_cap, assign))
+__mr (cp_msg_cm_unassociated_sta_ind_receive,
+ (cp_nid_t, nid, assign),
+ (u8, cco_cap, assign))
+__mrk (cp_msg_cm_set_key_req_receive, cp_msg_cm_set_key_req_t,
+ (enum cp_msg_key_type_t, key_type, assign),
+ (u8, cco_cap, assign),
+ (cp_nid_t, nid, assign),
+ (u8, new_eks, assign),
+ (cp_key_t, new_key, assign))
+__msk (cp_msg_cm_set_key_cnf_send, cp_msg_cm_set_key_cnf_t,
+ (enum cp_msg_cm_set_key_cnf_result_t, result, assign),
+ (u8, cco_cap, assign))
+__msk (cp_msg_cm_get_key_cnf_send, cp_msg_cm_get_key_cnf_t,
+ (enum cp_msg_cm_get_key_cnf_result_t, result, assign),
+ (enum cp_msg_key_type_t, key_type, assign),
+ (cp_nid_t, nid, assign),
+ (u8, eks, assign),
+ (u32 *, hash_key, hash_key))
+__msk (cp_msg_cm_get_key_req_send, cp_msg_cm_get_key_req_t,
+ (bool, relayed, assign),
+ (enum cp_msg_key_type_t, key_type, assign),
+ (cp_nid_t, nid, assign),
+ (u32 *, hash_key, hash_key))
+__mrk (cp_msg_cm_get_key_req_receive, cp_msg_cm_get_key_req_t,
+ (bool, relayed, assign),
+ (enum cp_msg_key_type_t, key_type, assign),
+ (cp_nid_t, nid, assign),
+ (u32 *, hash_key, hash_key))
+__mrk (cp_msg_cm_get_key_cnf_receive, cp_msg_cm_get_key_cnf_t,
+ (enum cp_msg_cm_get_key_cnf_result_t, result, assign),
+ (enum cp_msg_key_type_t, key_type, assign),
+ (cp_nid_t, nid, assign),
+ (u8, eks, assign),
+ (u32 *, hash_key, hash_key),
+ (cp_key_t, key, assign_deref))
+__mr (cp_msg_cm_hfid_req_receive,
+ (enum cp_msg_cm_hfid_req_reqtype_t, req_type, assign),
+ (cp_nid_t, nid, assign),
+ (char *, hfid, string_or_null))
+__ms (cp_msg_cm_hfid_cnf_send,
+ (enum cp_msg_cm_hfid_cnf_restype_t, restype, assign),
+ (const char *, hfid, string))
+__mrd (cp_msg_cm_mme_error_ind_receive, cp_msg_cm_mme_error_ind_t,
+ (enum cp_msg_cm_mme_error_ind_reason_t, reason, assign),
+ (u8, rx_mmv, assign),
+ (cp_mmtype_t, rx_mmtype, assign),
+ (uint, offset, assign))
+__msd (cp_msg_cm_sc_join_cnf_send, cp_msg_cm_sc_join_cnf_t,
+ (cp_nid_t, nid, assign),
+ (bool, avln_status, assign),
+ (u8, cco_cap, assign),
+ (bool, pco_cap, assign),
+ (bool, backup_cco_cap, assign),
+ (bool, cco_status, assign),
+ (bool, pco_status, assign),
+ (bool, backup_cco_status, assign))
+__mrd (cp_msg_cm_sc_join_cnf_receive, cp_msg_cm_sc_join_cnf_t,
+ (cp_nid_t, nid, assign),
+ (bool, avln_status, assign),
+ (u8, cco_cap, assign),
+ (bool, pco_cap, assign),
+ (bool, backup_cco_cap, assign),
+ (bool, cco_status, assign),
+ (bool, pco_status, assign),
+ (bool, backup_cco_status, assign))
+__ms (cp_msg_cm_sc_join_req_send)
+__mr (cp_msg_cm_sc_join_req_receive,
+ (uint, cco_cap, assign))
+__msk (cp_msg_cm_set_key_req_send, cp_msg_cm_set_key_req_t,
+ (enum cp_msg_key_type_t, key_type, assign),
+ (u8, cco_cap, assign),
+ (cp_nid_t, nid, assign),
+ (u8, new_eks, assign),
+ (cp_key_t, new_key, key))
+__mrk (cp_msg_cm_set_key_cnf_receive, cp_msg_cm_set_key_cnf_t,
+ (enum cp_msg_cm_set_key_cnf_result_t, result, assign),
+ (u8, cco_cap, assign))
+
+__mr (cp_msg_drv_sta_set_mac_addr_req_receive, (mac_t, mac, assign))
+__mr (cp_msg_drv_sta_set_cco_pref_req_receive, (bool, cco_pref, assign))
+__mr (cp_msg_drv_sta_set_was_cco_req_receive, (bool, was_cco, assign))
+__mr (cp_msg_drv_sta_set_npw_req_receive, (char *, npw, string))
+__mr (cp_msg_drv_sta_set_dpw_req_receive, (char *, dpw, string))
+__mr (cp_msg_drv_sta_set_sl_req_receive, (cp_security_level_t, sl, assign))
+__mr (cp_msg_drv_sta_set_nid_req_receive, (cp_nid_t, nid, assign))
+__mr (cp_msg_drv_sta_set_m_sta_hfid_req_receive, (char *, m_sta_hfid, string))
+__mr (cp_msg_drv_sta_set_u_sta_hfid_req_receive, (char *, u_sta_hfid, string))
+__mr (cp_msg_drv_sta_set_avln_hfid_req_receive, (char *, avln_hfid, string))
+__mr (cp_msg_drv_sta_set_tonemask_req_receive, (u32 *, tonemask, tonemask))
+__mr (cp_msg_drv_sta_mac_start_req_receive)
+__mr (cp_msg_drv_sta_mac_stop_req_receive)
+__mr (cp_msg_drv_sta_sc_req_receive, (bool, sc_join, assign))
+__mr (cp_msg_drv_sta_set_key_req_receive, (cp_key_t, nmk, assign),
+ (enum cp_msg_drv_sta_set_key_type_t, type, assign),
+ (cp_nid_t, nid, assign),
+ (cp_security_level_t, sl, assign))
+__ms (cp_msg_drv_sta_set_key_ind_send,
+ (cp_key_t, nmk, key),
+ (enum cp_msg_drv_sta_set_key_type_t, type, assign),
+ (cp_nid_t, nid, assign),
+ (cp_security_level_t, sl, assign))
+__mr (cp_msg_drv_sta_set_dak_req_receive, (cp_key_t, dak, assign))
+__ms (cp_msg_drv_any_cnf_send,
+ (cp_mmtype_t, mmtype, assign),
+ (cp_msg_drv_result_t, result, assign))
+__mr (cp_msg_drv_sta_get_key_req_receive)
+__msd (cp_msg_drv_sta_get_key_cnf_send, cp_msg_drv_sta_get_key_t,
+ (uint, result, assign),
+ (cp_key_t, nmk, key),
+ (cp_nid_t, nid, assign),
+ (cp_security_level_t, sl, assign))
+__mr (cp_msg_drv_sta_status_req_receive)
+__msd (cp_msg_drv_sta_status_cnf_send, cp_msg_drv_sta_status_cnf_t,
+ (uint, result, assign),
+ (cp_msg_drv_sta_status_status_t, (status, status), sub_assign),
+ (cp_msg_drv_sta_status_cco_t, (cco, status), sub_assign),
+ (bool, (preferred_cco, status), sub_assign),
+ (bool, (backup_cco, status), sub_assign),
+ (bool, (simple_connect, status), sub_assign),
+ (bsu_aclf_frequency_t, (pwl_sync_frequency, status), sub_assign))
+__msd (cp_msg_drv_sta_status_ind_send, cp_msg_drv_sta_status_t,
+ (cp_msg_drv_sta_status_status_t, status, assign),
+ (cp_msg_drv_sta_status_cco_t, cco, assign),
+ (bool, preferred_cco, assign),
+ (bool, backup_cco, assign),
+ (bool, simple_connect, assign),
+ (bsu_aclf_frequency_t, pwl_sync_frequency, assign))
+__mr (cp_msg_drv_sta_set_config_req_receive,
+ (char *, config, string))
+__mr (cp_msg_drv_mcast_set_list_req_receive,
+ (uint, nb_groups, assign),
+ (mac_t, groups, array, [MCAST_GROUP_MAX_NB]),
+ (uint, nb_members, array, [MCAST_GROUP_MAX_NB]),
+ (mac_t, members, array, [MCAST_GROUP_MAX_NB][MCAST_MEMBER_MAX_NB]))
+
+__mr (cp_msg_cm_brg_info_cnf_receive_begin,
+ (uint, bsf, assign),
+ (uint, nbda, assign))
+__mr (cp_msg_cm_brg_info_cnf_receive,
+ (mac_t, mac, assign))
+__mr (cp_msg_cm_brg_info_cnf_receive_end)
+
+__mr (cp_msg_cm_brg_info_req_receive)
+__mscb (cp_msg_cm_brg_info_cnf_send_begin,
+ (const uint, bsf, assign),
+ (const uint, nbda, assign),
+ (const uint, own_tei, assign))
+__msc (cp_msg_cm_brg_info_cnf_send,
+ (const mac_t, mac, assign))
+__msc (cp_msg_cm_brg_info_cnf_send_end)
+
+__mr (cp_msg_cc_handover_req_receive,
+ (cp_msg_cc_handover_req_soft_hard_t, soft_hard, assign),
+ (cp_msg_cc_handover_req_reason_t, reason, assign))
+__ms (cp_msg_cc_handover_cnf_send,
+ (cp_msg_cc_handover_cnf_result_t, result, assign))
+__mr (cp_msg_cc_handover_info_ind_receive_begin,
+ (cp_msg_cc_handover_info_ind_rsc_t, rsc, assign),
+ (cp_tei_t, bcco, assign),
+ (uint, num_sta, assign))
+__mr (cp_msg_cc_handover_info_ind_receive,
+ (cp_tei_t, tei, assign),
+ (mac_t, mac_addr, assign),
+ (uint, status, assign),
+ (cp_tei_t, ptei, assign))
+__mr (cp_msg_cc_handover_info_ind_receive_end)
+__ms (cp_msg_cc_handover_info_rsp_send)
+__mscb (cp_msg_cm_nw_stats_cnf_send_begin,
+ (const uint, num_stats, assign))
+__msc (cp_msg_cm_nw_stats_cnf_send,
+ (mac_t, mac, assign),
+ (uint, phy_dr_tx, assign),
+ (uint, phy_dr_rx, assign))
+__msc (cp_msg_cm_nw_stats_cnf_send_end)
+__mr (cp_msg_cm_nw_stats_req_receive)
+__mscb (cp_msg_cm_nw_info_cnf_send_begin,
+ (const uint, num_nw, assign))
+__msdc (cp_msg_cm_nw_info_cnf_send, cp_msg_cm_nw_info_cnf_t,
+ (cp_nid_t, nid, assign),
+ (cp_snid_t, snid, assign),
+ (cp_tei_t, tei, assign),
+ (int, sta_role, assign),
+ (mac_t, cco_mac, assign),
+ (hpav_access_t, access, assign),
+ (u8, num_coord_nets, assign))
+__msc (cp_msg_cm_nw_info_cnf_send_end)
+__mr (cp_msg_cm_nw_info_req_receive)
+__mscb (cp_msg_cm_link_stats_cnf_send_begin,
+ (u8, req_id, assign),
+ (u8, res_type, assign))
+__msc (cp_msg_cm_link_stats_cnf_send,
+ (mfs_t*, mfs, assign),
+ (cp_msg_cm_link_stats_tlflag_t, transmit, assign))
+__msc (cp_msg_cm_link_stats_cnf_send_end)
+__mrd (cp_msg_cm_link_stats_req_receive, cp_msg_cm_link_stats_req_t,
+ (int, req_type, assign),
+ (u8, req_id, assign),
+ (cp_nid_t, nid, assign),
+ (u8, lid, assign),
+ (bool, transmit, assign),
+ (bool, mgmt_flag, assign),
+ (mac_t, mac, assign))
+__ms (cp_msg_vs_get_tonemap_cnf_send,
+ (cp_msg_vs_get_tonemap_cnf_result_t, result, assign),
+ (uint, beacon_delta, assign),
+ (u8, int_id, assign),
+ (tonemaps_t*, tms, assign),
+ (cp_msg_vs_get_tonemap_tmi_t, tmi, assign))
+__mr (cp_msg_vs_get_tonemap_req_receive,
+ (mac_t, mac_addr, assign),
+ (cp_msg_vs_get_tonemap_tmi_t, tmi, assign),
+ (u8, int_id, assign),
+ (cp_msg_vs_get_tonemap_req_dir_t, dir, assign))
+
+__ms (cp_msg_vs_get_link_stats_cnf_send,
+ (u8, ReqID, assign),
+ (cp_msg_vs_get_link_stats_cnf_result_t, result, assign),
+ (u32, Bad_CRC, assign))
+__mrd (cp_msg_vs_get_link_stats_req_receive, cp_msg_vs_get_link_stats_req_t,
+ (cp_msg_vs_get_link_stats_req_reqtype_t, ReqType, assign),
+ (u8, ReqID, assign),
+ (cp_nid_t, nid, assign),
+ (u8, lid, assign),
+ (cp_msg_vs_get_link_stats_req_tlflag_t, TLFlag, assign),
+ (cp_msg_vs_get_link_stats_req_mgmtflag_t, Mgmt_Flag, assign),
+ (mac_t, dasa, assign))
+
+__mr (cp_msg_imac_get_discover_list_req_receive)
+__mscb (cp_msg_imac_get_discover_list_cnf_send_begin,
+ (const cp_msg_imac_get_discover_list_cnf_result_t, result, assign),
+ (const u8, version, assign),
+ (const u8, num_stations, assign))
+__msdc (cp_msg_imac_get_discover_list_cnf_send,
+ cp_msg_imac_discover_list_sta_info_t,
+ (mac_t, mac, assign),
+ (u8, ble_tx, assign),
+ (u8, ble_rx, assign))
+__msc (cp_msg_imac_get_discover_list_cnf_send_end)
+
+__mr (cp_msg_cm_sta_cap_req_receive)
+__msd (cp_msg_cm_sta_cap_cnf_send, cp_msg_cm_sta_cap_cnf_t,
+ (u8, av_version, assign),
+ (mac_t, mac, assign),
+ (uint, oui, assign),
+ (u8, auto_connect, assign),
+ (u8, smoothing, assign),
+ (u8, cco_cap, assign),
+ (u8, proxy_cap, assign),
+ (u8, backup_cco_cap, assign),
+ (u8, soft_handover, assign),
+ (u8, two_sym_fc, assign),
+ (u16, max_fl_av, assign),
+ (u8, homeplug_11_cap, assign),
+ (u8, homeplug_101_int, assign),
+ (u8, regulatory_cap, assign),
+ (u8, bidir_burst, assign),
+ (u16, implementation_version, assign))
+
+__msd (cp_msg_vs_get_snr_cnf_send, cp_msg_vs_get_snr_cnf_t,
+ (cp_msg_vs_get_snr_cnf_result_t, result, assign),
+ (u8, int_id, assign),
+ (uint, intervals_nb, assign),
+ (tonemap_intervals_t*, intervals, assign),
+ (u16, tm_ber, assign),
+ (u8, carrier_gr, assign),
+ (u32*, (snr, 768), array))
+__mr (cp_msg_vs_get_snr_req_receive,
+ (mac_t, mac_addr, assign),
+ (cp_msg_vs_get_snr_req_int_t, tm_int_i, assign),
+ (u8, int_id, assign),
+ (u8, carrier_gr, assign))
+
+__ms (cp_msg_drv_sta_set_u_sta_hfid_ind_send,
+ (const char *, u_sta_hfid, string))
+__ms (cp_msg_drv_sta_set_avln_hfid_ind_send,
+ (const char *, avln_hfid, string))
+
+__mr (cp_msg_vs_get_ce_stats_req_receive,
+ (mac_t, mac, assign))
+__ms (cp_msg_vs_get_ce_stats_cnf_send,
+ (u8, version, assign),
+ (u8, result, assign),
+ (sta_t *, sta, assign),
+ (tonemask_info_t *, ti, assign))
+
+__mr (cp_msg_vs_get_pb_stats_req_receive,
+ (cp_tei_t, stei_filter, assign))
+__mscb (cp_msg_vs_get_pb_stats_cnf_send_begin,
+ (int, nb_measures, assign))
+__msc (cp_msg_vs_get_pb_stats_cnf_send_measure,
+ (int, start_to_read, assign),
+ (int, nb_entries, assign))
+__msc (cp_msg_vs_get_pb_stats_cnf_send_end)
diff --git a/cesar/cp/av/sta/action/test/utest/src/poweron.c b/cesar/cp/av/sta/action/test/utest/src/poweron.c
new file mode 100644
index 0000000000..49df7066d9
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/poweron.c
@@ -0,0 +1,765 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/poweron.c
+ * \brief Test sta/action/poweron.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "cp/sta/action/action.h"
+#include "inc/test_sta_action.h"
+
+void
+poweron_test_cases (test_t t)
+{
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ cp_t *cp = &ctx.cp;
+ scenario_globals_t globals = {
+ .cp = cp,
+ };
+ cp_nid_t nid = 0x111111111111ull;
+ cp_net_t *net = NULL;
+ cp_sta_t *sta = NULL;
+ bsu_beacon_t beacon;
+ test_sta_action_beacon_create (&beacon, nid, 0, 1, 0);
+ /* Poweron start. */
+ test_case_begin (t, "poweron start");
+ test_sta_action_reset (&ctx);
+ cp_av_sta_action_init (cp);
+
+ test_begin (t, "start")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron_start),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_poweron),
+ SCENARIO_ACTION (poweron__idle__to_poweron),
+ SCENARIO_EVENT (cp_beacon_reconfigure_timer),
+ SCENARIO_EVENT (sar_activate, .flag = true),
+ SCENARIO_EVENT (pbproc_activate, .flag = true),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* POWERON timers. */
+ test_case_begin (t, "poweron");
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_set_was_cco (cp, false);
+ test_begin (t, "timer was not cco")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_BEACON_SCAN_MIN_MS,
+ .delay_max_ms = CP_BEACON_SCAN_MAX_MS),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_USTA_IND_INTERVAL_MS / 2,
+ .delay_max_ms = CP_USTA_IND_INTERVAL_MS * 3 / 2),
+ SCENARIO_ACTION (poweron__poweron__leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ cp_sta_own_data_set_was_cco (cp, true);
+ test_begin (t, "timer was cco")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_CCO_BEACON_SCAN_MIN_MS,
+ .delay_max_ms = CP_CCO_BEACON_SCAN_MAX_MS),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_USTA_IND_INTERVAL_MS / 2,
+ .delay_max_ms = CP_USTA_IND_INTERVAL_MS * 3 / 2),
+ SCENARIO_ACTION (poweron__poweron__leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* USTA timer. */
+ test_case_begin (t, "usta");
+ test_sta_action_reset (&ctx);
+ test_begin (t, "timer")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__usta__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_DISCOVER_PERIOD_MAX_MS / 2,
+ .delay_max_ms = CP_DISCOVER_PERIOD_MAX_MS * 3 / 2),
+ SCENARIO_ACTION (poweron__usta__leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* USTT timeout. */
+ test_case_begin (t, "poweron-usta ustt");
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_set_nid (cp, nid);
+ /* Without any other AVLN. */
+ test_begin (t, "no avln")
+ {
+ scenario_entry_t entries[] = {
+ /* POWERON. */
+ SCENARIO_ACTION (poweron__poweron__ustt_timeout),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_send,
+ .peer = CP_MME_PEER (MAC_BROADCAST,
+ MAC_TEI_UNASSOCIATED),
+ .nid = nid, .cco_cap = CP_CCO_LEVEL),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_USTA_IND_INTERVAL_MS / 2,
+ .delay_max_ms = CP_USTA_IND_INTERVAL_MS * 3 / 2),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta__ustt_timeout),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_send,
+ .peer = CP_MME_PEER (MAC_BROADCAST,
+ MAC_TEI_UNASSOCIATED),
+ .nid = nid, .cco_cap = CP_CCO_LEVEL),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_DISCOVER_PERIOD_MAX_MS / 2,
+ .delay_max_ms = CP_DISCOVER_PERIOD_MAX_MS * 3 / 2),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* With other AVLN. */
+ test_begin (t, "avln")
+ {
+ cp_sta_mgr_add_avln (cp, 1, 0x111111111111ull);
+ scenario_entry_t entries[] = {
+ /* POWERON. */
+ SCENARIO_ACTION (poweron__poweron__ustt_timeout),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_send,
+ .peer = CP_MME_PEER (MAC_BROADCAST,
+ MAC_TEI_UNASSOCIATED),
+ .nid = nid, .cco_cap = CP_CCO_LEVEL),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_USTA_IND_INTERVAL_MS / 2,
+ .delay_max_ms = CP_USTA_IND_INTERVAL_MS * 3 / 2),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta__ustt_timeout),
+ SCENARIO_EVENT (cp_msg_cm_unassociated_sta_ind_send,
+ .peer = CP_MME_PEER (MAC_BROADCAST,
+ MAC_TEI_UNASSOCIATED),
+ .nid = nid, .cco_cap = CP_CCO_LEVEL),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_DISCOVER_PERIOD_MAX_MS / 2,
+ .delay_max_ms = CP_DISCOVER_PERIOD_MAX_MS * 3 / 2),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Beacon. */
+ test_case_begin (t, "poweron-usta beacon");
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_set_nid (cp, nid);
+ /* NID do not match. */
+ test_begin (t, "no nid match")
+ {
+ net = cp_sta_mgr_add_avln (cp, 2, nid + 1);
+ sta = cp_sta_mgr_sta_add (cp, net, 1, 0x112233445566ull);
+ cp_net_set_cco (cp, net, 1);
+ test_sta_action_beacon_create (&beacon, cp_net_get_nid (cp, net),
+ cp_net_get_snid (cp, net),
+ cp_sta_get_tei (sta),
+ cp_sta_get_mac_address (sta));
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ /* POWERON. */
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ /* No tracking change, already done. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+ test_fail_unless (own_data->nid_track == nid + 1);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == 2);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ } test_end;
+ /* NID do match, not CCo. */
+ test_begin (t, "nid match no cco")
+ {
+ net = cp_sta_mgr_add_avln (cp, 1, nid);
+ sta = cp_sta_mgr_sta_add (cp, net, 1, 0x0123456789abull);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ /* POWERON. */
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+ test_fail_unless (own_data->nid_track == nid + 1);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == 2);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ } test_end;
+ /* NID do match. */
+ test_begin (t, "nid match cco")
+ {
+ cp_net_set_cco (cp, net, 1);
+ cp_sta_t *cco = cp_net_get_cco (cp, net);
+ test_sta_action_beacon_create (&beacon, cp_net_get_nid (cp, net),
+ cp_net_get_snid (cp, net),
+ cp_sta_get_tei (cco),
+ cp_sta_get_mac_address (cco));
+ slab_release (cco);
+ scenario_entry_t entries[] = {
+ /* POWERON SPOC not updated. */
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ /* POWERON SPOC updated. */
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ nid_match)),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ /* No tracking change, already done. */
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, BEACON,
+ no_nid_match)),
+ /* USTA SPOC updated. */
+ SCENARIO_ACTION (poweron__usta__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ /* No tracking change, already done. */
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_assoc),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, BEACON,
+ nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+ test_fail_unless (own_data->nid_track == nid);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == 1);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ test_sta_action_reset (&ctx);
+ } test_end;
+ /* NID do match but snid do not. */
+ test_begin (t, "nid match cco, snid don't")
+ {
+ cp_snid_t snid = 1;
+ cp_snid_t other_snid = 2;
+
+ cp_net_t *net = cp_sta_mgr_add_avln (cp, snid, nid);
+ cp_sta_t *sta = cp_sta_mgr_sta_add (cp, net, 1, 0x0123456789abull);
+
+ cp_net_t *other_net = cp_sta_mgr_add_avln (cp, other_snid, nid);
+ cp_sta_t *other_sta = cp_sta_mgr_sta_add (cp, other_net, 1,
+ 0x112233445576ull);
+
+ cp_net_set_cco (cp, net, 1);
+ cp_net_set_cco (cp, other_net, 1);
+ cp_sta_own_data_set_nid (cp, nid);
+
+ slab_release (sta);
+ slab_release (other_sta);
+
+ scenario_entry_t entries[] = {
+ /* POWERON SPOC not updated. */
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ /* other net and cco. */
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = other_net, .sta = other_sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta__beacon, .beacon = &beacon,
+ .net = other_net, .sta = other_sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+ test_fail_unless (own_data->nid_track == nid);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == snid);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ } test_end;
+ /* BTT timeout. */
+ test_case_begin (t, "poweron btt");
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_set_nid (cp, nid);
+ cp_sta_own_data_set_mac_address (cp, 0x112233445566ull);
+ test_begin (t, "no avln")
+ {
+ /* No AVLN. */
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_av_cco_action_ucco_start),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ no_avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* AVLN no NID match. */
+ test_begin (t, "no nid match")
+ {
+ net = cp_sta_mgr_add_avln (cp, 3, nid + 1);
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x0123456789abull);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_av_cco_action_ucco_start),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ no_avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* AVLN NID match, not CCo. */
+ test_begin (t, "not cco")
+ {
+ /* Because of CCo cap. */
+ net = cp_sta_mgr_add_avln (cp, 1, nid);
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x012345678901ull);
+ sta->cco_cap = 3;
+ slab_release (sta);
+ scenario_entry_t entries0[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries0, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x012345678901ull);
+ /* Because of CCo MAC address. */
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x0123456789abull);
+ sta->cco_cap = CP_CCO_LEVEL;
+ slab_release (sta);
+ scenario_entry_t entries1[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries1, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x0123456789abull);
+ } test_end;
+ /* AVLN NID match, CCo. */
+ test_begin (t, "cco")
+ {
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x012345678901ull);
+ sta->cco_cap = CP_CCO_LEVEL;
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_av_cco_action_cco__unassoc_start),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ nid_match_cco)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x012345678901ull);
+ } test_end;
+ /* AVLN NID match, CCo authenticated. */
+ test_begin (t, "cco authenticated")
+ {
+ sta = cp_sta_mgr_sta_add (cp, net, 1, 0x012345678901ull);
+ cp_net_set_cco (cp, net, 1);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x012345678901ull);
+ } test_end;
+ /* AVLN NID match, Sta associated. */
+ test_begin (t, "Sta associated")
+ {
+ sta = cp_sta_mgr_sta_add (cp, net, 1, 0x012345678901ull);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__btt_timeout),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, btt_timeout,
+ avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x012345678901ull);
+ } test_end;
+ /* USTA indication. */
+ test_case_begin (t, "usta usta ind");
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_set_nid (cp, nid);
+ cp_sta_own_data_set_mac_address (cp, 0x112233445566ull);
+ /* NID do not match. */
+ test_begin (t, "no nid match")
+ {
+ net = cp_sta_mgr_add_avln (cp, 3, nid + 1);
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x0123456789abull);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__usta__usta_ind, .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, usta_ind, else)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Not CCo. */
+ test_begin (t, "not cco")
+ {
+ /* Because of CCo cap. */
+ net = cp_sta_mgr_add_avln (cp, 1, nid);
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x012345678901ull);
+ sta->cco_cap = 3;
+ slab_release (sta);
+ scenario_entry_t entries0[] = {
+ SCENARIO_ACTION (poweron__usta__usta_ind, .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, usta_ind, else)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries0, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x012345678901ull);
+ /* Because of CCo MAC address. */
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x0123456789abull);
+ sta->cco_cap = CP_CCO_LEVEL;
+ slab_release (sta);
+ scenario_entry_t entries1[] = {
+ SCENARIO_ACTION (poweron__usta__usta_ind, .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, usta_ind, else)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries1, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x0123456789abull);
+ } test_end;
+ /* CCo. */
+ test_begin (t, "cco")
+ {
+ sta = cp_sta_mgr_sta_add (cp, net, 0, 0x012345678901ull);
+ sta->cco_cap = CP_CCO_LEVEL;
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__usta__usta_ind, .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_av_cco_action_cco__unassoc_start),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (USTA, usta_ind,
+ nid_match_cco)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_mgr_sta_remove_from_mac (cp, 0x012345678901ull);
+ } test_end;
+ /* POWERON, USTA JOINING. */
+ test_case_begin (t, "poweron-usta joining");
+ test_sta_action_reset (&ctx);
+ /* Association failure. */
+ test_begin (t, "unassociated")
+ {
+ scenario_entry_t entries[] = {
+ /* POWERON. */
+ SCENARIO_ACTION (poweron__poweron_joining__left),
+ /* USTA. */
+ SCENARIO_ACTION (poweron__usta_joining__left),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* Stopped during association. */
+ test_begin (t, "stop")
+ {
+ scenario_entry_t entries[] = {
+ /* POWERON. */
+ SCENARIO_ACTION (poweron_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ SCENARIO_ACTION (poweron__joining__to_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_leave),
+ SCENARIO_ACTION (poweron__many__to_idle),
+ SCENARIO_EVENT (pbproc_activate, .flag = false),
+ SCENARIO_EVENT (sar_activate, .flag = false),
+ SCENARIO_EVENT (sar_cleanup),
+ SCENARIO_EVENT (cp_beacon_deactivate),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_stopped),
+ /* USTA. */
+ SCENARIO_ACTION (poweron_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ SCENARIO_ACTION (poweron__joining__to_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_leave),
+ SCENARIO_ACTION (poweron__many__to_idle),
+ SCENARIO_EVENT (pbproc_activate, .flag = false),
+ SCENARIO_EVENT (sar_activate, .flag = false),
+ SCENARIO_EVENT (sar_cleanup),
+ SCENARIO_EVENT (cp_beacon_deactivate),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_stopped),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* UCCO. */
+ test_case_begin (t, "ucco");
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_set_nid (cp, nid);
+ test_begin (t, "assoc_cco enter")
+ {
+ cp_sta_t *other_cco;
+ net = cp_sta_mgr_add_avln (cp, 3, nid + 1);
+ other_cco = cp_sta_mgr_sta_add (cp, net, 1, 0x334455667788ull);
+ slab_release (other_cco);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron_cco__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_DISCOVER_PERIOD_MAX_MS,
+ .delay_max_ms = CP_DISCOVER_PERIOD_MAX_MS),
+ SCENARIO_ACTION (poweron__ucco__beacon, .beacon = &beacon,
+ .net = net, .sta = other_cco),
+ SCENARIO_EVENT (cp_av_cco_action_ucco_stop),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (UCCO, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* STA. */
+ test_case_begin (t, "sta");
+ test_sta_action_reset (&ctx);
+ test_begin (t, "stop")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ SCENARIO_ACTION (poweron__sta__to_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_leave),
+ /* Next actions tested yet... */
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ /* CCO. */
+ test_case_begin (t, "cco");
+ test_sta_action_reset (&ctx);
+ test_begin (t, "join timeout sta")
+ {
+ test_sta_action_create_our_net (&ctx, nid, 1);
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (cp);
+ sta = cp_sta_mgr_sta_add (cp, our_net, 1, 0x112233445566ull);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ /* Test timer here. */
+ SCENARIO_ACTION (poweron_cco__enter),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = CP_DISCOVER_PERIOD_MAX_MS,
+ .delay_max_ms = CP_DISCOVER_PERIOD_MAX_MS),
+ SCENARIO_ACTION (poweron__cco__join_timeout),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (CCO, join_timeout,
+ sta)),
+ SCENARIO_ACTION (poweron_cco__leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_mgr_sta_remove_assoc (cp, our_net, 1);
+ } test_end;
+ test_begin (t, "join timeout no sta no avln")
+ {
+ test_sta_action_create_our_net (&ctx, nid, 1);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__cco__join_timeout),
+ SCENARIO_EVENT (cp_av_cco_action_cco__to_ucco),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (CCO, join_timeout,
+ no_sta_no_avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "join timeout no sta avln")
+ {
+ test_sta_action_create_our_net (&ctx, nid, 1);
+ cp_sta_mgr_add_avln (cp, 2, 0x222222222222ull);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__cco__join_timeout),
+ SCENARIO_EVENT (cp_av_cco_action_cco__unassoc_stop),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (CCO, join_timeout,
+ no_sta_avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ cp_sta_mgr_remove_avln (cp, 2, 0x222222222222ull);
+ } test_end;
+ test_begin (t, "stop")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron_stop),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_stop),
+ /* Handled by cco/action which generates a left event. */
+ /* Next actions tested yet... */
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ test_begin (t, "Current tracked AVLN does not exists")
+ {
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+ own_data->nid_track = 30;
+ own_data->tei_track = 245;
+ net = cp_sta_mgr_add_avln (cp, 2, nid);
+ sta = cp_sta_mgr_sta_add (cp, net, 1, 0x112233445566ull);
+ cp_net_set_cco (cp, net, 1);
+ cp_sta_own_data_set_nid (cp, nid);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (own_data->nid_track == nid);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == 2);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ }
+ test_end;
+ test_begin (t, "Current tracked AVLN is blacklisted")
+ {
+ test_sta_action_reset (&ctx);
+ cp_sta_own_data_t *own_data = cp_sta_mgr_get_sta_own_data (cp);
+ own_data->nid_track = 30;
+ own_data->tei_track = 245;
+ net = cp_sta_mgr_add_avln (cp, 0, nid);
+ net->blacklisted = true;
+ net = cp_sta_mgr_add_avln (cp, 2, nid);
+ sta = cp_sta_mgr_sta_add (cp, net, 1, 0x112233445566ull);
+ cp_net_set_cco (cp, net, 1);
+ cp_sta_own_data_set_nid (cp, nid);
+ slab_release (sta);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (own_data->nid_track == nid);
+ test_fail_unless (own_data->tei_track == 1);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == 2);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ /* Only the TEI tracked has changed. */
+ own_data->tei_track = 10;
+ scenario_entry_t entries2[] = {
+ SCENARIO_ACTION (poweron__poweron__beacon, .beacon = &beacon,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (POWERON, BEACON,
+ no_nid_match)),
+ SCENARIO_END
+ };
+ scenario_run (t, entries2, &globals);
+ test_fail_unless (own_data->nid_track == nid);
+ test_fail_unless (own_data->tei_track == 1);
+ test_fail_unless (cp_sta_own_data_get_snid (cp) == 2);
+ test_fail_unless (cp_sta_own_data_get_nid (cp) == nid);
+ }
+ test_end;
+ /* Cleanup. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+poweron_test_suite (test_t t)
+{
+ test_suite_begin (t, "poweron");
+ poweron_test_cases (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/sc.c b/cesar/cp/av/sta/action/test/utest/src/sc.c
new file mode 100644
index 0000000000..6bc83a5ceb
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/sc.c
@@ -0,0 +1,1815 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/sc.c
+ * \brief Simple connect procedure test.
+ * \ingroup test
+ *
+ * Test the Simple Connect procedure.
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_sta_action.h"
+
+#include "cp/av/sta/action/sc.h"
+
+void
+sc_basic_test_cases (test_t t)
+{
+ /* Initialize test context. */
+ test_sta_action_t ctx;
+ test_sta_action_init (&ctx);
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ /* Configure my MAC address. */
+ const mac_t my_mac = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x01);
+ cp_sta_own_data_set_mac_address (&ctx.cp, my_mac);
+ const mac_t sc_add_mac = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x02);
+ const mac_t sc_add_mac2 = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x04);
+ const mac_t sc_join_mac = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x03);
+ const cp_nid_t nid = 0xF11111111111ull;
+ cp_mme_peer_t all_sta = CP_MME_PEER (MAC_BROADCAST,
+ MAC_TEI_UNASSOCIATED);
+
+ const uint sc_periodic_sc_join_req_bcast_ms_min = 750;
+ const uint sc_periodic_sc_join_req_bcast_ms_max = 1250;
+
+ uint second_hash_key[] = {
+ 0xfcfdfeff, 0xf8f9fafb, 0xf4f5f6f7, 0xf0f1f2f3, 0xecedeeef,
+ 0xe8e9eaeb, 0xe4e5e6e7, 0xe0e1e2e3, 0xdcdddedf, 0xd8d9dadb,
+ 0xd4d5d6d7, 0xd0d1d2d3, 0xcccdcecf, 0xc8c9cacb, 0xc4c5c6c7,
+ 0xc0c1c2c3, 0xbcbdbebf, 0xb8b9babb, 0xb4b5b6b7, 0xb0b1b2b3,
+ 0xacadaeaf, 0xa8a9aaab, 0xa4a5a6a7, 0xa0a1a2a3, 0x9c9d9e9f,
+ 0x98999a9b, 0x94959697, 0x90919293, 0x8c8d8e8f, 0x88898a8b,
+ 0x84858687, 0x80818283, 0x7c7d7e7f, 0x78797a7b, 0x74757677,
+ 0x70717273, 0x6c6d6e6f, 0x68696a6b, 0x64656667, 0x60616263,
+ 0x5c5d5e5f, 0x58595a5b, 0x54555657, 0x50515253, 0x4c4d4e4f,
+ 0x48494a4b, 0x44454647, 0x40414243, 0x3c3d3e3f, 0x38393a3b,
+ 0x34353637, 0x30313233, 0x2c2d2e2f, 0x28292a2b, 0x24252627,
+ 0x20212223, 0x1c1d1e1f, 0x18191a1b, 0x14151617, 0x10111213,
+ 0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203, 0xfcfdfeff,
+ 0xf8f9fafb, 0xf4f5f6f7, 0xf0f1f2f3, 0xecedeeef, 0xe8e9eaeb,
+ 0xe4e5e6e7, 0xe0e1e2e3, 0xdcdddedf, 0xd8d9dadb, 0xd4d5d6d7,
+ 0xd0d1d2d3, 0xcccdcecf, 0xc8c9cacb, 0xc4c5c6c7, 0xc0c1c2c3,
+ 0xbcbdbebf, 0xb8b9babb, 0xb4b5b6b7, 0xb0b1b2b3, 0xacadaeaf,
+ 0xa8a9aaab, 0xa4a5a6a7, 0xa0a1a2a3, 0x9c9d9e9f, 0x98999a9b,
+ 0x94959697, 0x90919293, 0x8c8d8e8f, 0x88898a8b, 0x84858687, 0x80818283
+ };
+ cp_key_t nmk = { {0x1, 0x2, 0x3, 0x4} };
+ ctx.cp.sta_mgr.sta_own_data.nmk = nmk;
+
+ /* Start SC test. */
+ test_case_begin (t, "sc join");
+
+ /* Start of an SC join procedure. */
+ scenario_entry_t start_sc_join[] =
+ {
+ /* Action function to call when we start an SC procedure. */
+ SCENARIO_ACTION (sc__start_sc_join),
+ /* Call to post event to make the SC FSM start. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_join),
+ /* Leave SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__leave),
+ /* Create SC timeout procedure. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 30000,
+ .delay_max_ms = 30000),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = true),
+ /* Enter SC_JOIN with no transition. */
+ /* Execute entering SC_JOIN enter function. */
+ SCENARIO_ACTION (sc__sc_join__enter),
+ /* Start JOIN_REQ timer. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_join_req_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* Send SC_JOIN.REQ to all STA. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_send,
+ .peer = all_sta),
+ SCENARIO_END
+ };
+
+
+ /* Test an SC join procedure with timeout for periodic SC_JOIN.REQ
+ * broadcast . */
+ test_begin (t, "periodic broadcast of SC_JOIN.REQ")
+ {
+ /* Run start of SC join procedure. */
+ scenario_entry_t entries[] = {
+ SCENARIO_SUB (start_sc_join),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ /* Simulate many timeout and broadcast of SC_JOIN.REQ. */
+ uint count;
+ for (count = 0; count < 30; count++)
+ {
+ scenario_entry_t sc_join_req_timeout[] = {
+ SCENARIO_ACTION (sc__sc_join__sc_join_req_timeout),
+ /* Start JOIN_REQ timer. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_join_req_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* Send SC_JOIN.REQ to all STA. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_send,
+ .peer = all_sta),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_req_timeout, &globals);
+ }
+ } test_end;
+
+ test_begin (t, "failure in SC_CCO: no other sta")
+ {
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ scenario_entry_t sc_main_timeout[] = {
+ /* First, execute transition. */
+ SCENARIO_ACTION (sc__sc_cco__sc_failed),
+ /* Quit CCo role. */
+ SCENARIO_EVENT (cp_av_cco_action_cco__to_ucco),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_CCO, sc_failed,
+ no_sta_no_avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_main_timeout, &globals);
+ } test_end;
+
+ test_begin (t, "failure in SC_CCO: one sta not in our net")
+ {
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ /* Another net. */
+ cp_net_t *other_net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ /* A station. */
+ cp_sta_t *a_sta = cp_sta_mgr_sta_add (&ctx.cp, other_net, 1,
+ sc_add_mac);
+ scenario_entry_t sc_main_timeout[] = {
+ /* First, execute transition. */
+ SCENARIO_ACTION (sc__sc_cco__sc_failed),
+ SCENARIO_EVENT (cp_av_cco_action_cco__unassoc_stop),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_CCO, sc_failed,
+ no_sta_avln)),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_main_timeout, &globals);
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, a_sta);
+ slab_release (a_sta);
+ } test_end;
+
+ test_begin (t, "failure in SC_CCO: one sta in our net")
+ {
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* A station in our net. */
+ cp_sta_t *a_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 2,
+ sc_add_mac);
+ scenario_entry_t sc_main_timeout[] = {
+ /* First, execute transition. */
+ SCENARIO_ACTION (sc__sc_cco__sc_failed),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_CCO, sc_failed,
+ sta)),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_main_timeout, &globals);
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, a_sta);
+ slab_release (a_sta);
+ } test_end;
+
+ /* Timeout of the whole SC procedure not in SC_ADD. */
+ test_begin (t, "timeout of SC procedure (not in SC_ADD)")
+ {
+ /* No answer, main timeout of SC join procedure occurs. */
+ scenario_entry_t sc_main_timeout[] = {
+ /* First, execute transition. */
+ SCENARIO_ACTION (sc__sc_timeout),
+ /* Tell CP FSM we failed. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_failed),
+ /* Second, leave the SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop SC join timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Last, enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_main_timeout, &globals);
+ } test_end;
+
+ /* Timeout of the whole SC procedure in SC_ADD. */
+ test_begin (t, "timeout of SC procedure (in SC_ADD)")
+ {
+ /* No answer, main timeout of SC join procedure occurs. */
+ scenario_entry_t sc_main_timeout[] = {
+ /* First, execute transition. */
+ SCENARIO_ACTION (sc_add__sc_timeout),
+ /* Tell CP FSM we failed. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_failed),
+ /* Second, leave the SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop SC join timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Last, enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_main_timeout, &globals);
+ } test_end;
+
+ /* Test SC join procedure with a STA replying with an SC_JOIN.CNF. */
+ test_begin (t, "SC_JOIN.CNF received from unassociated STA, decoding"
+ " failed")
+ {
+ /* A STA in SC add. */
+ cp_mme_peer_t sc_add_sta = CP_MME_PEER (sc_add_mac, 0);
+ /* STA replies to SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.CNF. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_cnf, .peer = sc_add_sta),
+ /* Decode failure. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_receive, .ok = false,
+ .nid = 0x00, .avln_status = false, .cco_cap = 0,
+ .pco_cap = false, .backup_cco_cap = false,
+ .cco_status = false, .pco_status = false,
+ .backup_cco_status = false),
+ /* Failed, go to SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_CNF,
+ nok)),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ } test_end;
+
+ test_begin (t, "SC_JOIN.CNF received from unassociated STA")
+ {
+ /* Some initialisation for the scenario. */
+ /* False beacon. */
+ bsu_beacon_t beacon;
+ bsu_beacon_t beacon_other_net;
+ /* Reset tracking. */
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ own->tei_track = own->cco_mac_addr_track = own->nid_track = 0;
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ cp_net_t *other_net = cp_sta_mgr_add_avln (&ctx.cp, 0, 1);
+ cp_net_t *other_net2 = cp_sta_mgr_add_avln (&ctx.cp, 1, nid);
+ /* A STA in SC add. */
+ cp_mme_peer_t sc_add_peer = CP_MME_PEER (sc_add_mac, 1);
+ cp_sta_t *sc_add_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 1,
+ sc_add_mac);
+ cp_sta_t *sc_add_sta2 = cp_sta_mgr_sta_add (&ctx.cp, other_net2, 1,
+ sc_add_mac2);
+ cp_net_set_cco (&ctx.cp, net, 1);
+ cp_net_set_cco (&ctx.cp, other_net2, 1);
+ cp_sta_t *cco = cp_net_get_cco (&ctx.cp, net);
+ own->tei_track = own->cco_mac_addr_track = own->nid_track = 0;
+ test_sta_action_beacon_create (
+ &beacon, cp_net_get_nid (&ctx.cp, net),
+ cp_net_get_snid (&ctx.cp, net), cp_sta_get_tei (cco),
+ cp_sta_get_mac_address (cco));
+ slab_release (cco);
+ test_sta_action_beacon_create (
+ &beacon_other_net, cp_net_get_nid (&ctx.cp, other_net),
+ cp_net_get_snid (&ctx.cp, other_net), 1, 1);
+ /* STA replies to SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.CNF. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_cnf, .peer = sc_add_peer),
+ /* Decode success. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_receive, .ok = true,
+ .nid = nid, .avln_status = false, .cco_cap = 0,
+ .pco_cap = false, .backup_cco_cap = false,
+ .cco_status = false, .pco_status = false,
+ .backup_cco_status = false),
+ /* Ok, we have finished for this state. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_CNF,
+ ok)),
+ /* Check nid has been setup correctly. */
+ SCENARIO_ACTION (sc__check_nid_set, .nid = nid),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_WAIT_BEACON. */
+ /* Nothing to do. */
+ /* A beacon has arrived. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon_other_net,
+ .net = other_net,
+ .sta = sc_add_sta),
+ /* Track it. */
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon =
+ &beacon_other_net, .net = other_net),
+ /* Beacon is wrong, nid differs. */
+ /* Stay in SC_WAIT_BEACON. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_differs)),
+ /* A second beacon has arrived. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = net,
+ .sta = sc_add_sta),
+ /* Beacon is ok, SPOC is not updated, do not start assoc. */
+ /* Track it. */
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_differs)),
+ /* A third beacon has arrived. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = other_net2,
+ .sta = sc_add_sta2),
+ /* Beacon is not ok, snid is wrong. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_differs)),
+ /* Beacon is ok, start assoc. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = net,
+ .sta = sc_add_sta),
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ /* Trigger SC assoc. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_sc_assoc),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Leave SC_WAIT_BEACON for SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_match)),
+ /* Enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC assoc start. */
+ SCENARIO_ACTION (sc__check_sc_assoc_start, .sc_peer = &sc_add_peer,
+ .cco_peer = &sc_add_peer, .net = net),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_add_sta);
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_add_sta2);
+ slab_release (sc_add_sta);
+ slab_release (sc_add_sta2);
+ } test_end;
+
+ /* SC_JOIN with associated STA. */
+ test_begin (t, "SC_JOIN.CNF received from associated STA")
+ {
+ /* Some initialisations for the scenario. */
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* A STA in SC add. */
+ cp_mme_peer_t sc_add_peer = CP_MME_PEER (sc_add_mac, 0);
+ cp_sta_t *sc_add_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 0,
+ sc_add_mac);
+ /* Future CCo. */
+ cp_mme_peer_t sc_cco_peer = CP_MME_PEER (sc_add_mac, 1);
+ /* STA replies to SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.CNF. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_cnf, .peer = sc_add_peer),
+ /* Decode success. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_receive, .ok = true,
+ .nid = nid, .avln_status = true, .cco_cap = 0,
+ .pco_cap = false, .backup_cco_cap = false,
+ .cco_status = false, .pco_status = false,
+ .backup_cco_status = false),
+ /* Ok, we have finished for this state. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_CNF,
+ ok)),
+ /* Check nid has been setup correctly. */
+ SCENARIO_ACTION (sc__check_nid_set, .nid = nid),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC assoc start: the cco of the net is unknown. */
+ SCENARIO_ACTION (sc__check_sc_assoc_start, .sc_peer = &sc_add_peer,
+ .cco_peer = &sc_cco_peer, .net = net),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_add_sta);
+ slab_release (sc_add_sta);
+ } test_end;
+
+ /* SC_JOIN with SC_JOIN STA. */
+ test_begin (t, "SC_JOIN.REQ received, decode error.")
+ {
+ /* Some initialisations for the scenario. */
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ /* STA replies to SC.JOIN.REQ with SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.REQ. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_req, .peer = sc_join_peer),
+ /* Decode error. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = false,
+ .cco_cap = 0),
+ /* Nothing to do, stop here. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_REQ,
+ nok)),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ } test_end;
+
+ /* SC_JOIN with SC_JOIN STA. */
+ test_begin (t, "SC_JOIN.REQ received, our CCo capabilities lower.")
+ {
+ /* Some initialisations for the scenario. */
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ /* STA replies to SC.JOIN.REQ with SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.REQ. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_req, .peer = sc_join_peer),
+ /* Decode ok. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 1),
+ /* Nothing to do, stop here, because our CCo cap are lower. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_REQ,
+ ok_my_cco_cap_lower)),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ } test_end;
+
+ /* SC_JOIN with SC_JOIN STA. */
+ test_begin (t, "SC_JOIN.REQ received, CCo cap equal, our mac lower.")
+ {
+ /* Some initialisations for the scenario. */
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ /* STA replies to SC.JOIN.REQ with SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.REQ. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_req, .peer = sc_join_peer),
+ /* Decode ok. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 0),
+ /* Nothing to do, stop here, because our CCo cap are equals and
+ * our mac is lower. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_REQ,
+ ok_my_cco_cap_lower)),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ } test_end;
+
+ /* SC_JOIN with SC_JOIN STA. */
+ test_begin (t, "SC_JOIN.REQ received, CCo cap equals, MAC address greater.")
+ {
+ /* Some initialisations for the scenario. */
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ /* Our net. */
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ cp_sta_t *sc_join_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 0,
+ sc_join_mac);
+ /* Setup our MAC to something higher than the peer. */
+ cp_sta_own_data_set_mac_address
+ (&ctx.cp, MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x42, 0x01));
+ /* STA replies to SC.JOIN.REQ with SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.REQ. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_req, .peer = sc_join_peer),
+ /* Decode is ok. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 0),
+ /* Our CCo cap are greater, let's become CCo. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_get_cco_functionality),
+ /* Send the SC_JOIN.CNF. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_send,
+ .peer = sc_join_peer, .nid = nid,
+ .avln_status = false, .cco_cap = CP_CCO_LEVEL,
+ .pco_cap = CP_PCO_CAP,
+ .backup_cco_cap = CP_BACKUP_CCO_CAP,
+ .cco_status = true, .pco_status = false,
+ .backup_cco_status = false),
+ /* End of this state, go to SC_WAIT_PEER_ASSOCIATED. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_REQ,
+ ok_my_cco_cap_greater)),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop SC join timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_join_sta);
+ slab_release (sc_join_sta);
+ cp_sta_own_data_set_mac_address (&ctx.cp, my_mac);
+
+ } test_end;
+
+ /* SC_JOIN with SC_JOIN STA. */
+ test_begin (t, "SC_JOIN.REQ received, going to SC_ADD and doing the wole procedure.")
+ {
+ /* Some initialisations for the scenario. */
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ /* Our net. */
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ cp_sta_t *sc_join_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 0,
+ sc_join_mac);
+ /* Setup our MAC to something higher than the peer. */
+ cp_sta_own_data_set_mac_address (&ctx.cp, sc_join_mac + 1);
+ /* STA replies to SC.JOIN.REQ with SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* Run start of SC join procedure. */
+ SCENARIO_SUB (start_sc_join),
+ /* We receive a CM_SC_JOIN.REQ. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_req, .peer = sc_join_peer),
+ /* Decode is ok. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 0),
+ /* Our CCo cap are greater, let's become CCo. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_get_cco_functionality),
+ /* Send the SC_JOIN.CNF. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_send,
+ .peer = sc_join_peer, .nid = nid,
+ .avln_status = false, .cco_cap = CP_CCO_LEVEL,
+ .pco_cap = CP_PCO_CAP,
+ .backup_cco_cap = CP_BACKUP_CCO_CAP,
+ .cco_status = true, .pco_status = false,
+ .backup_cco_status = false),
+ /* End of this state, go to SC_WAIT_PEER_ASSOCIATED. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_REQ,
+ ok_my_cco_cap_greater)),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop SC join timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_WAIT_PEER_ASSOCIATED. */
+ SCENARIO_ACTION (sc__sc_wait_peer_associated__new_sta_associated,
+ .net = net, .sta = sc_join_sta),
+ /* Send the first hash key. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = sc_join_peer,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED,
+ .pid = 3, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid),
+ /* Wait for the second hash key to build the TEK. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_PEER_ASSOCIATED,
+ new_sta_associated,
+ sta_is_sc_peer)),
+ /* Entering SC_BUILDING_TEK. */
+ SCENARIO_ACTION (sc__sc_building_tek__cm_get_key_cnf_pid3,
+ .peer = sc_join_peer),
+ /* Decoding MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .pmn = 2, .pid = 3,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid,
+ .eks = CP_MME_PEKS_TEK_MIN + 1,
+ .hash_key = second_hash_key),
+ /* Send the NMK. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_send,
+ .peer = sc_join_peer,
+ .peks = CP_MME_PEKS_TEK_MIN + 1,
+ .pid = 3, .pmn = 3, .key_type = CP_MSG_KEY_NMK,
+ .cco_cap = CP_CCO_LEVEL,
+ .nid = nid, .new_eks = CP_MME_PEKS_NMK,
+ .new_key = nmk),
+ /* Go to SC_NMK_EXCHANGE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_BUILDING_TEK,
+ CM_GET_KEY_CNF_PID3,
+ ok)),
+ /* Enter SC_NMK_EXCHANGE. */
+ SCENARIO_ACTION (sc__sc_nmk_exchange__cm_set_key_cnf_pid3,
+ .peer = sc_join_peer),
+ /* Decode MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_receive, .ok = true,
+ .pmn = 0xFF, .pid = 3, .new_prn = false,
+ .new_my_nonce = false, .new_your_nonce = false,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = 0),
+ /* We have finished, tell it to the top FSM. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Go to SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_NMK_EXCHANGE,
+ CM_SET_KEY_CNF_PID3,
+ ok)),
+ /* Enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_join_sta);
+ slab_release (sc_join_sta);
+ cp_sta_own_data_set_mac_address (&ctx.cp, my_mac);
+
+ } test_end;
+
+
+ /* Start SC test. */
+ test_case_begin (t, "sc add");
+
+ /* SC_ADD STA. */
+ test_begin (t, "SC_ADD and doing the wole procedure.")
+ {
+ /* Some initialisations for the scenario. */
+ /* Our net. */
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* The SC_ADD sta. */
+ cp_sta_t *sc_join_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 0,
+ sc_join_mac);
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ /* Setup our MAC to something higher than the peer. */
+ cp_sta_own_data_set_mac_address (&ctx.cp, sc_join_mac + 1);
+
+ /* Start of an SC ADD procedure. */
+ scenario_entry_t sc_add[] =
+ {
+ /* Action function to call when we start an SC add procedure. */
+ SCENARIO_ACTION (sc__start_sc_add),
+ /* Call to post event to make the SC FSM start. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_add),
+ /* Leave SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__leave),
+ /* Create SC timeout procedure. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 30000,
+ .delay_max_ms = 30000),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = true),
+ /* Enter SC_ADD with no transition. */
+ /* The SC_JOIN STA transmits some CM_SC_JOIN.REQ. */
+ SCENARIO_ACTION (sc__sc_add__cm_sc_join_req, .peer = sc_join_peer),
+ /* Check the MME (we fake the join STA has greater cco_cap, this
+ * should be ignored). */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 1),
+ /* We need to become CCo. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_get_cco_functionality),
+ /* Send the SC_JOIN.CNF. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_send,
+ .peer = sc_join_peer, .nid = nid,
+ .avln_status = false, .cco_cap = CP_CCO_LEVEL,
+ .pco_cap = CP_PCO_CAP,
+ .backup_cco_cap = CP_BACKUP_CCO_CAP,
+ .cco_status = true, .pco_status = false,
+ .backup_cco_status = false),
+ /* Take the "ok" branch. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_ADD, CM_SC_JOIN_REQ,
+ ok)),
+ /* Go to SC_WAIT_PEER_ASSOCIATED. */
+ /* No leave/enter. */
+ /* Enter SC_WAIT_PEER_ASSOCIATED. */
+ SCENARIO_ACTION (sc__sc_wait_peer_associated__new_sta_associated,
+ .net = net, .sta = sc_join_sta),
+ /* Send the first hash key. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = sc_join_peer,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED,
+ .pid = 3, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid),
+ /* Wait for the second hash key to build the TEK. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_PEER_ASSOCIATED,
+ new_sta_associated,
+ sta_is_sc_peer)),
+ /* Entering SC_BUILDING_TEK. */
+ SCENARIO_ACTION (sc__sc_building_tek__cm_get_key_cnf_pid3,
+ .peer = sc_join_peer),
+ /* Decoding MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .pmn = 2, .pid = 3,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid,
+ .eks = CP_MME_PEKS_TEK_MIN + 2,
+ .hash_key = second_hash_key),
+ /* Send the NMK. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_send,
+ .peer = sc_join_peer,
+ .peks = CP_MME_PEKS_TEK_MIN + 2,
+ .pid = 3, .pmn = 3, .key_type = CP_MSG_KEY_NMK,
+ .cco_cap = CP_CCO_LEVEL,
+ .nid = nid, .new_eks = CP_MME_PEKS_NMK,
+ .new_key = nmk),
+ /* Go to SC_NMK_EXCHANGE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_BUILDING_TEK,
+ CM_GET_KEY_CNF_PID3,
+ ok)),
+ /* Enter SC_NMK_EXCHANGE. */
+ SCENARIO_ACTION (sc__sc_nmk_exchange__cm_set_key_cnf_pid3,
+ .peer = sc_join_peer),
+ /* Decode MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_receive, .ok = true,
+ .pmn = 0xFF, .pid = 3, .new_prn = false,
+ .new_my_nonce = false, .new_your_nonce = false,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = 0),
+ /* We have finished, tell it to the top FSM. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Go to SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_NMK_EXCHANGE,
+ CM_SET_KEY_CNF_PID3,
+ ok)),
+ /* Enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ SCENARIO_END
+ };
+ scenario_run (t, sc_add, &globals);
+
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_join_sta);
+ slab_release (sc_join_sta);
+ cp_sta_own_data_set_mac_address (&ctx.cp, my_mac);
+ } test_end;
+
+ /* The purpose of theses tests is to check if the poweron FSM is working
+ * well for a SC procedure. */
+ test_case_begin (t, "sc in poweron FSM");
+ /* USTA -> SC_ADD. */
+ test_begin (t, "USTA doing an SC ADD procedure.")
+ {
+ /* Some initialisation. */
+ /* The "host" peer. */
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445566ull, MAC_TEI_FOREIGN);
+ scenario_entry_t sc_poweron_sc_add[] =
+ {
+ /* We start in USTA. */
+ /* Action function to call when we start an SC add procedure. */
+ SCENARIO_ACTION (drv__usta__drv_sta_sc, .peer = peer),
+ /* Decoding is ok, and we want an SC_ADD. */
+ SCENARIO_EVENT (cp_msg_drv_sta_sc_req_receive, .ok = true,
+ .sc_join = false),
+ /* Send the reply to the "host" peer. */
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send, .peer = peer,
+ .mmtype = DRV_STA_SC_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Start the SC ADD. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_add),
+ /* USTA -> SC_USTA. */
+ /* Leave USTA. */
+ SCENARIO_ACTION (poweron__usta__leave),
+ /* Stop the USTT timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Leave SC_USTA, nothing to do */
+ /* Go to SC_CCO. */
+ /* This part can not be tested in sta_action (because it is
+ * in cco_action module). */
+ /*
+ SCENARIO_ACTION (sc__sc_cco__cc_assoc_req),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_receive, .ok = true,
+ .peer = peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = 0, .proxy_cap = 0),
+ SCENARIO_EVENT (cp_cco_action__assoc__join, .peer = peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = 0, .proxy_cap = 0),
+ */
+ /* SC FSM on-going, succeed. */
+ /* We received an sc_succeed. */
+ /* We become CCO. */
+ SCENARIO_END
+ };
+ scenario_run (t, sc_poweron_sc_add, &globals);
+
+ } test_end;
+
+ test_begin (t, "USTA doing an SC_JOIN")
+ {
+ cp_key_t new_nmk = { {0x1, 0x2, 0x3, 0x5} };
+
+ /* Some initialisation for the scenario. */
+ /* False beacon. */
+ bsu_beacon_t beacon;
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* A STA in SC add. */
+ cp_mme_peer_t sc_add_peer = CP_MME_PEER (sc_add_mac, 3);
+ cp_sta_t *sc_add_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 3,
+ sc_add_mac);
+ cp_net_set_cco (&ctx.cp, net, 3);
+ cp_sta_t *cco = cp_net_get_cco (&ctx.cp, net);
+ test_sta_action_beacon_create (
+ &beacon, cp_net_get_nid (&ctx.cp, net),
+ cp_net_get_snid (&ctx.cp, net), cp_sta_get_tei (cco),
+ cp_sta_get_mac_address (cco));
+ slab_release (cco);
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (&ctx.cp);
+ own->tei_track = 3;
+ /* The "host" peer. */
+ cp_mme_peer_t host_peer = CP_MME_PEER (cp_sta_own_data_get_mac_address (&ctx.cp),
+ MAC_TEI_FOREIGN);
+ cp_security_level_t sl = cp_sta_own_data_get_security_level (&ctx.cp);
+
+ /* STA replies to SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* We start in USTA. */
+ /* Action function to call when we start an SC add procedure. */
+ SCENARIO_ACTION (drv__usta__drv_sta_sc, .peer = host_peer),
+ /* Decoding is ok, and we want an SC_JOIN. */
+ SCENARIO_EVENT (cp_msg_drv_sta_sc_req_receive, .ok = true,
+ .sc_join = true),
+ /* Send the reply to the "host" peer. */
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send, .peer = host_peer,
+ .mmtype = DRV_STA_SC_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Start the SC JOIN. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_join),
+ /* USTA -> SC_USTA. */
+ /* Leave USTA. */
+ SCENARIO_ACTION (poweron__usta__leave),
+ /* Stop the USTT timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter in SC_USTA, nothing to do. */
+ /* SC FSM start working. */
+ /* Leave SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__leave),
+ /* Create SC timeout procedure. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 30000,
+ .delay_max_ms = 30000),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = true),
+ /* Enter SC_JOIN with no transition. */
+ /* Execute entering SC_JOIN enter function. */
+ SCENARIO_ACTION (sc__sc_join__enter),
+ /* Start JOIN_REQ timer. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_join_req_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* Send SC_JOIN.REQ to all STA. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_send,
+ .peer = all_sta),
+ /* We receive a CM_SC_JOIN.CNF. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_cnf, .peer = sc_add_peer),
+ /* Decode success. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_receive, .ok = true,
+ .nid = nid, .avln_status = false, .cco_cap = 0,
+ .pco_cap = false, .backup_cco_cap = false,
+ .cco_status = false, .pco_status = false,
+ .backup_cco_status = false),
+ /* Ok, we have finished for this state. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_CNF,
+ ok)),
+ /* Check nid has been setup correctly. */
+ SCENARIO_ACTION (sc__check_nid_set, .nid = nid),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_WAIT_BEACON. */
+ /* Nothing to do. */
+ /* A beacon has arrived. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = net,
+ .sta = sc_add_sta),
+ /* Track it: already tracking it.
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net), */
+ /* Beacon is ok, start assoc. */
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_differs)),
+ /* A beacon has arrived. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = net,
+ .sta = sc_add_sta),
+ /* Track it: already done
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net), */
+ /* Beacon is ok, start assoc. */
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ /* Trigger SC assoc. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_sc_assoc),
+ /* SC FSM has finished, trigger sc succeed. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Leave SC_WAIT_BEACON for SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_match)),
+ /* Enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ /* Handle UNASSOCIATED =to_sc_assoc=> SC_WAIT_ASSOC_CONF. */
+ /* First, leave UNASSOCIATED: nothing to do. */
+ /* Second, execute transition: send ASSOC.REQ. */
+ SCENARIO_ACTION (assoc__unassociated__to_assoc),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = sc_add_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid,
+ .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ /* Enter SC_WAIT_ASSOC_CONF: start retry timer. */
+ SCENARIO_ACTION (assoc__start_retry_timer),
+ /* Ignored in the scenario.
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_assoc_timeout), */
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* Handle SC_USTA =sc_succeed=> SC_USTA_JOINING. */
+ /* Leave SC_USTA: nothing to do. */
+ /* No transition. */
+ /* Enter SC_USTA_JOINING: nothing to do. */
+ /* CC_ASSOC_CNF received. */
+ SCENARIO_ACTION (assoc__sc_wait_assoc_cnf__cc_assoc_cnf,
+ .peer = sc_add_peer),
+ /* Decode received message. */
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = 0x0,
+ .sta_tei = sc_add_peer.tei,
+ .lease_time_min = 10),
+ /* Become "associated". */
+ /* Set-up lease timer. */
+ /* Ignored in the scenario.
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_assoc_timeout), */
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 10 * 60 * 1000 - (5 * 60 * 1000),
+ .delay_max_ms = 10 * 60 * 1000 - (5 * 60 * 1000)),
+ /* Association ok. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_ASSOC_CONF, CC_ASSOC_CNF,
+ ok)),
+ /* We go to SC_ASSOCIATED. */
+ /* Fist, leave SC_WAIT_ASSOC_CONF: stop timer. */
+ SCENARIO_ACTION (assoc__stop_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_ASSOCIATED: we restart the timer. */
+ SCENARIO_ACTION (assoc__start_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* We received CM_GET_KEY_REQ_PID3. */
+ SCENARIO_ACTION (assoc__sc_associated__cm_get_key_req_pid_3,
+ .peer = sc_add_peer),
+ /* Decoding is ok. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_receive, .ok = true,
+ .relayed = false, .key_type = CP_MSG_KEY_HASH_KEY,
+ .nid = nid, .pid = 3, .new_my_nonce = true,
+ .new_your_nonce = false, .new_prn = true,
+ .pmn = 1, .hash_key = second_hash_key,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED),
+ /* Send reply. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_send, .peer = sc_add_peer,
+ .result =
+ CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid,
+ .eks = CP_MME_PEKS_TEK_MIN, .pid = 3, .pmn = 2,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED),
+ /* Ok, finished. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_ASSOCIATED, CM_GET_KEY_REQ_PID3,
+ ok)),
+ /* Go to SC_TEK_EXCHANGED. */
+ /* Leave SC_ASSOCIATED: stop timer. */
+ SCENARIO_ACTION (assoc__stop_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_TEK_EXCHANGED: nothing to do. */
+ /* We receive the NMK encrypted with the TEK. */
+ SCENARIO_ACTION (assoc__sc_tek_exchanged__cm_set_key_req_pid_3,
+ .peer = sc_add_peer),
+ /* Decoding ok. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_receive, .ok = true,
+ .key_type = CP_MSG_KEY_NMK, .new_my_nonce = false,
+ .new_your_nonce = false, .new_prn = false, .pid = 3,
+ .pmn = 3, .cco_cap = CP_CCO_LEVEL, .nid = nid,
+ .new_eks = CP_MSG_KEY_NMK, .new_key = new_nmk),
+ /* Send drv_set_key.ind to hle. */
+ SCENARIO_EVENT (cp_msg_drv_sta_set_key_ind_send, .peer = host_peer,
+ .nmk = new_nmk,
+ .type = CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_SECURITY_LEVEL,
+ .nid = 0, .sl = sl),
+ /* Send reply. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_send, .peer = sc_add_peer,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = CP_CCO_LEVEL,
+ .pid = 3, .pmn = 0xFF,
+ .peks = CP_MME_PEKS_NMK),
+ /* Start authentication. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send, .peer = sc_add_peer,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 1,
+ .relayed = false, .key_type = CP_MSG_KEY_NEK,
+ .nid = nid),
+ /* Ok, finished for this state. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_TEK_EXCHANGED, CM_SET_KEY_REQ_PID3,
+ ok)),
+ /* Go to SC_NMK_EXCHANGED. */
+ /* Leave SC_TEK_EXCHANGED: nothing to do. */
+ /* Enter SC_NMK_EXCHANGED: nothing to do. */
+ /* We receive CM_GET_KEY_CNF_PID3. */
+ SCENARIO_ACTION (assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0,
+ .peer = sc_add_peer),
+ /* Decode message ok. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0,
+ .new_prn = false, .pmn = 0xFF,
+ .result =
+ CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .new_my_nonce = false,
+ .new_your_nonce = true, .nid = nid,
+ .eks = CP_MSG_KEY_NEK, .key = &nmk),
+ /* Set NMK. */
+ SCENARIO_EVENT (cp_beacon_change_nek, .eks = CP_MSG_KEY_NEK,
+ .nek = &nmk, .now = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_joined),
+ /* Trigger event to tell we have joined. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_NMK_EXCHANGED, CM_GET_KEY_CNF_PID0,
+ ok)),
+ /* Go to authenticated. */
+ /* Leave SC_NMK_EXCHANGED: nothing to do. */
+ /* Enter AUTHENTICATED: nothing to do. */
+ /* Handle SC_USTA_JOINING =joined=> STA. */
+ /* Leaving SC_USTA_JOINING: nothing to do. */
+ /* Transition: nothing to do. */
+ /* Enter STA: nothing to do. */
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ /* Clean. */
+ slab_release (sc_add_sta);
+ } test_end;
+
+ test_begin (t, "UCCO doing an SC_JOIN")
+ {
+ /* Some initialisation for the scenario. */
+ /* False beacon. */
+ bsu_beacon_t beacon;
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* A STA in SC add. */
+ cp_mme_peer_t sc_add_peer = CP_MME_PEER (sc_add_mac, 3);
+ cp_sta_t *sc_add_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 3,
+ sc_add_mac);
+ cp_sta_own_data_set_tei (&ctx.cp, 0);
+ cp_net_set_cco (&ctx.cp, net, 3);
+ cp_sta_t *cco = cp_net_get_cco (&ctx.cp, net);
+ test_sta_action_beacon_create (
+ &beacon, cp_net_get_nid (&ctx.cp, net),
+ cp_net_get_snid (&ctx.cp, net), cp_sta_get_tei (cco),
+ cp_sta_get_mac_address (cco));
+ slab_release (cco);
+ /* The "host" peer. */
+ cp_mme_peer_t host_peer = CP_MME_PEER (cp_sta_own_data_get_mac_address (&ctx.cp),
+ MAC_TEI_FOREIGN);
+ cp_security_level_t sl = cp_sta_own_data_get_security_level (&ctx.cp);
+
+ /* STA replies to SC.JOIN.REQ. */
+ scenario_entry_t sc_join_reply[] = {
+ /* We start in UCCO. */
+ /* Action function to call when we start an SC join procedure. */
+ SCENARIO_ACTION (drv__ucco__drv_sta_sc, .peer = host_peer),
+ /* Decoding is ok, and we want an SC_JOIN. */
+ SCENARIO_EVENT (cp_msg_drv_sta_sc_req_receive, .ok = true,
+ .sc_join = true),
+ /* Send the reply to the "host" peer. */
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send, .peer = host_peer,
+ .mmtype = DRV_STA_SC_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Start the SC JOIN. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_join),
+ /* UCCO -> SC_UCCO. */
+ /* Leave UCCO: nothing to do. */
+ /* No transition. */
+ /* Enter in SC_UCCO: nothing to do. */
+ /* SC FSM start working. */
+ /* Leave SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__leave),
+ /* Create SC timeout procedure. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 30000,
+ .delay_max_ms = 30000),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = true),
+ /* Enter SC_JOIN with no transition. */
+ /* Execute entering SC_JOIN enter function. */
+ SCENARIO_ACTION (sc__sc_join__enter),
+ /* Start JOIN_REQ timer. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_join_req_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* Send SC_JOIN.REQ to all STA. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_send,
+ .peer = all_sta),
+ /* We receive a CM_SC_JOIN.CNF. */
+ SCENARIO_ACTION (sc__sc_join__cm_sc_join_cnf, .peer = sc_add_peer),
+ /* Decode success. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_receive, .ok = true,
+ .nid = nid, .avln_status = false, .cco_cap = 0,
+ .pco_cap = false, .backup_cco_cap = false,
+ .cco_status = false, .pco_status = false,
+ .backup_cco_status = false),
+ /* Ok, we have finished for this state. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_JOIN, CM_SC_JOIN_CNF,
+ ok)),
+ /* Check nid has been setup correctly. */
+ SCENARIO_ACTION (sc__check_nid_set, .nid = nid),
+ /* Leave SC_JOIN. */
+ SCENARIO_ACTION (sc__sc_join__leave),
+ /* Stop timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_WAIT_BEACON. */
+ /* Nothing to do. */
+ /* A beacon has arrived. */
+ /* Let's pretend it has been posted for the SC FSM first. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = net,
+ .sta = sc_add_sta),
+ /* Track it: already done
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net), */
+ /* Beacon is ok, start assoc. */
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = false),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_differs)),
+ /* New beacon. */
+ SCENARIO_ACTION (sc__sc_wait_beacon__beacon,
+ .beacon = &beacon,
+ .net = net,
+ .sta = sc_add_sta),
+ /* Track it: already done
+ SCENARIO_EVENT (cp_beacon_process_tracked_avln, .beacon = &beacon,
+ .net = net), */
+ /* Beacon is ok, start assoc. */
+ SCENARIO_EVENT (cp_beacon_synchronised, .ok = true),
+ /* Trigger SC assoc. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_to_sc_assoc),
+ /* SC FSM has finished, trigger sc succeed. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Leave SC_WAIT_BEACON for SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_BEACON, BEACON,
+ nid_match)),
+ /* Enter SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+ /* Top FSM receive the BEACON. */
+ /* Handle SC_UCCO =BEACON=> SC_USTA. */
+ /* Leave SC_UCCO: nothing to do. */
+ /* Handle transition. */
+ SCENARIO_ACTION (sc__sc_ucco_track_beacon, .beacon = &beacon,
+ .net = net, .sta = sc_add_sta),
+ /* Change to STA behaviour. */
+ SCENARIO_EVENT (cp_beacon_reconfigure_timer),
+ /* Enter SC_USTA: nothing to do. */
+ /* Handle UNASSOCIATED =to_sc_assoc=> SC_WAIT_ASSOC_CONF. */
+ /* First, leave UNASSOCIATED: nothing to do. */
+ /* Second, execute transition: send ASSOC.REQ. */
+ SCENARIO_ACTION (assoc__unassociated__to_assoc),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_send,
+ .peer = sc_add_peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid,
+ .cco_cap = CP_CCO_LEVEL,
+ .proxy_cap = CP_PCO_CAP),
+ /* Enter SC_WAIT_ASSOC_CONF: start retry timer. */
+ SCENARIO_ACTION (assoc__start_retry_timer),
+ /* Ignored in the scenario.
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_assoc_timeout), */
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* Handle SC_USTA =sc_succeed=> SC_USTA_JOINING. */
+ /* Leave SC_USTA: nothing to do. */
+ /* No transition. */
+ /* Enter SC_USTA_JOINING: nothing to do. */
+ /* CC_ASSOC_CNF received. */
+ SCENARIO_ACTION (assoc__sc_wait_assoc_cnf__cc_assoc_cnf,
+ .peer = sc_add_peer),
+ /* Decode received message. */
+ SCENARIO_EVENT (cp_msg_cc_assoc_cnf_receive, .ok = true,
+ .result = CP_MSG_CC_ASSOC_CNF_RESULT_SUCCESS,
+ .nid = nid, .snid = 0x0,
+ .sta_tei = sc_add_peer.tei,
+ .lease_time_min = 10),
+ /* Become "associated". */
+ /* Set-up lease timer. */
+ /* Ignored in the scenario.
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_assoc_timeout), */
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 10 * 60 * 1000 - (5 * 60 * 1000),
+ .delay_max_ms = 10 * 60 * 1000 - (5 * 60 * 1000)),
+ /* Association ok. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_ASSOC_CONF, CC_ASSOC_CNF,
+ ok)),
+ /* We go to SC_ASSOCIATED. */
+ /* Fist, leave SC_WAIT_ASSOC_CONF: stop timer. */
+ SCENARIO_ACTION (assoc__stop_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_ASSOCIATED: we restart the timer. */
+ SCENARIO_ACTION (assoc__start_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = sc_periodic_sc_join_req_bcast_ms_min,
+ .delay_max_ms = sc_periodic_sc_join_req_bcast_ms_max),
+ /* We received CM_GET_KEY_REQ_PID3. */
+ SCENARIO_ACTION (assoc__sc_associated__cm_get_key_req_pid_3,
+ .peer = sc_add_peer),
+ /* Decoding is ok. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_receive, .ok = true,
+ .relayed = false, .key_type = CP_MSG_KEY_HASH_KEY,
+ .nid = nid, .pid = 3, .new_my_nonce = true,
+ .new_your_nonce = false, .new_prn = true,
+ .pmn = 1, .hash_key = second_hash_key,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED),
+ /* Send reply. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_send, .peer = sc_add_peer,
+ .result =
+ CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid,
+ .eks = CP_MME_PEKS_TEK_MIN, .pid = 3, .pmn = 2,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED),
+ /* Ok, finished. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_ASSOCIATED, CM_GET_KEY_REQ_PID3,
+ ok)),
+ /* Go to SC_TEK_EXCHANGED. */
+ /* Leave SC_ASSOCIATED: stop timer. */
+ SCENARIO_ACTION (assoc__stop_retry_timer),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter SC_TEK_EXCHANGED: nothing to do. */
+ /* We receive the NMK encrypted with the TEK. */
+ SCENARIO_ACTION (assoc__sc_tek_exchanged__cm_set_key_req_pid_3,
+ .peer = sc_add_peer),
+ /* Decoding ok. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_receive, .ok = true,
+ .key_type = CP_MSG_KEY_NMK, .new_my_nonce = false,
+ .new_your_nonce = false, .new_prn = false, .pid = 3,
+ .pmn = 3, .cco_cap = CP_CCO_LEVEL, .nid = nid,
+ .new_eks = CP_MSG_KEY_NMK, .new_key = nmk),
+ /* Send drv_set_key.ind to hle. */
+ SCENARIO_EVENT (cp_msg_drv_sta_set_key_ind_send, .peer = host_peer,
+ .nmk = nmk,
+ .type = CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_SECURITY_LEVEL,
+ .nid = 0, .sl = sl),
+ /* Send reply. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_send, .peer = sc_add_peer,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = CP_CCO_LEVEL,
+ .pid = 3, .pmn = 0xFF,
+ .peks = CP_MME_PEKS_NMK),
+ /* Start authentication. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send, .peer = sc_add_peer,
+ .peks = CP_MME_PEKS_NMK, .pid = 0, .pmn = 1,
+ .relayed = false, .key_type = CP_MSG_KEY_NEK,
+ .nid = nid),
+ /* Ok, finished for this state. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_TEK_EXCHANGED, CM_SET_KEY_REQ_PID3,
+ ok)),
+ /* Go to SC_NMK_EXCHANGED. */
+ /* Leave SC_TEK_EXCHANGED: nothing to do. */
+ /* Enter SC_NMK_EXCHANGED: nothing to do. */
+ /* We receive CM_GET_KEY_CNF_PID3. */
+ SCENARIO_ACTION (assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0,
+ .peer = sc_add_peer),
+ /* Decode message ok. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .peks = CP_MME_PEKS_NMK, .pid = 0,
+ .new_prn = false, .pmn = 0xFF,
+ .result =
+ CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_NEK, .new_my_nonce = false,
+ .new_your_nonce = true, .nid = nid,
+ .eks = CP_MSG_KEY_NEK, .key = &nmk),
+ /* Set NMK. */
+ SCENARIO_EVENT (cp_beacon_change_nek, .eks = CP_MSG_KEY_NEK,
+ .nek = &nmk, .now = true),
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_joined),
+ /* Trigger event to tell we have joined. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_NMK_EXCHANGED, CM_GET_KEY_CNF_PID0,
+ ok)),
+ /* Go to authenticated. */
+ /* Leave SC_NMK_EXCHANGED: nothing to do. */
+ /* Enter AUTHENTICATED: nothing to do. */
+ /* Handle SC_USTA_JOINING =joined=> STA. */
+ /* Leaving SC_USTA_JOINING: nothing to do. */
+ /* Transition: nothing to do. */
+ /* Enter STA: nothing to do. */
+ SCENARIO_END
+ };
+ scenario_run (t, sc_join_reply, &globals);
+ /* Clean. */
+ slab_release (sc_add_sta);
+ } test_end;
+
+ test_begin (t, "CCO doing an SC_ADD")
+ {
+ /* Some initialisation for the scenario. */
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ cp_mme_peer_t sc_join_peer_assoc = CP_MME_PEER (sc_join_mac, 3);
+ cp_sta_t *sc_join_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 3,
+ sc_join_mac);
+ /* The "host" peer. */
+ cp_mme_peer_t host_peer = CP_MME_PEER (0x112233445566ull, MAC_TEI_FOREIGN);
+
+ /* We are a CCO. */
+ cp_sta_own_data_set_tei (&ctx.cp, 1);
+ cp_sta_own_data_set_cco_status (&ctx.cp, true);
+ scenario_entry_t sc_add[] = {
+ /* We start in CCO. */
+
+ /* CCO =DRV_STA_SC (add)=> SC_CCO. */
+ /* Action function to call when we start an SC join procedure. */
+ SCENARIO_ACTION (drv__cco__drv_sta_sc, .peer = host_peer),
+ /* Decoding is ok, and we want an SC_ADD. */
+ SCENARIO_EVENT (cp_msg_drv_sta_sc_req_receive, .ok = true,
+ .sc_join = false),
+ /* Send the reply to the "host" peer. */
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send, .peer = host_peer,
+ .mmtype = DRV_STA_SC_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Start the SC JOIN. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_add),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (CCO, DRV_STA_SC_REQ,
+ sc_add)),
+ /* Leave CCO: disable timer. */
+ SCENARIO_ACTION (poweron_cco__leave),
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Enter in SC_CCO: nothing to do. */
+
+ /* SC_IDLE =sc_start_add=> SC_ADD. */
+ /* Execute transition: nothing to do. */
+ /* Leave SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__leave),
+ /* Create SC timeout procedure. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 30000,
+ .delay_max_ms = 30000),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = true),
+ /* Enter SC_ADD: nothing to do. */
+
+ /* We receive an CM_SC_JOIN_REQ request. */
+ /* SC_ADD =CM_SC_JOIN_REQ (ok)=> SC_WAIT_PEER_ASSOCIATED. */
+ /* Execute transition. */
+ SCENARIO_ACTION (sc__sc_add__cm_sc_join_req,
+ .peer = sc_join_peer),
+ /* Check the MME (we fake the join STA has greater cco_cap, this
+ * should be ignored). */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 1),
+ /* Send the SC_JOIN.CNF. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_send,
+ .peer = sc_join_peer, .nid = nid,
+ .avln_status = true, .cco_cap = CP_CCO_LEVEL,
+ .pco_cap = CP_PCO_CAP,
+ .backup_cco_cap = CP_BACKUP_CCO_CAP,
+ .cco_status = true, .pco_status = false,
+ .backup_cco_status = false),
+ /* Take the "ok" branch. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_ADD, CM_SC_JOIN_REQ,
+ ok)),
+ /* SC_ADD leave: nothing to do. */
+ /* SC_WAIT_PEER_ASSOCIATED enter: nothing to do. */
+
+ /* We receive an CC_ASSOC.REQ. */
+ /* SC_CCO =CC_ASSOC.REQ=> SC_CCO. */
+ /* First execute transition: can not be tested in sta action. */
+ /*
+ SCENARIO_ACTION (sc__sc_cco__cc_assoc_req),
+ SCENARIO_EVENT (cp_msg_cc_assoc_req_receive, .ok = true,
+ .peer = peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = 0, .proxy_cap = 0),
+ SCENARIO_EVENT (cp_cco_action__assoc__join, .peer = peer,
+ .request_type = CP_MSG_CC_ASSOC_REQ_TYPE_NEW,
+ .nid = nid, .cco_cap = 0, .proxy_cap = 0),
+ */
+ /* We do not leave SC_CCO, nothing else to do. */
+
+ /* SC_WAIT_PEER_ASSOCIATED =new_sta_associated (sta_is_sc_peer)=>
+ * SC_BUILDING_TEK. */
+ /* Execute transition: send get key req. */
+ SCENARIO_ACTION (sc__sc_wait_peer_associated__new_sta_associated,
+ .net = net, .sta = sc_join_sta),
+ /* Send the first hash key. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = sc_join_peer_assoc,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED,
+ .pid = 3, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid),
+ /* Wait for the second hash key to build the TEK. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_PEER_ASSOCIATED,
+ new_sta_associated,
+ sta_is_sc_peer)),
+ /* Leave SC_WAIT_PEER_ASSOCIATED: nothing to do. */
+ /* Enter SC_BUILDING_TEK: nothing to do. */
+
+ /* SC_BUILDING_TEK =CM_GET_KEY_CNF_PID3 (ok)=> SC_NMK_EXCHANGE */
+ /* Transition function: decode and reply. */
+ SCENARIO_ACTION (sc__sc_building_tek__cm_get_key_cnf_pid3,
+ .peer = sc_join_peer_assoc),
+ /* Decoding MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .pmn = 2, .pid = 3,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid,
+ .eks = CP_MME_PEKS_TEK_MIN + 3,
+ .hash_key = second_hash_key),
+ /* Send the NMK encrypted with the TEK. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_send,
+ .peer = sc_join_peer_assoc,
+ .peks = CP_MME_PEKS_TEK_MIN + 3,
+ .pid = 3, .pmn = 3, .key_type = CP_MSG_KEY_NMK,
+ .cco_cap = CP_CCO_LEVEL,
+ .nid = nid, .new_eks = CP_MME_PEKS_NMK,
+ .new_key = nmk),
+ /* Go to SC_NMK_EXCHANGE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_BUILDING_TEK,
+ CM_GET_KEY_CNF_PID3,
+ ok)),
+ /* Leave SC_BUILDING_TEK: nothing to do. */
+
+ /* Receive CM_SET_KEY_CNF. */
+ /* SC_NMK_EXCHANGE =CM_SET_KEY_CNF_PID3 (ok) => SC_IDLE. */
+ /* First, handle transition: decode received MME. */
+ SCENARIO_ACTION (sc__sc_nmk_exchange__cm_set_key_cnf_pid3,
+ .peer = sc_join_peer_assoc),
+ /* Decode MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_receive, .ok = true,
+ .pmn = 0xFF, .pid = 3, .new_prn = false,
+ .new_my_nonce = false, .new_your_nonce = false,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = 0),
+ /* We have finished, tell it to the top FSM. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Go to SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_NMK_EXCHANGE,
+ CM_SET_KEY_CNF_PID3,
+ ok)),
+ /* Leave SC_NMK_EXCHANGE: nothing to do. */
+ /* Enter SC_IDLE: stop timer. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+
+ /* Top FSM receive sc_succeed. */
+ /* SC_CCO =sc_succeed=> CCO. */
+ /* Transition function: nothing to do. */
+ /* Leave SC_CCO: nothing to do. */
+ /* Enter CCO: start join timer. */
+ SCENARIO_ACTION (poweron_cco__enter),
+ /* Disable....
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_join_timeout), */
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 10 * 1000,
+ .delay_max_ms = 10 * 1000),
+ /* The rest of the autentication will be done in CCO. */
+ SCENARIO_END
+ };
+ scenario_run (t, sc_add, &globals);
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_join_sta);
+ slab_release (sc_join_sta);
+ } test_end;
+
+ test_begin (t, "STA doing an SC_ADD")
+ {
+ /* Some initialisation for the scenario. */
+ /* Create net. */
+ test_sta_action_create_our_net (&ctx, nid, 0);
+ cp_net_t *net = cp_sta_mgr_get_avln (&ctx.cp, 0, nid);
+ /* A STA in SC join. */
+ cp_mme_peer_t sc_join_peer = CP_MME_PEER (sc_join_mac, 0);
+ cp_mme_peer_t sc_join_peer_assoc = CP_MME_PEER (sc_join_mac, 3);
+ cp_sta_t *sc_join_sta = cp_sta_mgr_sta_add (&ctx.cp, net, 3,
+ sc_join_mac);
+ /* The "host" peer. */
+ cp_mme_peer_t host_peer = CP_MME_PEER (0x112233445566ull, MAC_TEI_FOREIGN);
+
+ /* We are a STA. */
+ cp_sta_own_data_set_cco_status (&ctx.cp, false);
+ scenario_entry_t sc_add[] = {
+ /* We start in STA. */
+
+ /* STA =DRV_STA_SC (add)=> SC_STA. */
+ /* Action function to call when we start an SC join procedure. */
+ SCENARIO_ACTION (drv__sta__drv_sta_sc, .peer = host_peer),
+ /* Decoding is ok, and we want an SC_ADD. */
+ SCENARIO_EVENT (cp_msg_drv_sta_sc_req_receive, .ok = true,
+ .sc_join = false),
+ /* Send the reply to the "host" peer. */
+ SCENARIO_EVENT (cp_msg_drv_any_cnf_send, .peer = host_peer,
+ .mmtype = DRV_STA_SC_CNF,
+ .result = CP_MSG_DRV_RESULT_SUCCESS),
+ /* Start the SC JOIN. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_start_add),
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (STA, DRV_STA_SC_REQ,
+ sc_add)),
+ /* Leave STA: nothing to do. */
+ /* Enter in SC_ADD: nothing to do. */
+
+ /* SC_IDLE =sc_start_add=> SC_ADD. */
+ /* Execute transition: nothing to do. */
+ /* Leave SC_IDLE. */
+ SCENARIO_ACTION (sc__sc_idle__leave),
+ /* Create SC timeout procedure. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_timeout),
+ SCENARIO_EVENT (cp_sta_core_gen_timed_event,
+ .delay_min_ms = 30000,
+ .delay_max_ms = 30000),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = true),
+ /* Enter SC_ADD: nothing to do. */
+
+ /* We receive an CM_SC_JOIN_REQ request. */
+ /* SC_ADD =CM_SC_JOIN_REQ (ok)=> SC_WAIT_PEER_ASSOCIATED. */
+ /* Execute transition. */
+ SCENARIO_ACTION (sc__sc_add__cm_sc_join_req,
+ .peer = sc_join_peer),
+ /* Check the MME (we fake the join STA has greater cco_cap, this
+ * should be ignored). */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_req_receive, .ok = true,
+ .cco_cap = 1),
+ /* Send the SC_JOIN.CNF. */
+ SCENARIO_EVENT (cp_msg_cm_sc_join_cnf_send,
+ .peer = sc_join_peer, .nid = nid,
+ .avln_status = true, .cco_cap = CP_CCO_LEVEL,
+ .pco_cap = CP_PCO_CAP,
+ .backup_cco_cap = CP_BACKUP_CCO_CAP,
+ .cco_status = false, .pco_status = false,
+ .backup_cco_status = false),
+ /* Take the "ok" branch. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_ADD, CM_SC_JOIN_REQ,
+ ok)),
+ /* SC_ADD leave: nothing to do. */
+ /* SC_WAIT_PEER_ASSOCIATED enter: nothing to do. */
+
+ /* CCo receive an CC_ASSOC.REQ and reply to it, we are not
+ * involved. We will see the TEI_MAP update and generate a
+ * new_sta_associated event */
+
+ /* SC_WAIT_PEER_ASSOCIATED =new_sta_associated (sta_is_sc_peer)=>
+ * SC_BUILDING_TEK. */
+ /* Execute transition: send get key req. */
+ SCENARIO_ACTION (sc__sc_wait_peer_associated__new_sta_associated,
+ .net = net, .sta = sc_join_sta),
+ /* Send the first hash key. */
+ SCENARIO_EVENT (cp_msg_cm_get_key_req_send,
+ .peer = sc_join_peer_assoc,
+ .peks = CP_MME_PEKS_SPC_NOT_EMBEDDED,
+ .pid = 3, .pmn = 1, .relayed = false,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid),
+ /* Wait for the second hash key to build the TEK. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_WAIT_PEER_ASSOCIATED,
+ new_sta_associated,
+ sta_is_sc_peer)),
+ /* Leave SC_WAIT_PEER_ASSOCIATED: nothing to do. */
+ /* Enter SC_BUILDING_TEK: nothing to do. */
+
+ /* SC_BUILDING_TEK =CM_GET_KEY_CNF_PID3 (ok)=> SC_NMK_EXCHANGE */
+ /* Transition function: decode and reply. */
+ SCENARIO_ACTION (sc__sc_building_tek__cm_get_key_cnf_pid3,
+ .peer = sc_join_peer_assoc),
+ /* Decoding MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_get_key_cnf_receive, .ok = true,
+ .pmn = 2, .pid = 3,
+ .new_prn = false, .new_my_nonce = false,
+ .new_your_nonce = true,
+ .result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED,
+ .key_type = CP_MSG_KEY_HASH_KEY, .nid = nid,
+ .eks = CP_MME_PEKS_TEK_MIN + 4,
+ .hash_key = second_hash_key),
+ /* Send the NMK encrypted with the TEK. */
+ SCENARIO_EVENT (cp_msg_cm_set_key_req_send,
+ .peer = sc_join_peer_assoc,
+ .peks = CP_MME_PEKS_TEK_MIN + 4,
+ .pid = 3, .pmn = 3, .key_type = CP_MSG_KEY_NMK,
+ .cco_cap = CP_CCO_LEVEL,
+ .nid = nid, .new_eks = CP_MME_PEKS_NMK,
+ .new_key = nmk),
+ /* Go to SC_NMK_EXCHANGE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_BUILDING_TEK,
+ CM_GET_KEY_CNF_PID3,
+ ok)),
+ /* Leave SC_BUILDING_TEK: nothing to do. */
+
+ /* Receive CM_SET_KEY_CNF. */
+ /* SC_NMK_EXCHANGE =CM_SET_KEY_CNF_PID3 (ok) => SC_IDLE. */
+ /* First, handle transition: decode received MME. */
+ SCENARIO_ACTION (sc__sc_nmk_exchange__cm_set_key_cnf_pid3,
+ .peer = sc_join_peer_assoc),
+ /* Decode MME (valid). */
+ SCENARIO_EVENT (cp_msg_cm_set_key_cnf_receive, .ok = true,
+ .pmn = 0xFF, .pid = 3, .new_prn = false,
+ .new_my_nonce = false, .new_your_nonce = false,
+ .result = CP_MSG_CM_SET_KEY_CNF_RESULT_SUCCESS,
+ .cco_cap = 0),
+ /* We have finished, tell it to the top FSM. */
+ SCENARIO_EVENT (cp_fsm_event_bare_new,
+ .type = CP_FSM_EVENT_TYPE_sc_succeed),
+ /* Go to SC_IDLE. */
+ SCENARIO_EVENT (cp_fsm_branch,
+ .branch = CP_FSM_BRANCH (SC_NMK_EXCHANGE,
+ CM_SET_KEY_CNF_PID3,
+ ok)),
+ /* Leave SC_NMK_EXCHANGE: nothing to do. */
+ /* Enter SC_IDLE: stop timer. */
+ SCENARIO_ACTION (sc__sc_idle__enter),
+ /* Stop SC timer. */
+ SCENARIO_EVENT (cp_sta_core_stop_timed_or_cyclic_event),
+ /* Check SC status has been updated. */
+ SCENARIO_ACTION (sc__check_sc_status, .sc_status = false),
+
+ /* Top FSM receive sc_succeed. */
+ /* SC_STA =sc_succeed=> STA. */
+ /* Transition function: nothing to do. */
+ /* Leave SC_CCO: nothing to do. */
+ /* Enter STA: nothing to do. */
+
+ /* The rest of the autentication will be done in CCO. */
+ SCENARIO_END
+ };
+ scenario_run (t, sc_add, &globals);
+ /* Clean. */
+ cp_sta_mgr_sta_remove (&ctx.cp, sc_join_sta);
+ slab_release (sc_join_sta);
+ } test_end;
+ /* Clean. */
+ test_sta_action_uninit (&ctx);
+}
+
+void
+sc_test_suite (test_t t)
+{
+ /* Start SC tests. */
+ test_suite_begin (t, "sc");
+ sc_basic_test_cases (t);
+
+ /* Check memory leak. */
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/sc_test.c b/cesar/cp/av/sta/action/test/utest/src/sc_test.c
new file mode 100644
index 0000000000..5d04f9fcab
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/sc_test.c
@@ -0,0 +1,64 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/sc_test.c
+ * \brief Tests for SC procedure.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "cp/sta/mgr/sta_own_data.h"
+#include "cp/inc/context.h"
+#include "cp/sta/action/inc/context.h"
+
+void
+scenario_action_sc__check_nid_set_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ dbg_assert (scenario.current);
+ test_within (scenario.t);
+ test_fail_unless (cp_sta_own_data_get_nid (globals->cp) ==
+ params->action_sc__check_nid_set.nid);
+}
+
+void
+scenario_action_sc__check_sc_assoc_start_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ /* Check parameters. */
+ dbg_assert (globals);
+ dbg_assert (params);
+ dbg_assert (scenario.current);
+
+ /* Check we are in the right scenario. */
+ test_within (scenario.t);
+ /* Check values. */
+ cp_t *cp = globals->cp;
+ test_fail_unless (cp_mme_peer_cmp (&cp->sta_action.sc.peer,
+ params->action_sc__check_sc_assoc_start.sc_peer));
+ test_fail_unless (cp_mme_peer_cmp (&cp->sta_action.assoc.peer,
+ params->action_sc__check_sc_assoc_start.cco_peer));
+}
+
+void
+scenario_action_sc__check_sc_status_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ /* Check parameters. */
+ dbg_assert (globals);
+ dbg_assert (params);
+ dbg_assert (scenario.current);
+
+ /* Check we are in the right scenario. */
+ test_within (scenario.t);
+ /* Check values. */
+ cp_t *cp = globals->cp;
+ test_fail_unless (cp->sta_mgr.sta_own_data.sc ==
+ params->action_sc__check_sc_status.sc_status);
+}
diff --git a/cesar/cp/av/sta/action/test/utest/src/scenario_actions.c b/cesar/cp/av/sta/action/test/utest/src/scenario_actions.c
new file mode 100644
index 0000000000..3a5c5ca97b
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/scenario_actions.c
@@ -0,0 +1,268 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/scenario_actions.c
+ * \brief Scenario actions.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "cp/av/sta/action/action.h"
+
+#include "lib/scenario/scenario.h"
+
+#define __m(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ static cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ mme.peks = CP_MME_PEKS_SPC_NOT_EMBEDDED; \
+ cp_sta_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __m_av(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ static cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ mme.peks = CP_MME_PEKS_SPC_NOT_EMBEDDED; \
+ cp_av_sta_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __mp(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ static cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ mme.prun.pid = params->action_ ## ACTION.pid; \
+ mme.peks = CP_MME_PEKS_SPC_NOT_EMBEDDED; \
+ cp_sta_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __me(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ static cp_mme_rx_t mme; \
+ mme.peer = params->action_ ## ACTION.peer; \
+ mme.encrypt = params->action_ ## ACTION.encrypt; \
+ cp_sta_action_ ## ACTION (globals->cp, &mme); \
+}
+
+#define __0(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ cp_sta_action_ ## ACTION (globals->cp); \
+}
+
+#define __0_av(ACTION) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ cp_av_sta_action_ ## ACTION (globals->cp); \
+}
+
+#define __n(ACTION, PARAMS...) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ scenario_action_ ## ACTION ## _t *p = &params->action_ ## ACTION; \
+ cp_sta_action_ ## ACTION (globals->cp \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, \
+ __n_args, ## PARAMS) \
+ ); \
+}
+
+#define __n_av(ACTION, PARAMS...) \
+void \
+scenario_action_ ## ACTION ## _cb (scenario_globals_t *globals, \
+ scenario_params_t *params) \
+{ \
+ scenario_action_ ## ACTION ## _t *p = &params->action_ ## ACTION; \
+ cp_av_sta_action_ ## ACTION (globals->cp \
+ PREPROC_FOR_EACH_PARAM (PREPROC_CALL_UNPACK, \
+ __n_args, ## PARAMS) \
+ ); \
+}
+
+#define __n_args(TYPE, PARAM) \
+ , p->PARAM
+
+__0 (garbage)
+
+__n_av (assoc_start,
+ (cp_net_t *, cco_net),
+ (cp_sta_t *, cco))
+__0_av (assoc_leave)
+__0_av (assoc__unassociated__enter)
+__0_av (assoc__unassociated__to_assoc)
+__0 (assoc__start_retry_timer)
+__0 (assoc__stop_retry_timer)
+__m_av (assoc__wait_assoc_cnf__cc_assoc_cnf)
+__0_av (assoc__wait_assoc_cnf__timeout)
+__m_av (assoc__associated__cm_get_key_cnf_pid_0)
+__0_av (assoc__associated__timeout)
+__0_av (assoc__associated__to_leave)
+__0_av (assoc__authenticated__leave)
+__0_av (assoc__authenticated__renew)
+__m_av (assoc__authenticated__cc_assoc_cnf)
+__m_av (assoc__authenticated__cm_set_key_req_pid_1)
+__0_av (assoc__authenticated__to_leave)
+__m_av (assoc__authenticated__cc_leave_ind)
+__n_av (assoc__authenticated__beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__0_av (assoc__authenticated__beacon_not_received)
+__0_av (assoc__authenticated__nek_request)
+__m_av (assoc__authenticated__cm_get_key_cnf_pid_1)
+__m_av (assoc__leaving__cc_leave_cnf)
+__0_av (assoc__leaving__timeout)
+__0_av (assoc__leave_wait__enter)
+__0_av (assoc__leave_wait__timeout)
+
+__m (drv__stopped__drv_sta_set_mac_addr_req)
+__m (drv__stopped__drv_sta_set_cco_pref_req)
+__m (drv__stopped__drv_sta_set_was_cco_req)
+__m (drv__stopped__drv_sta_set_dpw_req)
+__m (drv__stopped__drv_sta_set_npw_req)
+__m (drv__stopped__drv_sta_set_sl_req)
+__m (drv__stopped__drv_sta_set_nid_req)
+__m (drv__stopped__drv_sta_set_m_sta_hfid_req)
+__m (drv__stopped__drv_sta_set_u_sta_hfid_req)
+__m (drv__stopped__drv_sta_set_avln_hfid_req)
+__m (drv__stopped__drv_sta_set_tonemask_req)
+__m (drv__stopped__drv_sta_mac_start_req)
+__m (drv__started__drv_sta_mac_stop_req)
+__m (drv__stopped__drv_sta_set_key_req)
+__m (drv__stopped__drv_sta_set_dak_req)
+__0 (drv__stopping__stopped)
+__m (drv__drv_sta_get_key_req)
+__m (drv__drv_sta_status_req)
+__m (drv__drv_sta_set_config_req)
+__m (drv__drv_mcast_set_list_req)
+
+__m_av (process_cc_set_tei_map_ind)
+__m_av (process_cm_unassociated_sta_ind)
+
+__mp (process_cm_set_key_req)
+__mp (process_cm_set_key_cnf)
+__mp (process_cm_get_key_req)
+__mp (process_cm_get_key_cnf)
+
+__m (process_cc_who_ru_req)
+__m (process_cc_who_ru_cnf)
+__m_av (process_cc_discover_list_req)
+__me (process_cc_relay_req)
+__m (process_cm_hfid_req)
+__m (process_cm_mme_error_ind)
+
+__0 (poweron_start)
+__0 (poweron_stop)
+__0 (poweron__many__to_idle)
+__0 (poweron__idle__to_poweron)
+__0_av (poweron__poweron__enter)
+__0_av (poweron__poweron__leave)
+__0_av (poweron__poweron__ustt_timeout)
+__0_av (poweron__poweron__btt_timeout)
+__n_av (poweron__poweron__beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__0_av (poweron__poweron_joining__left)
+__0_av (poweron__joining__to_stop)
+__0_av (poweron__usta__enter)
+__0_av (poweron__usta__leave)
+__0_av (poweron__usta__ustt_timeout)
+__n_av (poweron__usta__beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__n_av (poweron__usta__usta_ind,
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__0_av (poweron__usta_joining__left)
+__n_av (poweron__ucco__beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__0_av (poweron__sta__to_stop)
+__0_av (poweron__cco__join_timeout)
+__0_av (poweron_cco__enter)
+__0_av (poweron_cco__leave)
+
+__m (process_cm_brg_info_cnf)
+__m (process_cm_brg_info_req)
+__0 (update_bridge_table)
+
+__m_av (drv__usta__drv_sta_sc)
+__m_av (drv__ucco__drv_sta_sc)
+__m_av (drv__cco__drv_sta_sc)
+__m_av (drv__sta__drv_sta_sc)
+__0_av (sc__start_sc_join)
+__0_av (sc__start_sc_add)
+__0_av (sc__sc_idle__enter)
+__0_av (sc__sc_idle__leave)
+__0_av (sc__sc_join__enter)
+__0_av (sc__sc_join__leave)
+__0_av (sc__sc_join__sc_join_req_timeout)
+__0_av (sc__sc_cco__sc_failed)
+__0_av (sc__sc_timeout)
+__0_av (sc_add__sc_timeout)
+__m_av (sc__sc_join__cm_sc_join_cnf)
+__m_av (sc__sc_join__cm_sc_join_req)
+__m_av (sc__sc_add__cm_sc_join_req)
+__n_av (sc__sc_wait_beacon__beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__n_av (sc__sc_wait_peer_associated__new_sta_associated,
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__m_av (sc__sc_building_tek__cm_get_key_cnf_pid3)
+__m_av (sc__sc_nmk_exchange__cm_set_key_cnf_pid3)
+__n_av (sc__sc_usta_track_beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__n_av (sc__sc_ucco_track_beacon,
+ (bsu_beacon_t *, beacon),
+ (cp_net_t *, net),
+ (cp_sta_t *, sta))
+__m_av (assoc__sc_wait_assoc_cnf__cc_assoc_cnf)
+__m_av (assoc__sc_associated__cm_get_key_req_pid_3)
+__m_av (assoc__sc_tek_exchanged__cm_set_key_req_pid_3)
+__m_av (assoc__sc_nmk_exchanged__cm_get_key_cnf_pid_0)
+
+__m_av (handover__start)
+__m_av (handover__handover_info_ind_receive)
+__0_av (handover__handover_ended)
+__0 (whoru_timeout_process)
+__m (process_cm_nw_stats_req)
+__m (process_cm_nw_info_req)
+__m (process_cm_link_stats_req)
+__m (process_cm_sta_cap_req)
+__m (vs__started__vs_get_snr_req)
+
+__m (vs__started__vs_get_tonemap_req)
+__m (vs__started__vs_get_link_stats_req)
+__m (vs__started__imac_get_discover_list_req)
+
+__m (vs__started__vs_get_ce_stats_req)
+__m (vs__started__vs_get_pb_stats_req)
diff --git a/cesar/cp/av/sta/action/test/utest/src/test_sta_action.c b/cesar/cp/av/sta/action/test/utest/src/test_sta_action.c
new file mode 100644
index 0000000000..2cec42d3b9
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/test_sta_action.c
@@ -0,0 +1,116 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_sta_action.c
+ * \brief Test sta/action.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/test_sta_action.h"
+
+#include "lib/test.h"
+
+void
+assoc_test_suite (test_t t);
+
+void
+drv_test_suite (test_t t);
+
+void
+info_test_suite (test_t t);
+
+void
+key_test_suite (test_t t);
+
+void
+bridge_test_suite (test_t t);
+
+void
+handover_test_suite (test_t t);
+
+void
+vs_test_suite (test_t t);
+
+void
+test_sta_action_init (test_sta_action_t *ctx)
+{
+#if CONFIG_TRACE
+ static trace_namespace_t namespace;
+ trace_buffer_add (&ctx->cp.trace, "cp", 8, 1, false, &namespace);
+#endif
+ memset (&ctx->cp.sta_action, 0, sizeof (cp_sta_action_t));
+ lib_rnd_init (&ctx->cp.rnd, 1234);
+ ctx->cp.mac_config = &ctx->mac_config;
+ ctx->cp.mac_store = mac_store_init ();
+ ctx->cp.sar = (void *) &ctx->cp;
+ ctx->cp.pbproc = NULL;
+ ctx->cp.cl = INVALID_PTR;
+ ctx->cp.bsu_aclf = &ctx->bsu_aclf;
+ cp_sta_mgr_init (&ctx->cp);
+}
+
+void
+test_sta_action_uninit (test_sta_action_t *ctx)
+{
+ cp_sta_mgr_uninit (&ctx->cp);
+ mac_store_uninit (ctx->cp.mac_store);
+#if CONFIG_TRACE
+ trace_buffer_remove (&ctx->cp.trace);
+#endif
+}
+
+void
+test_sta_action_reset (test_sta_action_t *ctx)
+{
+ cp_sta_mgr_uninit (&ctx->cp);
+ cp_sta_mgr_init (&ctx->cp);
+}
+
+void
+test_sta_action_create_our_net (test_sta_action_t *ctx, cp_nid_t nid,
+ cp_snid_t snid)
+{
+ cp_t *cp = &ctx->cp;
+ cp_sta_own_data_set_nid (cp, nid);
+ cp_sta_own_data_set_snid (cp, snid);
+ cp_net_t *our_net = cp_sta_mgr_add_avln (cp, snid, nid);
+ cp_sta_mgr_set_our_avln (cp, our_net);
+}
+
+void
+test_sta_action_beacon_create (
+ bsu_beacon_t *beacon, cp_nid_t nid, cp_snid_t snid, cp_tei_t stei,
+ mac_t mac)
+{
+ memset (beacon, 0, sizeof (bsu_beacon_t));
+ beacon->vf.bt = BSU_BEACON_TYPE_CENTRAL;
+ beacon->vf.nid = nid;
+ beacon->params.rx_parameters.snid = snid;
+ beacon->vf.stei = stei;
+ beacon->bmis.mac_address.present = MAC_IS_VALID (mac);
+ beacon->bmis.mac_address.mac_address = mac;
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init (t, argc, argv);
+ trace_init ();
+ assoc_test_suite (t);
+ drv_test_suite (t);
+ info_test_suite (t);
+ key_test_suite (t);
+ vs_test_suite (t);
+ bridge_test_suite (t);
+ handover_test_suite (t);
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/cp/av/sta/action/test/utest/src/vs.c b/cesar/cp/av/sta/action/test/utest/src/vs.c
new file mode 100644
index 0000000000..a918416577
--- /dev/null
+++ b/cesar/cp/av/sta/action/test/utest/src/vs.c
@@ -0,0 +1,988 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/vs.c
+ * \brief Test sta/action/vs.c
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "lib/scenario/scenario.h"
+#include "inc/test_sta_action.h"
+#include "ce/rx/bitloading/nsr.h"
+
+blk_t* nsr_block;
+
+void
+vs_get_snr_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+ const cp_tei_t tei_1 = 10;
+ const mac_t mac_1 = 0x111111111111ull;
+ const cp_nid_t our_nid = 0x111111111111ull;
+ u32 snr[CP_MSG_SNR_IN_MSG_NB];
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ /* Create our net/AVLN. */
+ test_sta_action_create_our_net (&ctx, our_nid, tei_1);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, my_net, tei_1, mac_1);
+ sta_t* station = mac_store_sta_get (cp->mac_store, tei_1);
+ station->rx_tonemaps->intervals->version = 2;
+ station->rx_tonemaps->intervals->intervals_nb = 3;
+ cp_sta_set_authenticated (cp, sta_1, true);
+
+ /* Create snr blocks */
+ const uint blk_size = BLK_SIZE / sizeof (u32);
+ u32 i = 0;
+ blk_t *last;
+ blk_t *first = blk_alloc_desc_range (PHY_CARRIER_NB / blk_size
+ + (PHY_CARRIER_NB % blk_size ? 1 : 0),
+ &last);
+ blk_t *cur = first;
+ u32* cur_data;
+
+ for (i = 0; i < PHY_CARRIER_NB; i++)
+ {
+ if (i % blk_size == 0)
+ {
+ if (i)
+ /* Get a new block. */
+ cur = cur->next;
+
+ /* Get current data. */
+ cur_data = (u32 *) cur->data;
+ }
+ cur_data[i % blk_size] = -i;
+ }
+
+ test_case_begin (t, "get snr : invalid message");
+ nsr_block = first;
+
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_snr_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_req_receive, .ok = false,
+ .mac_addr = mac_1, .tm_int_i = 0, .int_id = 1,
+ .carrier_gr = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "get snr : station not authenticated");
+ cp_sta_set_authenticated (cp, sta_1, false);
+ for (i = 0; i < CP_MSG_SNR_IN_MSG_NB; i++)
+ snr[i] = 0;
+
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_snr_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tm_int_i = 0,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .carrier_gr = 0),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_cnf_send, .peer = peer,
+ .result = CP_MSG_VS_GET_SNR_CNF_RESULT_FAILURE,
+ .int_id = 0,
+ .intervals_nb = 0,
+ .intervals = 0,
+ .tm_ber = 0,
+ .snr = snr),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_sta_set_authenticated (cp, sta_1, true);
+
+ test_case_begin (t, "get snr : invalid interval version");
+ for (i = 0; i < CP_MSG_SNR_IN_MSG_NB; i++)
+ snr[i] = 0;
+
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_snr_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_req_receive, .ok = true,
+ .mac_addr = mac_1, .tm_int_i = 0,
+ .int_id = 1,
+ .carrier_gr = 0),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_cnf_send, .peer = peer,
+ .result = CP_MSG_VS_GET_SNR_CNF_RESULT_BAD_TMP_INT_LIST_ID,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .intervals_nb =
+ station->rx_tonemaps->intervals->intervals_nb,
+ .intervals = station->rx_tonemaps->intervals,
+ .tm_ber = 0,
+ .snr = snr),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "get snr : request intervals only");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_snr_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tm_int_i = CP_MSG_VS_GET_SNR_REQ_INT_LIST_ONLY,
+ .int_id = 1,
+ .carrier_gr = 0),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_cnf_send, .peer = peer,
+ .result = CP_MSG_VS_GET_SNR_CNF_RESULT_SUCCESS,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .intervals_nb =
+ station->rx_tonemaps->intervals->intervals_nb,
+ .intervals = station->rx_tonemaps->intervals,
+ .tm_ber = 0,
+ .snr = snr),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "get snr : snr return ko");
+ nsr_block = 0;
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_snr_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tm_int_i = 0,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .carrier_gr = 0),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_cnf_send, .peer = peer,
+ .result = CP_MSG_VS_GET_SNR_CNF_RESULT_FAILURE,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .intervals_nb =
+ station->rx_tonemaps->intervals->intervals_nb,
+ .intervals = station->rx_tonemaps->intervals,
+ .tm_ber = 0,
+ .snr = snr),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "get snr : request is correct");
+ nsr_block = first;
+ int group;
+ for (group = 0; group < CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB; group++)
+ {
+ for (i = 0; i < CP_MSG_SNR_IN_MSG_NB; i++)
+ {
+ if (i * CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB + group <
+ PHY_CARRIER_OFFSET)
+ snr[i] = 0;
+ else if (i * CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB + group <
+ PHY_CARRIER_OFFSET + PHY_CARRIER_NB)
+ {
+ snr[i] = -(i * CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB + group -
+ PHY_CARRIER_OFFSET);
+ snr[i] /= CE_RX_BL_NSR_SOUND_RESCALE;
+ }
+ else
+ snr[i] = 0;
+ }
+
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_snr_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tm_int_i = 1,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .carrier_gr = group),
+ SCENARIO_EVENT (cp_msg_vs_get_snr_cnf_send, .peer = peer,
+ .result = CP_MSG_VS_GET_SNR_CNF_RESULT_SUCCESS,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .intervals_nb =
+ station->rx_tonemaps->intervals->intervals_nb,
+ .intervals = station->rx_tonemaps->intervals,
+ .tm_ber = 0,
+ .carrier_gr = group,
+ .snr = snr),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+ }
+
+ /* Cleanup. */
+ blk_release_desc_range (first, last);
+
+ blk_release (station);
+ slab_release (sta_1);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_1);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+vs_get_link_stats_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+ const cp_tei_t tei_1 = 10;
+ const mac_t mac_1 = 0x111111111111ull;
+ const cp_nid_t our_nid = 0x111111111111ull;
+ u8 lid_tx = 0;
+ u8 lid_rx = 1;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+ const cp_tei_t my_tei = 2;
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_case_begin (t, "vs_get_link_stats_req invalid message");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create our net/AVLN. */
+ test_sta_action_create_our_net (&ctx, our_nid, my_tei);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+
+ test_case_begin (t, "vs_get_link_stats_req invalid nid");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType = CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_STAT,
+ .ReqID = 1, .nid = 1, .lid = lid_tx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_TX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 1,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "vs_get_link_stats_req unknown mac");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType = CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_STAT,
+ .ReqID = 2, .nid = our_nid, .lid = lid_tx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_TX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 2,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create a station in the network */
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, my_net, tei_1, mac_1);
+
+ test_case_begin (t, "vs_get_link_stats_req unknown link");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType = CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_STAT,
+ .ReqID = 3, .nid = our_nid, .lid = lid_tx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_TX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 3,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create a tx link (tx=true, broadcast=false, mme=false) */
+ bool added = false;
+ mfs_t *m_tx = mac_store_mfs_add (cp->mac_store, true, false, false,
+ lid_tx, tei_1, &added);
+ m_tx->tx.stats.num_bad_pbs_crc = 123;
+
+ test_case_begin (t, "vs_get_link_stats_req valid tx link req");
+ test_begin (t, "ok")
+ {
+ test_fail_unless (added == true);
+
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType = CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_STAT,
+ .ReqID = 4, .nid = our_nid, .lid = lid_tx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_TX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 4,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS,
+ .Bad_CRC = 123),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create a rx link (tx=false, broadcast=false, mme=false) */
+ added = false;
+ mfs_t *m_rx = mac_store_mfs_add (cp->mac_store, false, false, false,
+ lid_rx, tei_1, &added);
+ m_rx->rx.stats.num_bad_pbs_crc = 321;
+
+ test_case_begin (t, "vs_get_link_stats_req valid rx link req");
+ test_begin (t, "ok")
+ {
+ test_fail_unless (added == true);
+
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType = CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_STAT,
+ .ReqID = 5, .nid = our_nid, .lid = lid_rx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_RX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 5,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS,
+ .Bad_CRC = 321),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_case_begin (t, "vs_get_link_stats_req valid tx link get and reset");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType =
+ CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_RESET_STAT,
+ .ReqID = 6, .nid = our_nid, .lid = lid_tx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_TX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 6,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS,
+ .Bad_CRC = 123),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ test_fail_unless (m_tx->tx.stats.num_bad_pbs_crc == 0);
+ } test_end;
+
+ test_case_begin (t, "link_stats_req valid rx link reset");
+ test_begin (t, "ok")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_link_stats_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_req_receive, .ok = true,
+ .ReqType = CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_RESET_STAT,
+ .ReqID = 7, .nid = our_nid, .lid = lid_rx,
+ .TLFlag = CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_RX_LINK,
+ .Mgmt_Flag =
+ CP_MSG_VS_GET_LINK_STATS_REQ_MGMTFLAG_NOT_MGMT_LINK,
+ .dasa = mac_1),
+ SCENARIO_EVENT (cp_msg_vs_get_link_stats_cnf_send,
+ .peer = peer, .ReqID = 7,
+ .result = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS,
+ .Bad_CRC = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ test_fail_unless (m_tx->tx.stats.num_bad_pbs_crc == 0);
+ } test_end;
+
+ /* Cleanup. */
+ mac_store_mfs_remove (cp->mac_store, m_rx);
+ blk_release (m_rx);
+ mac_store_mfs_remove (cp->mac_store, m_tx);
+ blk_release (m_tx);
+ slab_release (sta_1);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_1);
+
+ test_sta_action_uninit (&ctx);
+}
+
+void
+vs_get_tonemap_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+ const cp_tei_t tei_1 = 10;
+ const mac_t mac_1 = 0x111111111111ull;
+ const cp_nid_t our_nid = 0x111111111111ull;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_case_begin (t, "get tonemap");
+ test_begin (t, "get_tonemap_req_receive return false")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = false,
+ .mac_addr = mac_1, .tmi = 0, .int_id = 0,
+ .dir = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "invalid mac address")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = true,
+ .mac_addr = mac_1, .tmi = 0x00, .int_id = 0,
+ .dir = CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_RX),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE,
+ .beacon_delta = 0, .int_id = 0,
+ .tms = 0,
+ .tmi = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create our net/AVLN. */
+ test_sta_action_create_our_net (&ctx, our_nid, tei_1);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, my_net, tei_1, mac_1);
+ sta_t* station = mac_store_sta_get (cp->mac_store, tei_1);
+ cp_sta_set_authenticated (cp, sta_1, true);
+
+ test_begin (t, "tonemap doesn't exist")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tmi = 4,
+ .int_id = station->tx_tonemaps->intervals->version,
+ .dir = CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_TX),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE,
+ .beacon_delta = 0,
+ .int_id = station->tx_tonemaps->intervals->version,
+ .tms = 0,
+ .tmi = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ station->tx_tonemaps->tm[4] = tonemap_alloc ();
+ station->rx_tonemaps->tm[4] = tonemap_alloc ();
+ station->tx_tonemaps->intervals->version = 23;
+ station->rx_tonemaps->intervals->version = 15;
+
+ test_begin (t, "correct tonemap")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tmi = 4,
+ .int_id = station->tx_tonemaps->intervals->version,
+ .dir = CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_TX),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_SUCCESS,
+ .beacon_delta = 0,
+ .int_id = station->tx_tonemaps->intervals->version,
+ .tms = station->tx_tonemaps,
+ .tmi = 4),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_sta_set_authenticated (cp, sta_1, false);
+
+ test_begin (t, "requesting station is not part of our avln")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = true,
+ .mac_addr = mac_1, .tmi = 0x00, .int_id = 0,
+ .dir = CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_RX),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE,
+ .beacon_delta = 0, .int_id = 0,
+ .tms = 0,
+ .tmi = 0),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_sta_set_authenticated (cp, sta_1, true);
+
+ /* In this test we try to get the tonemap tx with the tmi version of
+ * the rx, which is invalid.
+ */
+ test_begin (t, "wrong interval list index")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tmi = 4,
+ .int_id = station->rx_tonemaps->intervals->version,
+ .dir = CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_TX),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_cnf_send,
+ .peer = peer,
+ .result =
+ CP_MSG_VS_GET_TONEMAP_CNF_RESULT_BAD_TMP_INT_LIST_ID,
+ .beacon_delta = 0,
+ .int_id = station->tx_tonemaps->intervals->version,
+ .tms = station->tx_tonemaps,
+ .tmi = 4),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "only get intervals and tonemaps")
+ {
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (vs__started__vs_get_tonemap_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_req_receive, .ok = true,
+ .mac_addr = mac_1,
+ .tmi = CP_MSG_VS_GET_TONEMAP_TMI_AND_INT_ONLY,
+ .int_id = 0,
+ .dir = CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_TX),
+ SCENARIO_EVENT (cp_msg_vs_get_tonemap_cnf_send,
+ .peer = peer,
+ .result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_SUCCESS,
+ .beacon_delta = 0,
+ .int_id = station->tx_tonemaps->intervals->version,
+ .tms = station->tx_tonemaps,
+ .tmi = CP_MSG_VS_GET_TONEMAP_TMI_AND_INT_ONLY),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Cleanup. */
+ blk_release (station);
+ slab_release (sta_1);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+imac_get_discover_list_test_case (test_t t)
+{
+ /* init test context */
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+ const cp_tei_t tei_1 = 10;
+ const mac_t mac_1 = 0x111111111111ull;
+ const cp_nid_t our_nid = 0x111111111111ull;
+
+ /* init globals */
+ scenario_globals_t globals = {
+ .cp = &ctx.cp,
+ };
+
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_case_begin (t, "get discover list");
+
+ test_begin (t, "get_discover_list_req_receive return false")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__imac_get_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_req_receive,
+ .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "get_discover_list_req_receive return true, no sta")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__imac_get_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send_begin,
+ .peer = peer,
+ .result = CP_MSG_IMAC_GET_DISCOVER_LIST_RESULT_SUCCESS,
+ .version = CP_MSG_GET_DISCOVER_LIST_VERSION,
+ .num_stations = 0),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Create our net/AVLN. */
+ test_sta_action_create_our_net (&ctx, our_nid, tei_1);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (cp);
+
+ cp_sta_t *sta_1 = cp_sta_mgr_sta_add (cp, my_net, tei_1, mac_1);
+ sta_t *sta1 = mac_store_sta_get (cp->mac_store, tei_1);
+ sta1->tx_tonemaps->intervals->intervals_nb = 0;
+ sta1->tx_tonemaps->default_tmi = PHY_MOD_ROBO;
+ sta1->rx_tonemaps->intervals->intervals_nb = 0;
+ sta1->rx_tonemaps->default_tmi = PHY_MOD_HS_ROBO;
+ cp->mac_config->tonemask_info.tonemap_robo[PHY_MOD_ROBO].ble = 0x15;
+ cp->mac_config->tonemask_info.tonemap_robo[PHY_MOD_HS_ROBO].ble = 0x16;
+
+ test_begin (t, "one station in our net")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__imac_get_discover_list_req, .peer = peer),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send_begin,
+ .peer = peer,
+ .result = CP_MSG_IMAC_GET_DISCOVER_LIST_RESULT_SUCCESS,
+ .version = CP_MSG_GET_DISCOVER_LIST_VERSION,
+ .num_stations = 1),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send,
+ .mac = mac_1,
+ .ble_tx = 69,
+ .ble_rx = 138),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ cp_net_t *other_net = cp_sta_mgr_add_avln (cp, 5, our_nid+1);
+ cp_sta_t *sta_2 = cp_sta_mgr_sta_add (cp, other_net, tei_1+1, mac_1+1);
+
+ cp_sta_t *sta_3 = cp_sta_mgr_sta_add (cp, my_net, tei_1+2, mac_1+2);
+ sta_t *sta3 = mac_store_sta_get (cp->mac_store, tei_1+2);
+ sta3->tx_tonemaps->intervals->intervals_nb = 0;
+ sta3->tx_tonemaps->default_tmi = TONEMAP_INDEX_NEGOTIATED_FIRST;
+
+ sta3->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST] = tonemap_alloc ();
+ sta3->tx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST]->ble = 0x23;
+
+ sta3->rx_tonemaps->intervals->intervals_nb = 4;
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST] = tonemap_alloc ();
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST]->ble = 0xFF;
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 1] = tonemap_alloc ();
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 1]->ble = 0x00;
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 2] = tonemap_alloc ();
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 2]->ble = 0x08;
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 3] = tonemap_alloc ();
+ sta3->rx_tonemaps->tm[TONEMAP_INDEX_NEGOTIATED_FIRST + 3]->ble = 0x0F;
+
+ sta3->rx_tonemaps->intervals->interval[0].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST;
+ sta3->rx_tonemaps->intervals->interval[0].end_offset_atu = 10;
+ sta3->rx_tonemaps->intervals->interval[1].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 1;
+ sta3->rx_tonemaps->intervals->interval[1].end_offset_atu = 100;
+ sta3->rx_tonemaps->intervals->interval[2].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 2;
+ sta3->rx_tonemaps->intervals->interval[2].end_offset_atu = 400;
+ sta3->rx_tonemaps->intervals->interval[3].tmi =
+ TONEMAP_INDEX_NEGOTIATED_FIRST + 3;
+ sta3->rx_tonemaps->intervals->interval[3].end_offset_atu = 500;
+
+ test_begin (t, "one more station in our net and one in an other net")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__imac_get_discover_list_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_req_receive,
+ .ok = true),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send_begin,
+ .peer = peer,
+ .result = CP_MSG_IMAC_GET_DISCOVER_LIST_RESULT_SUCCESS,
+ .version = CP_MSG_GET_DISCOVER_LIST_VERSION,
+ .num_stations = 3),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send,
+ .mac = mac_1,
+ .ble_tx = 69,
+ .ble_rx = 138),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send,
+ .mac = mac_1+2,
+ .ble_tx = 18,
+ .ble_rx = 65),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send,
+ .mac = mac_1+1,
+ .ble_tx = 0,
+ .ble_rx = 0),
+ SCENARIO_EVENT (cp_msg_imac_get_discover_list_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Cleanup. */
+ blk_release (sta1);
+ blk_release (sta3);
+ slab_release (sta_3);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_1+2);
+ slab_release (sta_2);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_1+1);
+ slab_release (sta_1);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac_1);
+
+ test_sta_action_uninit (&ctx);
+}
+
+void
+vs_get_ce_stats_test_case (test_t t)
+{
+ test_case_begin (t, "vs_get_ce_stats");
+ test_sta_action_t ctx;
+ cp_t *cp = &ctx.cp;
+
+ /* Init globals. */
+ scenario_globals_t globals =
+ {
+ .cp = &ctx.cp,
+ };
+
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_begin (t, "invalid address")
+ {
+ mac_t mac = MAC_ZERO;
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_ce_stats_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_ce_stats_req_receive,
+ .mac = mac,
+ .ok = false),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_begin (t, "non existing mac")
+ {
+ mac_t mac = 0x42ull;
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_ce_stats_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_ce_stats_req_receive,
+ .mac = mac,
+ .ok = true),
+ SCENARIO_EVENT (
+ cp_msg_vs_get_ce_stats_cnf_send,
+ .peer = peer,
+ .version = 0,
+ .result = CP_MSG_VS_GET_CE_STATS_CNF_RESULT_FAILURE,
+ .sta = NULL,
+ .ti = NULL),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ /* Add a station. */
+ mac_t mac = 0x42ull;
+ const cp_tei_t tei = 10;
+ const cp_nid_t our_nid = 0x111111111111ull;
+ test_sta_action_create_our_net (&ctx, our_nid, tei);
+ cp_net_t *my_net = cp_sta_mgr_get_our_avln (&ctx.cp);
+ cp_sta_t *cp_sta = cp_sta_mgr_sta_add (cp, my_net, tei, mac);
+ sta_t *sta = mac_store_sta_get (cp->mac_store, tei);
+ cp_sta_set_authenticated (cp, cp_sta, true);
+
+ test_begin (t, "existing mac")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_ce_stats_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_ce_stats_req_receive,
+ .mac = mac,
+ .ok = true),
+ SCENARIO_EVENT (
+ cp_msg_vs_get_ce_stats_cnf_send,
+ .peer = peer,
+ .version = 0,
+ .result = CP_MSG_VS_GET_CE_STATS_CNF_RESULT_SUCCESS,
+ .sta = sta,
+ .ti = &cp->mac_config->tonemask_info),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ } test_end;
+
+ cp_sta_set_authenticated (cp, cp_sta, false);
+
+ test_begin (t, "existing mac, but stations not authenticated")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_ce_stats_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_ce_stats_req_receive,
+ .mac = mac,
+ .ok = true),
+ SCENARIO_EVENT (
+ cp_msg_vs_get_ce_stats_cnf_send,
+ .peer = peer,
+ .version = 0,
+ .result = CP_MSG_VS_GET_CE_STATS_CNF_RESULT_FAILURE,
+ .sta = NULL,
+ .ti = NULL),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+
+ } test_end;
+
+ blk_release (sta);
+ slab_release (cp_sta);
+ cp_sta_mgr_sta_remove_from_mac (cp, mac);
+ test_sta_action_uninit (&ctx);
+}
+
+void
+vs_get_pb_stats_test_case (test_t t)
+{
+ test_sta_action_t ctx;
+
+ /* Init globals. */
+ scenario_globals_t globals =
+ {
+ .cp = &ctx.cp,
+ };
+
+ cp_mme_peer_t peer = CP_MME_PEER (0x112233445577ull, 5);
+ cp_mme_tx_t mme_to_send;
+ globals.mme = &mme_to_send;
+
+ test_sta_action_init (&ctx);
+
+ test_case_begin (t, "vs_get_pb_stats");
+ test_begin (t, "basic behavior")
+ {
+ scenario_entry_t entries[] =
+ {
+ SCENARIO_ACTION (vs__started__vs_get_pb_stats_req,
+ .peer = peer),
+ SCENARIO_EVENT (cp_msg_vs_get_pb_stats_req_receive,
+ .stei_filter = MAC_TEI_UNASSOCIATED,
+ .ok = true),
+ SCENARIO_EVENT (
+ cp_msg_vs_get_pb_stats_cnf_send_begin,
+ .peer = peer,
+ .nb_measures = 0),
+ SCENARIO_EVENT (
+ cp_msg_vs_get_pb_stats_cnf_send_measure,
+ .start_to_read = 0,
+ .nb_entries = 0),
+ SCENARIO_EVENT (
+ cp_msg_vs_get_pb_stats_cnf_send_end),
+ SCENARIO_END
+ };
+ scenario_run (t, entries, &globals);
+ } test_end;
+
+ test_sta_action_uninit (&ctx);
+}
+
+void
+vs_test_suite (test_t t)
+{
+ test_suite_begin (t, "vs");
+ vs_get_tonemap_test_case (t);
+ vs_get_link_stats_test_case (t);
+ imac_get_discover_list_test_case (t);
+ vs_get_snr_test_case (t);
+ vs_get_ce_stats_test_case (t);
+ vs_get_pb_stats_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
diff --git a/cesar/cp/av/sta/mgr/Module b/cesar/cp/av/sta/mgr/Module
new file mode 100644
index 0000000000..d6a9a3d666
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/Module
@@ -0,0 +1,3 @@
+SOURCES := sta_own_data.c sta_mgr.c
+
+MODULES := cp/sta/mgr
diff --git a/cesar/cp/av/sta/mgr/src/sta_mgr.c b/cesar/cp/av/sta/mgr/src/sta_mgr.c
new file mode 100644
index 0000000000..543e97dfca
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/src/sta_mgr.c
@@ -0,0 +1,388 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/mgr/src/sta_mgr.c
+ * \brief Station manager source.
+ * \ingroup cp_av_sta_mgr
+ *
+ */
+#include "common/std.h"
+
+#include "cp/defs.h"
+#include "cp/cp.h"
+#include "cp/fsm/fsm.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/sta/mgr/sta_own_data.h"
+#include "cp/sta/core/core.h"
+#include "cp/cco/action/cco_action.h"
+#include "cl/cl_mactotei.h"
+#include "cl/brg_rx.h"
+#include "mac/sar/sar.h"
+
+#include "cp/inc/context.h"
+#include "cp/sta/mgr/inc/sta.h"
+#include "cp/sta/mgr/inc/net.h"
+#include "cp/sta/mgr/inc/sta_mgr.h"
+#include "cp/sta/mgr/inc/sta_own_data.h"
+#include "cp/av/cco/action/cco_action.h"
+
+void
+cp_av_sta_mgr_init (cp_t *ctx)
+{
+ dbg_assert (ctx);
+
+ memset (&ctx->sta_mgr, 0, sizeof (cp_sta_mgr_t));
+
+ // Initialise the station own data.
+ cp_sta_own_data_init (ctx);
+
+ // Initialise the list of releasing stations.
+ list_init (&ctx->sta_mgr.release_sta_list);
+
+ // Initialise the slab cache.
+ slab_cache_init (&ctx->sta_mgr.sta_slab_cache,
+ "Station cache",
+ sizeof (cp_sta_private_t),
+ (slab_object_destructor_t) cp_sta_uninit);
+
+ // Initialise the set of station sorted by mac addresses.
+ set_init (&ctx->sta_mgr.stas, cp_sta_mgr_sta_mac_address_less);
+}
+
+static void
+cp_av_sta_mgr_sta_remove_common (cp_t *ctx, cp_sta_t * station)
+{
+ set_t *set;
+ cp_sta_private_t *sta = (cp_sta_private_t *) station;
+ cp_net_t *net;
+
+ dbg_assert (ctx);
+ dbg_assert (sta);
+ dbg_assert (sta->net);
+
+ net = sta->net;
+
+ // If the station is CCo, modify the net CCo pointer to NULL.
+ if (cp_sta_get_cco_status(station))
+ net->cco = NULL;
+
+ // If the station is PCo to communicate with the CCo, modify the
+ // pointer in the net.
+ if (net->pco == station)
+ net->pco = NULL;
+
+ set = (cp_sta_get_tei (&sta->public_data)) ?
+ &sta->net->associated_stas : &sta->net->unassociated_stas;
+ /* Remove the station from its net. */
+ set_remove (set, &sta->public_data.node_net);
+
+ /* Remove the station from the station manager. If the mac address of the
+ * station is broadcast, the station is not in the set. */
+ if (sta->mac_address != MAC_BROADCAST)
+ set_remove (&ctx->sta_mgr.stas, &sta->public_data.node_sta_mgr);
+
+ /* decrease the visible counter. */
+ if (sta->visible)
+ sta->net->num_visible_stas --;
+
+ /* decrease the number of stations. */
+ sta->net->num_stas --;
+
+ if (MAC_TEI_IS_STA (cp_sta_get_tei (&sta->public_data)))
+ sta->net->num_associated_stas--;
+ if (net == ctx->sta_mgr.our_avln && sta->net->num_associated_stas == 0)
+ cp_fsm_post_new_event (ctx, bare, sta_status_changed);
+
+ cp_sta_mgr_elects_sta_partial_ack (ctx);
+}
+
+void
+cp_av_sta_mgr_release_station (cp_t *ctx, cp_tei_t tei)
+{
+ cp_sta_t *sta;
+ cp_net_t *net;
+
+ dbg_assert (ctx);
+ dbg_assert (tei);
+ dbg_assert (cp_sta_own_data_get_cco_status (ctx));
+
+ net = cp_sta_mgr_get_our_avln (ctx);
+ sta = cp_sta_mgr_sta_get_assoc (ctx, net, tei);
+ dbg_assert (sta);
+
+ list_init_node (&sta->release_node);
+ list_push (&ctx->sta_mgr.release_sta_list, &sta->release_node);
+
+ /* Set the station tei_lease_ms to 5 min as indicated in the HPAV
+ * specification. */
+ sta->tei_lease_date_ms = CP_STA_MGR_STATION_RELEASE_MS +
+ cp_sta_core_get_date_ms (ctx);
+
+ /* Remove the station. */
+ cp_av_sta_mgr_sta_remove_common (ctx, sta);
+ /* Remove the reference provided. */
+ slab_release (sta);
+
+ /* Check if our net is empty, if it is post an FSM event
+ * cco__all_sta_leaved */
+ if (cp_sta_own_data_get_tei (ctx)
+ && net == cp_sta_mgr_get_our_avln (ctx)
+ && cp_net_is_empty (ctx, net))
+ cp_fsm_trigger_new_event (ctx, bare, cco__all_sta_leaved);
+}
+
+void
+cp_av_sta_mgr_sta_remove (cp_t *ctx, cp_sta_t * station)
+{
+ cp_sta_private_t *sta = (cp_sta_private_t *) station;
+
+ dbg_assert (ctx);
+ dbg_assert (sta);
+
+ if ((sta->net == ctx->sta_mgr.our_avln)
+ && (MAC_TEI_IS_STA (sta->tei)))
+ {
+ sar_sta_remove (ctx->sar, sta->tei);
+ }
+
+ cp_av_sta_mgr_sta_remove_common (ctx, station);
+
+ /* Release the station. */
+ slab_release (sta);
+}
+
+void
+cp_av_sta_mgr_set_tracking (cp_t *ctx, cp_snid_t snid, cp_nid_t nid)
+{
+ dbg_assert (ctx);
+ dbg_assert (HPAV_NID_IS_VALID (nid));
+#if CONFIG_DEBUG
+ bool found = false;
+ cp_net_t *net;
+ for (net = cp_sta_mgr_get_first_avln (ctx);
+ net;
+ net = cp_sta_mgr_get_next_avln (ctx, net))
+ {
+ if (cp_net_get_snid (ctx, net) == snid
+ && cp_net_get_nid (ctx, net) == nid)
+ found = true;
+ }
+ dbg_assert (found);
+#endif
+ ctx->sta_mgr.sta_own_data.snid = snid;
+}
+
+void
+cp_av_sta_mgr_garbage (cp_t *ctx)
+{
+ cp_sta_t *sta;
+ cp_net_t *net;
+ dbg_assert (ctx);
+ u32 now = cp_sta_core_get_date_ms (ctx);
+ for (net = cp_sta_mgr_get_first_avln (ctx);
+ net;
+ net = cp_sta_mgr_get_next_avln (ctx, net))
+ {
+ if (net != ctx->sta_mgr.our_avln)
+ cp_net_garbage_stations (ctx, net, now);
+ if (net->blacklisted
+ && less_mod2p32 ( net->blacklisted_reset_date, phy_date ()))
+ net->blacklisted = false;
+ }
+ /* Release the release stations if possible. */
+ while ((sta = cp_sta_mgr_release_sta_get_first (ctx))
+ && (less_mod2p32 (sta->tei_lease_date_ms, now)))
+ {
+ /* remove the station from the list. */
+ list_remove (&ctx->sta_mgr.release_sta_list,
+ &sta->release_node);
+
+ sar_sta_remove (ctx->sar, cp_sta_get_tei (sta));
+
+ if (cp_sta_own_data_get_cco_status (ctx))
+ {
+ /* Request the CCo to release the TEI. */
+ cp_cco_action_tei_release (ctx, cp_sta_get_tei (sta));
+ }
+ slab_release (sta);
+ }
+ cp_sta_mgr_elects_sta_partial_ack (ctx);
+ if (cp_sta_mgr_net_list_is_empty (ctx))
+ cp_fsm_trigger_new_event (ctx, bare, net_list_empty);
+ /* Recommit to dataplane. */
+ cp_sta_mgr_commit_to_dataplane (ctx);
+}
+
+cp_sta_t *
+cp_av_sta_mgr_sta_add (cp_t *ctx, cp_net_t *net, cp_tei_t tei, mac_t mac_address)
+{
+ cp_sta_t *sta = NULL;
+ cp_sta_t *sta_from_tei = NULL;
+ dbg_assert (ctx);
+ dbg_assert (net);
+ dbg_assert ((tei && mac_address == MAC_BROADCAST)
+ || (mac_address & ~MAC_BROADCAST) == 0);
+ /* Try to get the station by the TEI. */
+ if (tei)
+ sta_from_tei = cp_sta_mgr_sta_get_assoc (ctx, net, tei);
+ /* Try to get the station by the mac address. */
+ if (MAC_IS_VALID(mac_address))
+ sta = cp_sta_mgr_sta_get_from_mac (ctx, mac_address);
+
+ /* Does the two station match ? */
+ if (sta && sta_from_tei)
+ {
+ if (sta != sta_from_tei)
+ /* remove the station got using the TEI. */
+ cp_sta_mgr_sta_remove_assoc (ctx, net, tei);
+ slab_release (sta_from_tei);
+ }
+ else if (!sta)
+ sta = sta_from_tei;
+
+ if (!sta)
+ {
+ sta = cp_sta_mgr_sta_add_realy (ctx, net, tei, mac_address);
+ }
+ else
+ {
+ cp_tei_t sta_tei = cp_sta_get_tei (sta);
+ mac_t sta_mac = cp_sta_get_mac_address (sta);
+ cp_net_t *sta_net = cp_sta_get_net (sta);
+ /* Last case. The network change. */
+ if (sta_net != net)
+ {
+ cp_sta_mgr_sta_remove (ctx, sta);
+ slab_release (sta);
+ sta = cp_sta_mgr_sta_add_realy (ctx, net, tei, mac_address);
+ }
+ /* Second case,
+ * - station's TEI == TEI and != MAC_TEI_UNASSOCIATED.
+ * - station's Mac address was broadcast. */
+ else if ((sta_tei == tei)
+ && (tei != MAC_TEI_UNASSOCIATED)
+ && (sta_mac != mac_address)
+ && (sta_mac == MAC_BROADCAST))
+ {
+ /* Add the station mgr node to the set. */
+ cp_sta_private_t *p = PARENT_OF (cp_sta_private_t, public_data,
+ sta);
+ p->mac_address = mac_address;
+ set_insert (&ctx->sta_mgr.stas, &sta->node_sta_mgr);
+ }
+ /* First case only the TEI change from the previous state. */
+ else if ((sta_tei == MAC_TEI_UNASSOCIATED
+ && tei != MAC_TEI_UNASSOCIATED
+ && sta_mac == mac_address)
+ /* Third case, only the station's TEI change. */
+ || (sta_tei != tei
+ && tei != MAC_TEI_UNASSOCIATED
+ && sta_mac == mac_address
+ && mac_address != MAC_BROADCAST)
+ /* Fourth case, only the station's TEI change from a
+ * associated tei to the unassociated TEI.. */
+ || (sta_tei != tei
+ && tei == MAC_TEI_UNASSOCIATED
+ && sta_mac == mac_address
+ && mac_address != MAC_BROADCAST)
+ /* Fifth case, Same TEI only the mac address change from A
+ * to B without being null or broadcast. */
+ || (sta_tei == tei
+ && sta_mac != mac_address
+ && MAC_IS_VALID (sta_mac)
+ && MAC_IS_VALID (mac_address))
+ )
+ {
+ /* Remove the station. */
+ cp_sta_mgr_sta_remove (ctx, sta);
+ slab_release (sta);
+ /* Add the station with the new TEI. */
+ sta = cp_sta_mgr_sta_add_realy (ctx, net, tei, mac_address);
+ }
+ }
+ /* Update the last seen value. */
+ if (ctx->sta_mgr.sta_own_data.is_cco
+ && cp_sta_get_net (sta) == ctx->sta_mgr.our_avln)
+ sta->expired_date_ms = cp_sta_core_get_date_ms (ctx)
+ + HPAV_STA_PRESENCE_TIMEOUT_INSIDE_AVLN_MS;
+ else
+ sta->expired_date_ms = cp_sta_core_get_date_ms (ctx)
+ + HPAV_DISCOVERED_LIST_EXPIRE_TIME_MS;
+ return sta;
+}
+
+void
+cp_av_sta_mgr_commit_to_dataplane (cp_t *ctx)
+{
+ cp_sta_t *sta;
+ cl_mactotei_blk_t *mactotei;
+
+ dbg_assert (ctx);
+ dbg_assert (ctx->cl);
+
+ // If the net does not correspond to the AVLN, do not commit.
+ if (!ctx->sta_mgr.our_avln)
+ return;
+
+ // Get the first station from the set.
+ if (set_empty (&ctx->sta_mgr.our_avln->associated_stas))
+ {
+ cl_mactotei_release_table (ctx->cl);
+ }
+ else
+ {
+ // There is at least a station in the network list.
+ mactotei = cl_mactotei_new ();
+ uint i;
+
+ for (sta = cp_net_sta_get_first (
+ ctx, ctx->sta_mgr.our_avln, CP_NET_STA_ASSOC);
+ sta;
+ sta = cp_net_sta_get_next (ctx, ctx->sta_mgr.our_avln, sta))
+ {
+ cp_sta_private_t *sta_private =
+ PARENT_OF (cp_sta_private_t, public_data, sta);
+ // Copy all the bridge table from the previous list.
+ cl_mactotei_copy_tei_and_tag (ctx->cl, mactotei, sta_private->tei,
+ sta_private->tei);
+ // Add the current station.
+ cl_mactotei_addr_add (mactotei, sta_private->mac_address,
+ sta_private->tei, MAC_TEI_UNASSOCIATED);
+ }
+ /* Get the bridge RX table of the CL. */
+ cl_brg_rx_t *brg_rx_table = cl_brg_rx_get (ctx->cl);
+ if (brg_rx_table)
+ {
+ /* Add bridged Mac addresses to the mac to tei.
+ * If the bridged MAC address is already present in the mac2tei,
+ * the extra_info will be updated using the bridged tei. */
+ for (i = 0; i < brg_rx_table->nb_entry; i++)
+ {
+ sta = cp_sta_mgr_sta_get_assoc (
+ ctx, ctx->sta_mgr.our_avln,
+ brg_rx_table->entry[i].tei);
+ if (sta)
+ {
+ cl_mactotei_addr_add (
+ mactotei, brg_rx_table->entry[i].mac,
+ brg_rx_table->entry[i].tei,
+ brg_rx_table->entry[i].tei);
+ slab_release (sta);
+ }
+ }
+ blk_release (brg_rx_table);
+ }
+
+ // Copy all the groups list table from the previous list.
+ cl_mactotei_copy_tei (ctx->cl, mactotei, MAC_TEI_BCAST);
+
+ // Request the CL to use the table.
+ cl_mactotei_use_table (ctx->cl, mactotei);
+ cl_update_igmp_groups (ctx->cl);
+ }
+}
diff --git a/cesar/cp/av/sta/mgr/src/sta_own_data.c b/cesar/cp/av/sta/mgr/src/sta_own_data.c
new file mode 100644
index 0000000000..edeb0cf253
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/src/sta_own_data.c
@@ -0,0 +1,87 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/data/src/sta_own_data.c
+ * \brief Station data source.
+ * \ingroup cp_sta_data
+ *
+ */
+#include "common/std.h"
+#include "string.h"
+
+#include "lib/dbg.h"
+#include "lib/bitstream.h"
+#include "cp/fsm/fsm.h"
+#include "bsu/bsu.h"
+#include "hal/gpio/gpio.h"
+
+/* Public interfaces. */
+#include "cp/sta/mgr/sta_own_data.h"
+#include "cp/msg/msg.h"
+
+/* Private interfaces. */
+#include "cp/inc/context.h"
+#include "cp/sta/mgr/inc/sta_own_data.h"
+
+/**
+ * Initialise the station own data to default values.
+ * \param ctx the module context.
+ */
+void
+cp_av_sta_own_data_init (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ memset (&ctx->sta_mgr.sta_own_data, 0,
+ sizeof (cp_sta_own_data_private_t));
+ /* Store the hybrid mode. */
+ ctx->sta_mgr.sta_own_data.public.hybrid_mode =
+ MAC_COEXISTENCE_HYBRID_DELIMITERS_MODE;
+ /* Get an snid. */
+ ctx->sta_mgr.sta_own_data.snid =
+ lib_rnd_uniform (&ctx->rnd, HPAV_SNID_NB);
+}
+
+bool
+cp_av_sta_own_data_set_nmk (cp_t *ctx, const cp_key_t nmk,
+ cp_msg_drv_sta_set_key_type_t type)
+{
+ dbg_assert (ctx);
+ dbg_assert (type < CP_MSG_DRV_STA_SET_KEY_TYPE_NB);
+
+ uint i;
+ cp_key_t current_key = cp_sta_own_data_get_nmk (ctx);
+
+ for (i = 0; i < COUNT(nmk.key) ;i++)
+ if (nmk.key[i] != current_key.key[i])
+ break;
+
+ if (i < COUNT(nmk.key))
+ {
+ ctx->sta_mgr.sta_own_data.nmk = nmk;
+
+ /* Report new computed values to HLE. */
+ cp_mme_peer_t peer = CP_MME_PEER (cp_sta_own_data_get_mac_address (ctx),
+ MAC_TEI_FOREIGN);
+ cp_nid_t nid = 0;
+ cp_security_level_t sl = 0;
+
+ if (type == CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_NID)
+ nid = cp_sta_own_data_get_nid (ctx);
+ else
+ sl = cp_sta_own_data_get_security_level (ctx);
+
+ cp_msg_drv_sta_set_key_ind_send (ctx, &peer,
+ nmk,
+ type,
+ nid,
+ sl);
+ return true;
+ }
+
+ return false;
+}
diff --git a/cesar/cp/av/sta/mgr/sta_mgr.h b/cesar/cp/av/sta/mgr/sta_mgr.h
new file mode 100644
index 0000000000..bd52c8ce8d
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/sta_mgr.h
@@ -0,0 +1,35 @@
+#ifndef cp_av_sta_mgr_h
+#define cp_av_sta_mgr_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/av/sta/mgr/sta_mgr.h
+ * \brief Station Manager.
+ * \ingroup cp_av_sta_mgr
+ *
+ * Station and AVLN manager.
+ */
+#include "cp/sta/mgr/net.h"
+
+BEGIN_DECLS
+
+/**
+ * Set the SNID of the station to track the correct AVLN.
+ * \param ctx the module context.
+ * \param snid the station SNID.
+ * \param nid the network identifier to track.
+ *
+ * Be careful, this function does not modify our AVLN snid to do some use
+ * cp_sta_own_data_set_snid.
+ */
+void
+cp_av_sta_mgr_set_tracking (cp_t *ctx, cp_snid_t snid, cp_nid_t nid);
+
+END_DECLS
+
+#endif /* cp_av_sta_mgr_h */
diff --git a/cesar/cp/av/sta/mgr/test/utest/Config b/cesar/cp/av/sta/mgr/test/utest/Config
new file mode 100644
index 0000000000..f720280e07
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/Config
@@ -0,0 +1,3 @@
+CONFIG_CP_AV = y
+CONFIG_DEBUG_FATAL_CATCH = y
+CONFIG_RESTRACK = y
diff --git a/cesar/cp/av/sta/mgr/test/utest/Makefile b/cesar/cp/av/sta/mgr/test/utest/Makefile
new file mode 100644
index 0000000000..71c6c9f850
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/Makefile
@@ -0,0 +1,15 @@
+BASE = ../../../../../..
+
+INCLUDES = cp/av/sta/mgr/test/utest/override
+
+HOST_PROGRAMS = test_sta_mgr
+test_sta_mgr_SOURCES = core_stub.c net_test.c sar_stub.c sta_mgr.c \
+ sta-test.c station_test.c test_sta_mgr.c
+test_sta_mgr_MODULES = lib cp/av/sta/mgr mac/common cp/av/fsm/stub \
+ cp/av/cco/action/stub bsu/stub cp/msg/stub \
+ cl cl/stub hal/ipmbox/stub
+test_sta_mgr_CONFIG_MODULES = cp
+
+cl_MODULE_SOURCES = cl_mactotei.c brg_rx.c
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/cp/av/sta/mgr/test/utest/doc/Makefile b/cesar/cp/av/sta/mgr/test/utest/doc/Makefile
new file mode 100644
index 0000000000..bc8795eaad
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/doc/Makefile
@@ -0,0 +1,20 @@
+PAGES= sta_mgr.txt sta.txt net.txt net_list.txt
+
+ODT=$(PAGES:%.txt=%.odt)
+HTML=$(PAGES:%.txt=%.html)
+
+all: $(ODT) $(HTML)
+
+odt: $(ODT)
+
+html: $(HTML)
+
+%.odt: %.txt
+ rst2odt.py $< $@
+
+%.html: %.txt
+ rst2html $< $@
+
+clean:
+ rm -f $(ODT)
+ rm -f $(HTML)
diff --git a/cesar/cp/av/sta/mgr/test/utest/doc/net.txt b/cesar/cp/av/sta/mgr/test/utest/doc/net.txt
new file mode 100644
index 0000000000..fa0017049c
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/doc/net.txt
@@ -0,0 +1,191 @@
+Network test
+============
+
+Test the APIs available in the cp_net.
+
+sta_add
+-------
+
+Test 1 : Unassociated STAs
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add some station to the net list and verify the data. The STA are added with a
+TEI null and a known mac address.
+
+The Station shall be added as unassociated stations and be added in the set of
+unassociated stations.
+
+Their status shall be equal to CP_STA_STATE_EXISTS.
+The Mac address shall be set.
+
+Test 2 : Associated STAs
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add some stations to the net list and verify the data. The STA are added with
+a TEI different of any one already present in the Net list.
+
+The mac address is not necessary if the TEI is set, the station status shall
+be equal to CP_STA_STATE_ASSOCIATED.
+
+Test 3 : Authenticated STAs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add some authenticated stations to the net list. The STAs are added with a TEI
+different of any one already present in the Net list.
+
+The stations status shall be equal to CP_STA_STATE_AUTHENTICATED.
+
+Test 4 : Modifying the CCo in the NET
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add a station authenticated and set it as a CCo in the AVLN.
+
+The station shall be in the CP_STA_STATE_AUTHENTICATED, and the AVLN shall
+have a pointer to this station in the cco variable.
+
+Test 5 : Modifying the PCo in the NET
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add a station authenticated and set it as a PCo in the AVLN.
+
+The station shall be in the CP_STA_STATE_AUTHENTICATED, and the AVLN shall
+have a pointer to this station in the pco variable.
+
+Remove Sta
+----------
+
+Test 1 : Removing a Associated station (not CCo, not PCo)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add some station and remove it.
+At the end the list must be empty.
+
+Test 2 : Removing the CCo station of the net.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add some station in the net list as associated, one of those stations is the
+CCo (TEI = 3 for examples).
+
+At the beginning of the test, the station with the TEI = 3, shall have its
+status cco flag setted and the network has its cco pointer corresponding to
+this station.
+
+At the end, the station shall not exist in the network and the pointer to the
+CCo in the network shall be null.
+The other stations of the AVLN shall remain present.
+
+Test 3 : Removing the PCo Station of the net.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add some station in the net list as associated, one of those stations is the
+PCo (TEI = 3 for examples).
+
+At the beginning of the test, the station with the TEI = 3, shall have its
+status pco flag setted and the network has its pco pointer corresponding to
+this station.
+
+At the end, the station shall not exist in the network and the pointer to the
+PCo in the network shall be null.
+The other stations of the AVLN shall remain present.
+
+Commit to data plane
+--------------------
+
+Add some station to the list and call the commit to data plane function.
+
+The function of the CL have been overwritten in the cl_stub.c file (see in the
+src directory).
+
+It will normally allocate a block and all the station present in the network
+list will be present in it.
+
++-----+-----+-------+
+| Tag | TEI | MAC @ |
++-----+-----+-------+
+
+Garbage
+-------
+
+Verify the expiration date of all the station in the network. It the network
+is empty it shall post an event in the FSM.
+
+Environment
+~~~~~~~~~~~
+
+Add an AVLN and some station with different status.
+
+Three associated and three not associated stations.
+
++-----+-------+-----+-------+-----------+
+| sta | assoc | tei | mac @ | last seen |
++-----+-------+-----+-------+-----------+
+| 1 | false | 0 | 1 | 5 |
++-----+-------+-----+-------+-----------+
+| 2 | false | 0 | 2 | 7 |
++-----+-------+-----+-------+-----------+
+| 3 | false | 0 | 3 | 9 |
++-----+-------+-----+-------+-----------+
+| 4 | true | 1 | 1 | 6 |
++-----+-------+-----+-------+-----------+
+| 5 | true | 2 | 5 | 8 |
++-----+-------+-----+-------+-----------+
+| 6 | true | 3 | 9 | 10 |
++-----+-------+-----+-------+-----------+
+
+Result
+~~~~~~
+
+The station 1 and the station 4 shall be expired and shall not appear in the
+list after the garbage.
+
+The others shall be still present.
+
+Set slot id
+-----------
+
+Add an AVLN and set the slot id to 5.
+
+Result
+ The slot id shall be equal to 5.
+
+Network mode
+------------
+
+This test case shall test the function to set and get the network mode of an
+AVLN.
+
+Net configuration
+ After the initialization of the network the network mode is CSMA-Only.
+ At the second modification the network mode shall be setted to coordinated
+ mode.
+
+Result
+ The network shall be in CSMA only mode at the first read of the network mode.
+ The network shall be in Coordinated mode at the second read.
+
+Set sta visible
+---------------
+
+This function has for job to set the neighbour station as visible allowing to
+increase or decrease the counter of visible stations in the network.
+
+Test 1 : Adding a STA
+~~~~~~~~~~~~~~~~~~~~~
+
+Environment
+ Add a station to the network and set it as visible.
+
+Result
+ The network shall have one station as visible.
+
+Test 2 : Adding two STAs
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Environment
+ Add two station to the AVLN configured as followed :
+
+ * STA 1 : visible
+ * STA 2 : hidden
+
+Result
+ The network shall have two station and only one visible.
diff --git a/cesar/cp/av/sta/mgr/test/utest/doc/net_list.txt b/cesar/cp/av/sta/mgr/test/utest/doc/net_list.txt
new file mode 100644
index 0000000000..913968df83
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/doc/net_list.txt
@@ -0,0 +1,117 @@
+Network list
+============
+
+Initialise
+-----------
+
+Shall initialise all the networks list (index greater than 1, the index 0
+corresponds to the station AVLN):
+ - present flag shall be false.
+ - snid = 0
+ - nid = 0
+ - cco = null
+ - pco = null
+ - expiration_ntb = CP_NET_EXPIRATION_DELAY (see defs file in cp)
+ - associated_stas shall be empty.
+ - unssociated_stas shall be empty.
+
+The AVLN with the index 0 (the Stations AVLN) shall be present, i.e. the
+present flag shall be setted.
+
+Uninitialise
+------------
+
+Shall reset all the networks and call on each one the uninit function.
+
+For that some station will be create in each AVLN.
+
+AVLN 0:
+ - Station 1, TEI = 1, Mac @ = 11, is_cco = true.
+ - Station 2, TEI = 2, Mac @ = 12, is_cco = false, is_pco = true.
+
+AVLN 1:
+ - Station 1, TEI = 1, Mac @ = 21, is_cco = true.
+ - Station 2, TEI = 2, Mac @ = 22, is_cco = false, is_pco = true.
+ - Station 3, TEI = 3, Mac @ = 23.
+ - Station 4, TEI = 4, Mac @ = 24.
+
+AVLN 2:
+ - Station 1, TEI = 1, Mac @ = 31, is_cco = true.
+ - Station 2, TEI = 2, Mac @ = 32.
+ - Station 3, TEI = 3, Mac @ = 33.
+ - Station 4, TEI = 4, Mac @ = 34.
+
+At the end of this test case, all the station list shall be empty and the
+CCo, PCo pointer reseted.
+
+
+Add an AVLN
+-----------
+
+Create the AVLN and verify that it is possible to get it back using the get
+AVLN function.
+
+AVLN data:
+ - SNID = 1
+ - NID = 1
+
+The AVLN returned by the add function shall be in the following state:
+ - SNID = 1
+ - NID = 1
+ - present = true
+ - station_avln = false
+ - cco = null
+ - pco = null
+ - expiration_ntb = CP_NET_EXPIRATION_DELAY (see cp/defs.h)
+ - associated_stas = empty (use set_empty function).
+ - unassociated_stas = empty (use set_empty function).
+
+Remove an AVLN
+--------------
+
+Same thing as uninitializing an AVLN.
+
+Add an AVLN and remove it only using the SNID and NID.
+
+AVLN Data:
+ - SNID = 1
+ - NID = 1.
+
+At the end of the test this AVLN shall not exists.
+
+Update Station's SNID
+---------------------
+
+Modify the AVLN's SNID.
+
+Is empty
+--------
+
+Verify the presence of others AVLN on the medium.
+
+SNID present
+------------
+
+Return a flag indicating which SNID is currently in use.
+
+Environment 3 AVLNs with SNID 1, 5, 10.
+
+At the end of the test the flag shall contain 0x211.
+
+Get slot usage
+--------------
+
+Environment
+
+Result
+ This function shall return 0x94.
+ Add three AVLN in the station manager configured as followed:
+
+ * AVLN 1 : Slot id = 4;
+ * AVLN 2 : Slot id = 7;
+ * AVLN 3 : Slot id = 2;
+
+ This makes a slot usage equal to 0x94.
+
+Result
+ This function shall return 0x94.
diff --git a/cesar/cp/av/sta/mgr/test/utest/doc/sta.txt b/cesar/cp/av/sta/mgr/test/utest/doc/sta.txt
new file mode 100644
index 0000000000..e711621277
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/doc/sta.txt
@@ -0,0 +1,44 @@
+Station
+=======
+
+Get tei
+-------
+
+Allow any user to get a copy of the station TEI.
+
+Result
+~~~~~~
+
+Returns the correct value.
+
+Get Mac address
+---------------
+
+Allow any user to get a copy of the Station's Mac address.
+
+Result
+~~~~~~
+
+Returns the correct value.
+
+Get CCo status
+--------------
+
+Allow any user to get a copy of the station CCo status.
+
+Result
+~~~~~~
+
+Returns the correct value.
+
+
+Get PCo status
+---------------
+
+Allow any user to get a copy of the Station's Pco.
+
+Result
+~~~~~~
+
+Returns the correct value.
+
diff --git a/cesar/cp/av/sta/mgr/test/utest/doc/sta_mgr.txt b/cesar/cp/av/sta/mgr/test/utest/doc/sta_mgr.txt
new file mode 100644
index 0000000000..6fcf407725
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/doc/sta_mgr.txt
@@ -0,0 +1,14 @@
+Station Manager
+===============
+
+Initialise
+----------
+
+This shall call the function init of the net_list and the init function of the
+STA own data.
+
+Uninitialise
+------------
+
+This will call the uninit function to the net_list and the station own data.
+
diff --git a/cesar/cp/av/sta/mgr/test/utest/doc/sta_own_data.txt b/cesar/cp/av/sta/mgr/test/utest/doc/sta_own_data.txt
new file mode 100644
index 0000000000..6f700f137f
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/doc/sta_own_data.txt
@@ -0,0 +1,111 @@
+Sta own data
+============
+
+Test the Sta own data private attributes which shall only be modified by the
+accessors.
+
+Status
+------
+
+Tested : under test.
+
+Initialise
+----------
+
+Initialise the private structure (this structure contains the public
+structure) and verify if all the data are setted to 0.
+
+Result
+~~~~~~
+
+- If all the values are equals to 0, the test succeed.
+- If any value is not equal to 0, the test fail.
+
+TEI
+---
+
+Shall update the STA own data to set the station TEI, and modified the Mac
+config structure data referenced in the CP to update the station TEI.
+
+Result
+~~~~~~
+
+- The mac config contains the correct TEI.
+- The station own data contains the correct TEI.
+
+Mac address
+-----------
+
+Shall update the sta own data to set the mac address and modified the mac
+config structure referenced in the CP to update the mac address.
+
+Result
+~~~~~~
+
+- The mac config contains the correct Mac address
+- The station own data contains the correct mac address.
+
+NPW
+---
+
+Shall set up the NPW in the station own data and request the module MSG to
+send a MME to the PLC Driver to store the modification in the flash memory.
+
+*TODO* : Add the API in the MSG module.
+
+Result
+~~~~~~
+
+- The NPW is stored correctly in the STA own data.
+
+NMK
+---
+
+Shall set up the NMK in the station own data and request the module MSG to
+send a MME to the PLC Driver to store the modification in the flash memory.
+
+*TODO* : Add the API in the MSG module.
+
+Result
+~~~~~~
+
+- The NMK is stored correctly in the STA own data.
+
+DPW
+---
+
+Shall set up the DPW in the station own data and request the module MSG to
+send a MME to the PLC Driver to store the modification in the flash memory.
+
+*TODO* : Add the API in the MSG module.
+
+Result
+~~~~~~
+
+- The DPW is stored correctly in the STA own data.
+
+Security level
+--------------
+
+Shall set the security level of the station and send a message to the PLC
+driver to store the SL in the flash memory.
+
+*TODO* : Add the API in the MSG module.
+
+Result
+~~~~~~
+
+- The security level is setted correctly in the station own data.
+
+Was CCo Status
+--------------
+
+Shall set the was CCo status and send a MME to the PLC driver to store the
+station cco status in the flash memory.
+
+*TODO* : Add the API in the MSG module.
+
+Result
+~~~~~~
+
+- The was_cco status is setted in the station own data.
diff --git a/cesar/cp/av/sta/mgr/test/utest/override/cp/cco/action/inc/context.h b/cesar/cp/av/sta/mgr/test/utest/override/cp/cco/action/inc/context.h
new file mode 100644
index 0000000000..ca3da3cf61
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/override/cp/cco/action/inc/context.h
@@ -0,0 +1,26 @@
+#ifndef overide_cp_cco_action_inc_context_h
+#define overide_cp_cco_action_inc_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file overide/cp/cco/action/inc/context.h
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+
+#define CP_CCO_ACTION_TEI_FLAGS_ROW 8
+
+struct cp_cco_action_t
+{
+ /** TEI in use. */
+ uint tei_flags [CP_CCO_ACTION_TEI_FLAGS_ROW];
+};
+
+#endif /* overide_cp_cco_action_inc_context_h */
diff --git a/cesar/cp/av/sta/mgr/test/utest/override/cp/inc/context.h b/cesar/cp/av/sta/mgr/test/utest/override/cp/inc/context.h
new file mode 100644
index 0000000000..f5bfbc4840
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/override/cp/inc/context.h
@@ -0,0 +1,57 @@
+#ifndef cp_inc_cp_h
+#define cp_inc_cp_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/inc/cp_private.h
+ * \brief Control plane context.
+ * \ingroup cp
+ *
+ */
+#include "lib/rnd.h"
+
+/* Public interfaces. */
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/cco/action/cco_action.h"
+#include "cl/cl.h"
+#include "mac/common/config.h"
+#include "mac/sar/sar.h"
+
+/* Private interfaces. */
+#include "cp/sta/mgr/inc/sta_mgr.h"
+
+/* Override ones. */
+#include "cp/cco/action/inc/context.h"
+
+struct cp_t
+{
+ /** station manager context. */
+ cp_sta_mgr_t sta_mgr;
+
+ /** Cl context. */
+ cl_t *cl;
+
+ /** Mac config */
+ mac_config_t *mac_config;
+
+ /** Mac store. */
+ mac_store_t *mac_store;
+
+ /** SAR layer context pointer. */
+ sar_t *sar;
+
+ /** CCo action */
+ cp_cco_action_t cco_action;
+
+ /** Random context. */
+ lib_rnd_t rnd;
+
+ void *bsu;
+};
+
+#endif /* cp_inc_cp_h */
diff --git a/cesar/cp/av/sta/mgr/test/utest/override/cp/sta/core/core.h b/cesar/cp/av/sta/mgr/test/utest/override/cp/sta/core/core.h
new file mode 100644
index 0000000000..a00e59f744
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/override/cp/sta/core/core.h
@@ -0,0 +1,21 @@
+#ifndef overide_cp_sta_core_core_h
+#define overide_cp_sta_core_core_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file overide/cp/sta/core/core.h
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+
+u32
+cp_sta_core_get_date_ms (cp_t *cp);
+
+#endif /* overide_cp_sta_core_core_h */
diff --git a/cesar/cp/av/sta/mgr/test/utest/override/mac/sar/inc/context.h b/cesar/cp/av/sta/mgr/test/utest/override/mac/sar/inc/context.h
new file mode 100644
index 0000000000..9e7c6f07ca
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/override/mac/sar/inc/context.h
@@ -0,0 +1,23 @@
+#ifndef overide_mac_sar_inc_context_h
+#define overide_mac_sar_inc_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file overide/mac/sar/inc/context.h
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+
+struct sar_t
+{
+ mac_store_t *mac_store;
+};
+
+#endif /* overide_mac_sar_inc_context_h */
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/core_stub.c b/cesar/cp/av/sta/mgr/test/utest/src/core_stub.c
new file mode 100644
index 0000000000..c2dfaceccb
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/core_stub.c
@@ -0,0 +1,23 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/core_stub.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+#include "cp/cp.h"
+
+u32
+cp_sta_core_get_date_ms (cp_t *cp)
+{
+ return 1;
+}
+
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/net_test.c b/cesar/cp/av/sta/mgr/test/utest/src/net_test.c
new file mode 100644
index 0000000000..c4ef480f26
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/net_test.c
@@ -0,0 +1,225 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/net_test.c
+ * \brief Test the net APIs
+ * \ingroup cp_sta_mgr
+ *
+ */
+#include "common/std.h"
+#include "test_sta_mgr.h"
+
+bool
+cp_net_station_assoc_less (set_node_t *left, set_node_t *right);
+
+bool
+cp_net_station_unassoc_less (set_node_t *left, set_node_t *right);
+
+void
+test_case_cp_net_init (test_t test)
+{
+ cp_t ctx;
+ cp_net_t net;
+ test_case_begin (test, "NET init");
+ test_begin (test, "init")
+ {
+ cp_net_init (&ctx, &net);
+ test_fail_unless (net.present == false);
+ }
+ test_end;
+}
+
+void
+test_case_cp_net_uninit (test_t test)
+{
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ test_case_begin (test, "uninit");
+ test_begin (test, "Net empty")
+ {
+ cp_net_t net;
+ cp_net_init (&cp, &net);
+ cp_net_uninit (&cp, &net);
+ test_fail_unless (set_empty (&net.associated_stas));
+ test_fail_unless (set_empty (&net.unassociated_stas));
+ test_fail_unless (!net.present);
+ }
+ test_end;
+
+ test_begin (test, "NET empty with NID SNID")
+ {
+ cp_net_t *net;
+ /* Initialise the comparison net. */
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ test_fail_unless (net->present);
+ cp_sta_mgr_remove_avln (&cp, net->snid, net->nid);
+ test_fail_unless (set_empty (&net->associated_stas));
+ test_fail_unless (set_empty (&net->unassociated_stas));
+ test_fail_unless (!net->present);
+ }
+ test_end;
+ test_sta_mgr_uninit (&cp);
+}
+
+void
+test_case_cp_net_get_snid_nid (test_t test)
+{
+ test_case_begin (test, "Get snid");
+
+ test_begin (test, "Get snid and nid from a NET")
+ {
+ cp_t cp;
+ cp_net_t net;
+
+ /* Configure the test. */
+ memset (&cp, 0, sizeof (cp_t));
+ memset (&net, 0, sizeof (cp_net_t));
+
+ net.snid = 0x1;
+ net.nid = 0x133456789ABCull;
+
+ test_fail_if (cp_net_get_snid (&cp, &net) != net.snid);
+ test_fail_if (cp_net_get_nid (&cp, &net) != net.nid);
+ }
+ test_end;
+}
+
+void
+test_case_cp_net_slot_usage (test_t test)
+{
+ test_case_begin (test, "Set, get slots and get slot mask");
+
+ test_begin (test, "Set slot id and mask")
+ {
+ cp_t cp;
+ cp_net_t net;
+
+ /* Configure the test. */
+ memset (&cp, 0, sizeof (cp_t));
+ memset (&net, 0, sizeof (cp_net_t));
+
+ cp_net_set_slot_id_and_usage (&cp, &net, 1, 2);
+
+ test_fail_if (cp_net_get_slot_id (&cp, &net) != 1);
+ test_fail_if (cp_net_get_slot_usage_mask (&cp, &net) != 2);
+ }
+ test_end;
+}
+
+void
+test_case_cp_net_nm (test_t test)
+{
+ test_case_begin (test, "Network mode");
+
+ test_begin (test, "Set the NM and GET it.")
+ {
+ cp_t cp;
+ cp_net_t net;
+
+ /* Configure the test. */
+ memset (&cp, 0, sizeof (cp_t));
+ memset (&net, 0, sizeof (cp_net_t));
+
+ cp_net_set_nm (&cp, &net, MAC_NM_COORDINATED);
+ test_fail_if (cp_net_get_nm (&cp, &net) != MAC_NM_COORDINATED);
+
+ cp_net_set_nm (&cp, &net, MAC_NM_CSMA_ONLY);
+ test_fail_if (cp_net_get_nm (&cp, &net) != MAC_NM_CSMA_ONLY);
+
+ cp_net_set_nm (&cp, &net, MAC_NM_UNCOORDINATED);
+ test_fail_if (cp_net_get_nm (&cp, &net) != MAC_NM_UNCOORDINATED);
+ }
+ test_end;
+}
+
+void
+test_case_cp_net_sta_visible (test_t test)
+{
+ test_case_begin (test, "visible stations");
+
+ test_begin (test, "Set")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ /* Configure the test. */
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_own_data_set_tei (&cp, 254);
+ /* the test. */
+ cp_sta_set_visible_status (
+ &cp, sta, CP_STA_VISIBLE_STATE_VISIBLE);
+ test_fail_unless (net->num_visible_stas == 1);
+ cp_sta_set_visible_status (
+ &cp, sta, CP_STA_VISIBLE_STATE_HIDDEN);
+ test_fail_unless (net->num_visible_stas == 0);
+ slab_release (sta);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_net_access (test_t test)
+{
+ test_case_begin (test, "Network Access type");
+
+ test_begin (test, "Network access type")
+ {
+ cp_t cp;
+ cp_net_t net;
+
+ /* Configuring the test. */
+ memset (&cp, 0, sizeof (cp_t));
+ memset (&net, 0, sizeof (cp_net_t));
+
+ /* Test. */
+ cp_net_set_access (&cp, &net, HPAV_ACCESS_ACCESS);
+ test_fail_if (net.access != HPAV_ACCESS_ACCESS);
+
+ cp_net_set_access (&cp, &net, HPAV_ACCESS_IN_HOME);
+ test_fail_if (net.access != HPAV_ACCESS_IN_HOME);
+ }
+ test_end;
+}
+
+void
+test_case_get_net (test_t test)
+{
+ test_case_begin (test, "Net of a STA");
+
+ test_begin (test, "Get the net of a STA")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ /* Initialize. */
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ test_fail_unless (cp_sta_get_net (sta) == net);
+ slab_release (sta);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_suite_net (test_t test)
+{
+ test_suite_begin (test, "Net");
+ test_case_cp_net_init (test);
+ test_case_cp_net_uninit (test);
+ test_case_cp_net_get_snid_nid (test);
+ test_case_cp_net_slot_usage (test);
+ test_case_cp_net_nm (test);
+ test_case_cp_net_sta_visible (test);
+ test_case_cp_net_access (test);
+}
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/sar_stub.c b/cesar/cp/av/sta/mgr/test/utest/src/sar_stub.c
new file mode 100644
index 0000000000..681e8dbdfd
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/sar_stub.c
@@ -0,0 +1,56 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/sar_stub.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+#include "mac/sar/sar.h"
+#include "mac/sar/inc/context.h"
+
+/**
+ * Remove a station from the SAR and the mac store.
+ * \param ctx the CP context.
+ * \param tei the station tei.
+ *
+ * Remove all the MFS from the expiration mechanism of the SAR and ends to
+ * remove the station from the mac store.
+ */
+void
+sar_sta_remove (sar_t *ctx, u8 tei)
+{
+ sta_t *sta;
+ dbg_assert (ctx);
+ dbg_assert (ctx->mac_store);
+ dbg_assert (tei);
+
+ sta = mac_store_sta_get (ctx->mac_store, tei);
+ if (sta)
+ {
+ dbg_check (mac_store_sta_remove (ctx->mac_store, tei));
+ blk_release (sta);
+ }
+}
+
+void
+sar_cleanup (sar_t *ctx)
+{
+ mfs_tx_t *mfs;
+ dbg_assert (ctx);
+
+ mfs = mac_store_mfs_get_tx (ctx->mac_store, true, false, 1,
+ MAC_TEI_BCAST);
+ if (mfs)
+ {
+ mac_store_mfs_remove (ctx->mac_store, (mfs_t *) mfs);
+ blk_release (mfs);
+ }
+}
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/sta-test.c b/cesar/cp/av/sta/mgr/test/utest/src/sta-test.c
new file mode 100644
index 0000000000..d8effc6c7d
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/sta-test.c
@@ -0,0 +1,688 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/sta-test.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/bitstream.h"
+
+#include "cp/sta/mgr/sta_own_data.h"
+
+#include "cp/inc/context.h"
+#include "cp/sta/mgr/inc/sta_own_data.h"
+
+#include "cl/inc/context.h"
+#include "mac/sar/inc/context.h"
+#include <string.h>
+#include "cp/fsm/fsm.h"
+
+static bool fsm_posted;
+
+static void
+test_sta_own_init (cp_t *cp)
+{
+ static mac_config_t mac_config;
+ static cl_t cl;
+ static sar_t sar;
+ memset (&mac_config, 0, sizeof (mac_config));
+ memset (&cl, 0, sizeof (cl_t));
+ memset (&sar, 0, sizeof (sar_t));
+ memset (cp, 0, sizeof (cp_t));
+ cp->mac_config = &mac_config;
+ cp->cl = &cl;
+ cp->sar = &sar;
+ cp->mac_store = sar.mac_store = mac_store_init ();
+ lib_rnd_init (&cp->rnd, 1234);
+ cp_sta_mgr_init (cp);
+}
+
+static void
+test_sta_own_uninit (cp_t *cp)
+{
+ cp_sta_mgr_uninit (cp);
+ mac_store_uninit (cp->mac_store);
+}
+
+
+void
+cp_fsm_post (cp_t *ctx, cp_fsm_event_t *event)
+{
+ fsm_posted = true;
+}
+
+void
+test_case_cp_sta_own_data_init (test_t test)
+{
+ test_case_begin (test, "init");
+
+ test_begin (test, "init")
+ {
+ cp_t cp;
+ cp_sta_own_data_private_t cmp;
+ cp_sta_own_data_private_t *real;
+
+ memset (&cmp, 0, sizeof (cp_sta_own_data_private_t));
+ cmp.public.hybrid_mode = MAC_COEXISTENCE_HYBRID_DELIMITERS_MODE;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ cmp.snid = cp_sta_own_data_get_snid (&cp);
+
+ real = (cp_sta_own_data_private_t*) cp_sta_mgr_get_sta_own_data(&cp);
+ test_fail_if (
+ memcmp(&cmp, real, sizeof (cp_sta_own_data_private_t)) != 0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__set_and_get_tei (test_t test)
+{
+ test_case_begin (test, "Set Get tei");
+
+ test_begin (test, "Set")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ test_sta_own_init (&cp);
+ // Add an AVLN.
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_tei (&cp, 2);
+
+ test_fail_if (cp_sta_own_data_get_tei (&cp) != 2);
+ test_fail_unless (fsm_posted == true);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_tei (&cp, 2);
+ test_fail_if (cp_sta_own_data_get_tei (&cp) != 2);
+ test_fail_unless (fsm_posted == false);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_tei (&cp, MAC_TEI_UNASSOCIATED);
+ test_fail_unless (cp_sta_own_data_get_tei (&cp) ==
+ MAC_TEI_UNASSOCIATED);
+ test_fail_unless (fsm_posted == true);
+ test_sta_own_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__mac_address (test_t test)
+{
+ test_case_begin (test, "Mac address");
+
+ test_begin (test, "Set and Get the mac address")
+ {
+ cp_t cp;
+
+ mac_config_t mac_config;
+ cp.mac_config = &mac_config;
+ lib_rnd_init (&cp.rnd, 0x432);
+
+ cp_sta_mgr_init (&cp);
+ cp_sta_own_data_set_mac_address (&cp, 0x123456789ABCull);
+
+ test_fail_if (cp_sta_own_data_get_mac_address (&cp) !=
+ 0x123456789ABCull);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__npw (test_t test)
+{
+ test_case_begin (test, "Set and get the NPW");
+
+ test_begin (test, "NPW")
+ {
+ cp_t cp;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ cp_sta_own_data_set_npw (&cp, "Hello world");
+
+ test_fail_if (
+ strcmp (cp_sta_own_data_get_npw (&cp), "Hello world") != 0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__nmk (test_t test)
+{
+ test_case_begin (test, "Set and get the NMK");
+
+ test_begin (test, "NMK")
+ {
+ cp_t cp;
+ cp_key_t key;
+ cp_key_t res;
+ bool changed;
+
+ key.key[0] = 0x1234;
+ key.key[1] = 0x5678;
+ key.key[2] = 0x9abc;
+ key.key[3] = 0xdef0;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ changed = cp_sta_own_data_set_nmk (&cp, key, 0);
+
+ res = cp_sta_own_data_get_nmk (&cp);
+
+ test_fail_if (changed == false);
+ test_fail_if (memcmp (&res, &key, sizeof (cp_key_t)) != 0);
+
+ changed = cp_sta_own_data_set_nmk (&cp, key, 0);
+ test_fail_if (changed == true);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__dpw (test_t test)
+{
+ test_case_begin (test, "Set and get the DPW");
+
+ test_begin (test, "DPW")
+ {
+ cp_t cp;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ cp_sta_own_data_set_dpw (&cp, "Hello world");
+
+ test_fail_if (
+ strcmp (cp_sta_own_data_get_dpw (&cp), "Hello world") != 0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__security_level (test_t test)
+{
+ test_case_begin (test, "Set and get the SL");
+
+ test_begin (test, "SL")
+ {
+ cp_t cp;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ cp_sta_own_data_set_security_level (&cp, CP_SECURITY_LEVEL_SC);
+
+ test_fail_if (cp_sta_own_data_get_security_level (&cp) !=
+ CP_SECURITY_LEVEL_SC);
+
+ cp_sta_own_data_set_security_level (&cp, CP_SECURITY_LEVEL_HS);
+
+ test_fail_if (cp_sta_own_data_get_security_level (&cp) !=
+ CP_SECURITY_LEVEL_HS);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__was_cco (test_t test)
+{
+ test_case_begin (test, "Set and get was_cco");
+
+ test_begin (test, "was_cco")
+ {
+ cp_t cp;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ cp_sta_own_data_set_was_cco (&cp, true);
+ test_fail_if (cp_sta_own_data_get_was_cco(&cp) != true);
+ cp_sta_own_data_set_was_cco (&cp, false);
+ test_fail_if (cp_sta_own_data_get_was_cco (&cp) != false);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+}
+
+void
+test_case_cp_sta_own_data__hfid_avln (test_t test)
+{
+ test_case_begin (test, "Set and get the AVLN HFID");
+
+ test_begin (test, "AVLN HFID")
+ {
+ cp_t cp;
+ cp_sta_own_data_t *sta;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_hfid_avln (&cp, "Hello world");
+
+ test_fail_if (
+ strcmp (sta->hfid_avln, "Hello world") != 0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__hfid_user (test_t test)
+{
+ test_case_begin (test, "Set and get the USER HFID");
+
+ test_begin (test, "USER HFID")
+ {
+ cp_t cp;
+ cp_sta_own_data_t *sta;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_hfid_user (&cp, "Hello world");
+
+ test_fail_if (
+ strcmp (sta->hfid_user, "Hello world") != 0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__hfid_manufacturer (test_t test)
+{
+ test_case_begin (test, "Set and get the MANUFACTURER HFID");
+
+ test_begin (test, "MANUFACTURER HFID")
+ {
+ cp_t cp;
+ cp_sta_own_data_t *sta;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_hfid_manufacturer (&cp, "Hello world");
+
+ test_fail_if (
+ strcmp (sta->hfid_manufacturer, "Hello world") != 0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__pco_glid (test_t test)
+{
+ test_case_begin (test, "Set and get the PCO glid");
+
+ test_begin (test, "PCo")
+ {
+ cp_t cp;
+ cp_sta_own_data_t *sta;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_pco_glid (&cp, 0x90);
+ test_fail_if (cp_sta_own_data_get_pco_glid (&cp) != 0x90);
+ cp_sta_own_data_set_pco_glid (&cp, 0x0);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__pco_status (test_t test)
+{
+ test_case_begin (test, "Set and get the PCO status");
+
+ test_begin (test, "PCo")
+ {
+ cp_t cp;
+ cp_sta_own_data_t *sta;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_pco_status (&cp, true);
+ test_fail_if (cp_sta_own_data_get_pco_status (&cp) != true);
+ test_fail_unless (fsm_posted == true);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_pco_status (&cp, true);
+ test_fail_if (cp_sta_own_data_get_pco_status (&cp) != true);
+ test_fail_unless (fsm_posted == false);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_pco_status (&cp, false);
+ test_fail_if (cp_sta_own_data_get_pco_status (&cp) != false);
+ test_fail_unless (fsm_posted == true);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "PCo and glid")
+ {
+ cp_t cp;
+ cp_sta_own_data_t *sta;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_pco_status (&cp, true);
+ cp_sta_own_data_set_pco_glid (&cp, 0x85);
+
+ test_fail_if (cp_sta_own_data_get_pco_status (&cp) != true);
+ test_fail_if (cp_sta_own_data_get_pco_glid (&cp) != 0x85);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__cco_status (test_t test)
+{
+ test_case_begin (test, "Set and get the CCo status");
+
+ test_begin (test, "CCo")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ mac_config_t mac_config;
+ cp_sta_own_data_t *sta;
+ cl_t cl;
+ sar_t sar;
+
+ cp.mac_config = &mac_config;
+ cl.mactotei = NULL;
+ cp.cl = &cl;
+ cp.sar = &sar;
+ cp.mac_store = mac_store_init ();
+ sar.mac_store = cp.mac_store;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_tei (&cp, 1);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_cco_status (&cp, true);
+ test_fail_if (cp_sta_own_data_get_cco_status (&cp) != true);
+ test_fail_unless (fsm_posted == true);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_cco_status (&cp, true);
+ test_fail_if (cp_sta_own_data_get_cco_status (&cp) != true);
+ test_fail_unless (fsm_posted == false);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_cco_status (&cp, false);
+ test_fail_if (cp_sta_own_data_get_cco_status (&cp) != false);
+ test_fail_unless (fsm_posted == true);
+
+ cp_sta_mgr_uninit (&cp);
+ mac_store_uninit (cp.mac_store);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__authenticated_status (test_t test)
+{
+ test_case_begin (test, "Set and get the CCo authenticated");
+
+ test_begin (test, "CCo")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ mac_config_t mac_config;
+ cp_sta_own_data_t *sta;
+ cl_t cl;
+ sar_t sar;
+
+ cp.mac_config = &mac_config;
+ cl.mactotei = NULL;
+ cp.cl = &cl;
+ cp.sar = &sar;
+ cp.mac_store = mac_store_init ();
+ sar.mac_store = cp.mac_store;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ sta = cp_sta_mgr_get_sta_own_data (&cp);
+ cp_sta_own_data_set_tei (&cp, 1);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_authenticated_status (&cp, true);
+ test_fail_if (cp_sta_own_data_get_authenticated_status (&cp) != true);
+ test_fail_unless (fsm_posted == true);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_authenticated_status (&cp, true);
+ test_fail_if (cp_sta_own_data_get_authenticated_status (&cp) != true);
+ test_fail_unless (fsm_posted == false);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_authenticated_status (&cp, false);
+ test_fail_if (cp_sta_own_data_get_authenticated_status (&cp) != false);
+ test_fail_unless (fsm_posted == true);
+
+ cp_sta_mgr_uninit (&cp);
+ mac_store_uninit (cp.mac_store);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__nid (test_t test)
+{
+ test_case_begin (test, "Set/Get NID & SL");
+
+ test_begin (test, "")
+ {
+ cp_t cp;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+
+ lib_rnd_t rnd;
+ lib_rnd_init (&rnd, 0x4224);
+
+ cp_security_level_t sl;
+ for (sl = CP_SECURITY_LEVEL_SC; sl < CP_SECURITY_LEVEL_NB; sl++)
+ {
+ uint i;
+ for (i = 0; i < 1234; i++)
+ {
+ cp_nid_t nid = ((u64) sl) << (HPAV_NID_SIZE_BITS - 2)
+ | lib_rnd_uniform (&rnd, -1);
+ cp_sta_own_data_set_nid (&cp, nid);
+ test_fail_if (cp_sta_own_data_get_nid (&cp) != nid);
+ test_fail_if (cp_sta_own_data_get_security_level (&cp) != sl);
+ }
+ }
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__snid (test_t test)
+{
+ test_case_begin (test, "Set and GET SNID");
+
+ test_begin (test, "")
+ {
+ cp_t cp;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+
+ cp_sta_own_data_set_snid (&cp, 0x2);
+ test_fail_if (cp_sta_own_data_get_snid (&cp) != 0x2);
+ cp_sta_own_data_set_snid (&cp, 0x1);
+ test_fail_if (cp_sta_own_data_get_snid (&cp) != 0x1);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__tek (test_t test)
+{
+ test_case_begin (test, "Set the TEK");
+
+ test_begin (test, "TEK")
+ {
+ cp_t cp;
+ cp_key_t key;
+ cp_key_t tek;
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+
+ key.key[0] = 0x12345678;
+ key.key[1] = 0x12345678;
+ key.key[2] = 0x12345678;
+ key.key[3] = 0x12345678;
+
+ cp_sta_own_data_set_tek (&cp, key);
+
+ tek = cp_sta_own_data_get_tek (&cp);
+
+ test_fail_unless (memcmp (&tek, &key, sizeof (cp_key_t)) == 0);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__dak (test_t test)
+{
+ test_case_begin (test, "DAK");
+
+ test_begin (test, "store dak")
+ {
+ cp_t cp;
+ uint i;
+ cp_key_t dak = { {0x11111111, 0x22222222, 0x33333333, 0x44444444} };
+ cp_key_t own_dak;
+
+ memset (&cp, 0, sizeof (cp_t));
+
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+
+ cp_sta_own_data_set_dak (&cp, dak);
+ own_dak = cp_sta_own_data_get_dak (&cp);
+
+ for (i = 0; i < COUNT (dak.key); i++)
+ test_fail_unless (dak.key[i] == own_dak.key[i]);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case_cp_sta_own_data__sc (test_t test)
+{
+ test_case_begin (test, "Simple connect");
+
+ test_begin (test, "")
+ {
+ cp_t cp;
+
+ memset (&cp, 0, sizeof (cp_t));
+ lib_rnd_init (&cp.rnd, 0x432);
+ cp_sta_mgr_init (&cp);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_sc (&cp, true);
+ test_fail_unless (cp.sta_mgr.sta_own_data.sc == true);
+ test_fail_unless (cp_sta_own_data_get_sc (&cp) == true);
+ test_fail_unless (fsm_posted == true);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_sc (&cp, true);
+ test_fail_unless (cp.sta_mgr.sta_own_data.sc == true);
+ test_fail_unless (cp_sta_own_data_get_sc (&cp) == true);
+ test_fail_unless (fsm_posted == false);
+
+ fsm_posted = false;
+ cp_sta_own_data_set_sc (&cp, false);
+ test_fail_unless (cp.sta_mgr.sta_own_data.sc == false);
+ test_fail_unless (cp_sta_own_data_get_sc (&cp) == false);
+ test_fail_unless (fsm_posted == true);
+
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_suite_sta_own (test_t test)
+{
+ test_suite_begin (test, "station own data");
+ test_case_cp_sta_own_data_init (test);
+ test_case_cp_sta_own_data__set_and_get_tei (test);
+ test_case_cp_sta_own_data__mac_address (test);
+ test_case_cp_sta_own_data__npw (test);
+ test_case_cp_sta_own_data__nmk (test);
+ test_case_cp_sta_own_data__dpw (test);
+ test_case_cp_sta_own_data__security_level (test);
+ test_case_cp_sta_own_data__was_cco (test);
+ test_case_cp_sta_own_data__hfid_avln (test);
+ test_case_cp_sta_own_data__hfid_user (test);
+ test_case_cp_sta_own_data__hfid_manufacturer (test);
+ test_case_cp_sta_own_data__pco_glid (test);
+ test_case_cp_sta_own_data__pco_status (test);
+ test_case_cp_sta_own_data__cco_status (test);
+ test_case_cp_sta_own_data__authenticated_status (test);
+ test_case_cp_sta_own_data__nid (test);
+ test_case_cp_sta_own_data__snid (test);
+ test_case_cp_sta_own_data__tek (test);
+ test_case_cp_sta_own_data__dak (test);
+ test_case_cp_sta_own_data__sc (test);
+}
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/sta_mgr.c b/cesar/cp/av/sta/mgr/test/utest/src/sta_mgr.c
new file mode 100644
index 0000000000..d3fa8199e6
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/sta_mgr.c
@@ -0,0 +1,1745 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/sta_mgr.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include "common/std.h"
+#include "lib/test.h"
+#include "test_sta_mgr.h"
+#include "cp/av/sta/mgr/sta_mgr.h"
+
+void
+cp_sta_mgr_elects_sta_partial_ack (cp_t *ctx);
+
+void
+test_case__cp_sta_mgr_sta (test_t test)
+{
+ test_case_begin (test, "Station manager using stations");
+
+ test_begin (test, "Station Unassociated")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ mac_t mac_addr;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add the station. */
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, mac_addr);
+ test_fail_if (sta == NULL);
+ slab_release (sta);
+
+ /* Find the station by the mac address. */
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, mac_addr);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addr);
+ slab_release (sta);
+
+ /* Remove the station. */
+ cp_sta_mgr_sta_remove_from_mac (&cp, mac_addr);
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, mac_addr);
+ test_fail_if (sta != NULL);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "Station associated")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ mac_t mac_addr;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station associated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addr);
+ test_fail_if (sta == NULL);
+ slab_release (sta);
+
+ /* Get the station by the TEI. */
+ sta = cp_sta_mgr_sta_get_assoc (&cp, net, sta_tei);
+ test_fail_if (sta == NULL);
+ slab_release (sta);
+
+ /* Get the station by the mac address. */
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, mac_addr);
+ test_fail_if (sta == NULL);
+ slab_release (sta);
+
+ /* Remove the station by the TEI. */
+ cp_sta_mgr_sta_remove_assoc (&cp, net, sta_tei);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 1: Nothing change")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station unassociated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, mac_addr);
+ test_fail_if (sta == NULL);
+
+ /* Add a station with the same mac address and TEI. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, 0, mac_addr);
+ test_fail_if (sta != sta2);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 2: Same TEI, Mac address change from bcast to unique")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station unassociated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei, MAC_BROADCAST);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta) != MAC_BROADCAST);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != true);
+
+ /* Add a station with the real mac address. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addr);
+ test_fail_if (sta != sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 2: Same TEI, Mac address change from A to B")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addrA;
+ mac_t mac_addrB;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ memset (&cp, 0, sizeof (cp_t));
+ mac_addrA = 0x12345678ABCull;
+ mac_addrB = 0x2345678ABCDull;
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station unassociated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addrA);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addrA);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+
+ /* Add a station with the real mac address. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addrB);
+ test_fail_if (sta == sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addrB);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 2: Change the TEI, Mac address unchanged")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station unassociated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, mac_addr);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != 0);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != true);
+ test_fail_if (set_empty(&net->unassociated_stas) != false);
+
+ /* Add a station with the real TEI. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addr);
+ test_fail_if (sta == sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 2: Change the TEI A to B, Mac address unchanged")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei_A;
+ cp_tei_t sta_tei_B;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+
+ sta_tei_A = 0xB;
+ sta_tei_B = 0xF;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station associated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei_A, mac_addr);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != sta_tei_A);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* Add a station with the real TEI. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, sta_tei_B, mac_addr);
+ test_fail_if (sta == sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei_B);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 2: Change the TEI A to 0, Mac address unchanged")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei_A;
+ cp_tei_t sta_tei_B;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+
+ sta_tei_A = 0xB;
+ sta_tei_B = 0;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station associated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei_A, mac_addr);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != sta_tei_A);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* Add a station with the real TEI. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, sta_tei_B, mac_addr);
+ test_fail_if (sta == sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei_B);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != true);
+ test_fail_if (set_empty(&net->unassociated_stas) != false);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+
+ test_begin (test, "station Case 4: Change the Mac address from A to bcast")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+
+ /* Add a station associated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addr);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* Add a station with the new Mac address. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net, sta_tei, MAC_BROADCAST);
+ test_fail_if (sta != sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "station Case 2: Change the network")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_net_t *net2;
+ cp_sta_t *sta;
+ cp_sta_t *sta2;
+ mac_t mac_addr;
+ cp_tei_t sta_tei;
+
+ /* configuring the test. */
+ mac_addr = 0x12345678ABCull;
+
+ sta_tei = 0xB;
+
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ dbg_check (net);
+ net2 = cp_sta_mgr_add_avln (&cp, 2, 2);
+ dbg_check (net2);
+
+ /* Add a station associated. */
+ sta = cp_sta_mgr_sta_add (&cp, net, sta_tei, mac_addr);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* Add a station in another network. */
+ sta2 = cp_sta_mgr_sta_add (&cp, net2, sta_tei, mac_addr);
+ test_fail_if (sta == sta2);
+
+ test_fail_if (cp_sta_get_tei (sta2) != sta_tei);
+ test_fail_if (cp_sta_get_mac_address (sta2) != mac_addr);
+
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != false);
+ test_fail_if (set_empty(&net->associated_stas) != true);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ test_fail_if (set_empty(&net2->associated_stas) != false);
+ test_fail_if (set_empty(&net2->unassociated_stas) != true);
+
+ /* release the stations. */
+ slab_release (sta);
+ slab_release (sta2);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_case_begin (test, "Sta Remove");
+
+ test_begin (test, "remove from mac")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, 1);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove_from_mac (&cp, 1);
+
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+
+ /* set our avln. */
+ cp_sta_mgr_set_our_avln (&cp, net);
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, 1);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove_from_mac (&cp, 1);
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove_from_mac (&cp, 1);
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "remove from assoc")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove_assoc (&cp, net, 1);
+
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+
+ /* set our avln. */
+ cp_sta_mgr_set_our_avln (&cp, net);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove_assoc (&cp, net, 1);
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "remove")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+
+ cp_sta_mgr_sta_remove (&cp, sta);
+ slab_release (sta);
+
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+
+ /* set our avln. */
+ cp_sta_mgr_set_our_avln (&cp, net);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ slab_release (sta);
+
+ cp_sta_mgr_sta_remove (&cp, sta);
+ sta = cp_sta_mgr_sta_get_from_mac(&cp, 1);
+ test_fail_unless (sta == NULL);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+ test_begin (test, "Two STAs with same TEI.")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta_old;
+ cp_sta_t *sta_new;
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta_new = cp_sta_mgr_sta_add (&cp, net, 0, 2);
+ slab_release (sta_new);
+ sta_old = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ sta_new = cp_sta_mgr_sta_add (&cp, net, 1, 2);
+ test_fail_unless (sta_old != sta_new);
+ test_fail_unless (!set_node_in_any_set (&sta_old->node_net));
+ test_fail_unless (set_node_in_any_set (&sta_new->node_net));
+ slab_release (sta_old);
+ slab_release (sta_new);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_net_uninit (test_t test)
+{
+ test_case_begin (test, "Uninitialise the network with some stations");
+
+ test_begin (test, "net")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+
+ /* configuring the test. */
+
+ test_sta_mgr_init (&cp);
+
+ /* Add an AVLN. */
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+
+ test_fail_if (set_empty(&net->associated_stas) != true);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+
+ /* Add some stations. */
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, 1);
+ slab_release (sta);
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, 2);
+ slab_release (sta);
+ sta = cp_sta_mgr_sta_add (&cp, net, 0, 3);
+ slab_release (sta);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 4);
+ slab_release (sta);
+ sta = cp_sta_mgr_sta_add (&cp, net, 2, 5);
+ slab_release (sta);
+ sta = cp_sta_mgr_sta_add (&cp, net, 3, 6);
+ slab_release (sta);
+
+ test_fail_if (set_empty(&net->associated_stas) != false);
+ test_fail_if (set_empty(&net->unassociated_stas) != false);
+
+ test_sta_mgr_uninit (&cp);
+
+ test_fail_if (set_empty(&net->associated_stas) != true);
+ test_fail_if (set_empty(&net->unassociated_stas) != true);
+ test_fail_if (set_empty(&cp.sta_mgr.stas) != true);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_manager_garbage (test_t test)
+{
+ test_case_begin (test, "Garbage function");
+
+ test_begin (test, "Garbage outside our AVLN.")
+ {
+ cp_t cp;
+ cp_net_t *net1;
+ cp_net_t *net2;
+ cp_sta_t *sta;
+ uint i;
+
+ /* configuring the test. */
+
+ test_sta_mgr_init (&cp);
+
+ /* Add an AVLN. */
+ net1 = cp_sta_mgr_add_avln (&cp, 1, 1);
+ net2 = cp_sta_mgr_add_avln (&cp, 2, 2);
+
+ for (i = 0; i < 10; i++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net1, i + 1, i + 1);
+ sta->expired_date_ms = cp_sta_core_get_date_ms (&cp)
+ - HPAV_DISCOVERED_LIST_EXPIRE_TIME_MS;
+ slab_release (sta);
+
+ sta = cp_sta_mgr_sta_add (&cp, net2, i + 1, (i + 1) * 20);
+ sta->expired_date_ms = cp_sta_core_get_date_ms (&cp)
+ - HPAV_DISCOVERED_LIST_EXPIRE_TIME_MS;
+ slab_release (sta);
+ }
+
+ /* Release the stations. */
+ cp_sta_mgr_garbage (&cp);
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp));
+ cp_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "Associated stations")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ /* configure the test.*/
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp.sta_mgr.our_avln = net;
+ cp_sta_own_data_set_tei (&cp, 34);
+ cp_sta_own_data_set_cco_status (&cp, true);
+
+ /* Add some stations. */
+ sta = cp_sta_mgr_sta_add (&cp, net, 0x1, 123);
+ cp_sta_set_assoc_confirmed (&cp, sta, false);
+ sta->assoc_req_last_ms = 130000; /* > 2 min. */
+ slab_release (sta);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 0x3, 124);
+ cp_sta_set_assoc_confirmed (&cp, sta, false);
+ sta->assoc_req_last_ms = 60000; /* 1 min. */
+ slab_release (sta);
+
+ /* Test. */
+ cp_sta_mgr__assoc__timeout (&cp, 60000);
+
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, 123);
+ test_fail_if (cp_sta_get_assoc_confirmed (&cp, sta) != false);
+ slab_release (sta);
+
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, 124);
+ test_fail_if (cp_sta_get_assoc_confirmed (&cp, sta) != false);
+ slab_release (sta);
+
+ /* Test. */
+ cp_sta_mgr__assoc__timeout (&cp, 120000);
+
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, 123);
+ test_fail_if (cp_sta_get_assoc_confirmed (&cp, sta) != false);
+ slab_release (sta);
+
+ sta = cp_sta_mgr_sta_get_from_mac (&cp, 124);
+ test_fail_if (cp_sta_get_assoc_confirmed (&cp, sta) != true);
+ slab_release (sta);
+
+ /* Station manager uninitialise. */
+ cp_sta_mgr_sta_remove_from_mac (&cp, 123);
+ cp_sta_mgr_sta_remove_from_mac (&cp, 124);
+ test_sta_mgr_uninit (&cp);
+ mac_store_uninit (cp.mac_store);
+ }
+ test_end;
+
+ test_begin (test, "Garbage the network")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ /* Add some stations in the first AVLN. */
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ sta->expired_date_ms = cp_sta_core_get_date_ms (&cp)
+ - HPAV_DISCOVERED_LIST_EXPIRE_TIME_MS - 10;
+ slab_release (sta);
+ /* Set our AVLN. */
+ cp_sta_mgr_set_our_avln (&cp, net);
+ /* Launch the test. */
+ cp_sta_mgr_garbage (&cp);
+ /* Its our AVLN and the station is not CCo. It should not remove the
+ * station. */
+ test_fail_unless (!cp_net_is_empty (&cp, net));
+ /* Now the net is no more our AVLN. */
+ cp_sta_mgr_set_our_avln (&cp, NULL);
+ test_fail_unless (!cp_net_is_empty (&cp, net));
+ cp_sta_mgr_garbage (&cp);
+ test_fail_unless (cp_net_is_empty (&cp, net));
+ test_fail_unless (!net->present);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_net_pco (test_t test)
+{
+ test_case_begin (test, "Net pco");
+
+ test_begin (test, "PCo on the net")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+
+ /* configuring the test. */
+ test_sta_mgr_init (&cp);
+
+ /* Add an AVLN. */
+ net = cp_sta_mgr_add_avln (&cp, 2, 2);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+
+ /* Set the station as PCo. */
+ cp_net_set_pco (&cp, net, 1);
+
+ test_fail_if (cp_sta_get_pco_status (sta) != true);
+ test_fail_if (net->pco != sta);
+
+ /* Unset the PCo. */
+ cp_net_set_pco (&cp, net, 0);
+
+ test_fail_if (cp_sta_get_pco_status (sta) != false);
+ test_fail_if (net->pco != NULL);
+
+ slab_release (sta);
+ test_sta_mgr_uninit (&cp);
+
+ }
+ test_end;
+}
+
+void
+test_case__cp_net_sta_get_first_next (test_t test)
+{
+ test_case_begin (test, "Get first and next");
+
+ test_begin (test, "Get the first and next station")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta1;
+ cp_sta_t *sta2;
+
+ /* configuring the test. */
+ test_sta_mgr_init (&cp);
+
+ /* Add an AVLN. */
+ net = cp_sta_mgr_add_avln (&cp, 2, 2);
+
+ sta1 = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ sta2 = cp_sta_mgr_sta_add (&cp, net, 2, 2);
+ slab_release (sta1);
+ slab_release (sta2);
+
+ /* Get the first station. */
+ sta1 = cp_net_sta_get_first (&cp, net, CP_NET_STA_ASSOC);
+ test_fail_if (sta1 == NULL);
+ test_fail_if (cp_sta_get_tei (sta1) != 1);
+
+ /* Get the next station. */
+ sta2 = cp_net_sta_get_next (&cp, net, sta1);
+ test_fail_if (sta2 == NULL);
+ test_fail_if (cp_sta_get_tei (sta2) != 2);
+
+ slab_release (sta2);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_get_avln (test_t test)
+{
+ test_case_begin (test, "Get AVLN");
+
+ test_begin (test, "Get an AVLN")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ uint i, j;
+ /* configuring the test. */
+ test_sta_mgr_init (&cp);
+ for (i = 0; i < HPAV_AVLNS_NB_MAX; i++)
+ net = cp_sta_mgr_add_avln (&cp, i, i);
+ for (i = 0; i < HPAV_AVLNS_NB_MAX; i++)
+ {
+ test_fail_unless (cp.sta_mgr.networks[i].present);
+ for (j = 0; j < HPAV_AVLNS_NB_MAX; j++)
+ {
+ if (i != j)
+ {
+ test_fail_unless (
+ cp.sta_mgr.networks[i].snid
+ != cp.sta_mgr.networks[j].snid);
+ test_fail_unless (
+ cp.sta_mgr.networks[i].nid
+ != cp.sta_mgr.networks[j].nid);
+ }
+ }
+ }
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_get_first_next_avln (test_t test)
+{
+ test_case_begin (test, "Get first and next AVLN");
+
+ test_begin (test, "Get first and next AVLN")
+ {
+ cp_t cp;
+ cp_net_t *net_cmp[3];
+ cp_net_t *net;
+
+ /* configuring the test. */
+ test_sta_mgr_init (&cp);
+
+ /* Add AVLN. */
+ net_cmp[0] = cp_sta_mgr_add_avln (&cp, 2, 2);
+ net_cmp[1] = cp_sta_mgr_add_avln (&cp, 3, 3);
+ net_cmp[2] = cp_sta_mgr_add_avln (&cp, 4, 4);
+
+ /* Get the AVLN. */
+ net = cp_sta_mgr_get_first_avln (&cp);
+ test_fail_if (net_cmp[0] != net);
+ net = cp_sta_mgr_get_next_avln (&cp, net);
+ test_fail_if (net_cmp[1] != net);
+ net = cp_sta_mgr_get_next_avln (&cp, net);
+ test_fail_if (net_cmp[2] != net);
+ net = cp_sta_mgr_get_next_avln (&cp, net);
+ test_fail_if (NULL != net);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_net_is_empty (test_t test)
+{
+ test_case_begin (test, "Network is empty");
+
+ test_begin (test, "Network is empty")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ uint i;
+ /* configuring the test. */
+ test_sta_mgr_init (&cp);
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == true);
+ for (i = 0; i < HPAV_AVLNS_NB_MAX; i++)
+ {
+ net = cp_sta_mgr_add_avln (&cp, i, i);
+ test_fail_unless (net);
+ }
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == false);
+ /* Set our AVLN. */
+ cp_sta_mgr_set_our_avln (&cp, cp_sta_mgr_get_avln (&cp, 0, 0));
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == false);
+ /* add a station per AVLN. */
+ for (i = 0; i < HPAV_AVLNS_NB_MAX; i++)
+ {
+ net = cp_sta_mgr_get_avln (&cp, i, i);
+ test_fail_unless (net);
+ sta = cp_sta_mgr_sta_add (&cp, net, i+1, i+1);
+ slab_release (sta);
+ }
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == false);
+ /* Remove AVLN by AVLN unless our AVLN. */
+ for (i = 1; i < HPAV_AVLNS_NB_MAX; i++)
+ {
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == false);
+ cp_sta_mgr_remove_avln (&cp, i, i);
+ }
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == false);
+ /* Set present flag in our AVLN. This is just to verify that present
+ * flag in our AVLN is not used. */
+ net = cp_sta_mgr_get_our_avln (&cp);
+ net->present = false;
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == false);
+ /* Remove the station in this AVLN. */
+ cp_sta_mgr_sta_remove_from_mac (&cp, 1);
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == true);
+ net->present = true;
+ test_fail_unless (cp_sta_mgr_net_list_is_empty (&cp) == true);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_set_our_avln__no_net (test_t test)
+{
+ test_case_begin (test, "Set our AVLN, coming from unassociated state");
+
+ test_begin (test, "start")
+ {
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ cp_net_t *net;
+ cp_sta_t *sta;
+ uint i;
+ sta_t *sta_store;
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ for (i = 1; i < 4; i ++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i, i);
+ slab_release (sta);
+ }
+ test_fail_unless (cp.mac_config->partial_ack_tei_default
+ == MAC_TEI_BCAST);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ test_fail_unless (
+ MAC_TEI_IS_STA (cp.mac_config->partial_ack_tei_default));
+
+ for (i = 1; i < 4; i++)
+ {
+ sta_store = mac_store_sta_get (cp.mac_store, i);
+ sta = cp_sta_mgr_sta_get_assoc (&cp, net, i);
+ test_fail_if (cp_sta_get_tei (sta) != i);
+ test_fail_if (cp_sta_get_mac_address (sta) != i);
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, i) == i);
+ test_fail_unless (sta_store);
+ test_fail_unless (sta);
+ slab_release (sta);
+ blk_release (sta_store);
+ }
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_set_our_avln__with_net (test_t test)
+{
+ test_case_begin (test, "Set our AVLN, coming from associated state");
+
+ test_begin (test, "start")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ uint i;
+ sta_t *sta_store;
+ mfs_tx_t *mfs;
+ bool added;
+ test_sta_mgr_init (&cp);
+ /* Store a broadcast MFS. */
+ mfs = mac_store_mfs_add_tx (cp.mac_store, true, false, 1,
+ MAC_TEI_BCAST,
+ &added);
+ dbg_assert (added);
+ blk_release (mfs);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+
+ for (i = 1; i < 4; i ++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i, i);
+ slab_release (sta);
+ }
+
+ cp_sta_mgr_set_our_avln (&cp, net);
+ test_fail_unless (
+ MAC_TEI_IS_STA (cp.mac_config->partial_ack_tei_default));
+ for (i = 1; i < 4; i++)
+ {
+ sta_store = mac_store_sta_get (cp.mac_store, i);
+ sta = cp_sta_mgr_sta_get_assoc (&cp, net, i);
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, i) == i);
+ test_fail_if (sta_store == NULL);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != i);
+ test_fail_if (cp_sta_get_mac_address (sta) != i);
+
+ slab_release (sta);
+ blk_release (sta_store);
+ }
+
+ net = cp_sta_mgr_add_avln (&cp, 2, 2);
+ test_fail_unless (
+ MAC_TEI_IS_STA (cp.mac_config->partial_ack_tei_default));
+
+ for (i = 1; i < 4; i ++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i + 3, i + 3);
+ slab_release (sta);
+ }
+
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ for (i = 1; i < 4; i++)
+ {
+ sta_store = mac_store_sta_get (cp.mac_store, i + 3);
+ sta = cp_sta_mgr_sta_get_assoc (&cp, net, i + 3);
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, i+3) == i+3);
+ test_fail_if (sta_store == NULL);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != i + 3);
+ test_fail_if (cp_sta_get_mac_address (sta) != i + 3);
+
+ slab_release (sta);
+ blk_release (sta_store);
+ }
+
+ for (i = 1; i < 4; i++)
+ {
+ sta_store = mac_store_sta_get (cp.mac_store, i);
+ test_fail_if (sta_store != NULL);
+ }
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_set_our_avln__with_net_to_unassoc (test_t test)
+{
+ test_case_begin (test, "Set our AVLN, coming from associated to unassoc");
+
+ test_begin (test, "start")
+ {
+ uint i;
+ cp_sta_t *sta;
+ sta_t *sta_store;
+ cp_net_t *net;
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+
+ for (i = 1; i < 4; i ++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i, i);
+ slab_release (sta);
+ }
+
+ cp_sta_mgr_set_our_avln (&cp, net);
+ test_fail_unless (
+ MAC_TEI_IS_STA (cp.mac_config->partial_ack_tei_default));
+
+ for (i = 1; i < 4; i++)
+ {
+ sta_store = mac_store_sta_get (cp.mac_store, i);
+ sta = cp_sta_mgr_sta_get_assoc (&cp, net, i);
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, i) == i);
+ test_fail_if (sta_store == NULL);
+ test_fail_if (sta == NULL);
+ test_fail_if (cp_sta_get_tei (sta) != i);
+ test_fail_if (cp_sta_get_mac_address (sta) != i);
+
+ slab_release (sta);
+ blk_release (sta_store);
+ }
+
+ dbg_fatal_try_begin
+ {
+ cp_sta_mgr_set_our_avln (&cp, NULL);
+
+ test_fail_if (cp.cl->mactotei != NULL);
+
+ for (i = 1; i < 4; i++)
+ {
+ sta_store = mac_store_sta_get (cp.mac_store, i);
+ test_fail_if (sta_store != NULL);
+ }
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ test_verbose_print (fatal_message);
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (cp.mac_config->partial_ack_tei_default
+ == MAC_TEI_BCAST);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_release_station (test_t test)
+{
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ sta_t *sta_store;
+ test_case_begin (test, "Release station");
+ test_begin (test, "No AVLN")
+ {
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ test_fail_if (cp_net_get_num_discovered_stas (&cp, net) != 1);
+ test_fail_if (cp_net_get_num_stas (&cp, net) != 1);
+
+ dbg_fatal_try_begin
+ {
+ cp_sta_mgr_release_station (&cp, 1);
+ }
+ dbg_fatal_try_catch (const char *fail)
+ {
+ test_verbose_print (fail);
+ test_fail_if (cp_sta_own_data_get_cco_status (&cp) == true);
+ }
+ dbg_fatal_try_end;
+
+ // The same as CCo.
+ cp_sta_own_data_set_tei (&cp, 2);
+ cp_sta_own_data_set_cco_status (&cp, true);
+ cp_sta_mgr_release_station (&cp, 1);
+
+ test_fail_if (sta->tei_lease_date_ms != CP_STA_MGR_STATION_RELEASE_MS +
+ cp_sta_core_get_date_ms (&cp));
+ test_fail_if (cp_net_get_num_discovered_stas (&cp, net) != 0);
+ test_fail_if (cp_net_get_num_stas (&cp, net) != 0);
+
+ /* Launch the garbage. */
+ cp_sta_mgr_garbage (&cp);
+
+ test_fail_if (list_empty (&cp.sta_mgr.release_sta_list) == true);
+
+ /* modify the lease to make the station expire. */
+ sta->tei_lease_date_ms = 0;
+ slab_release (sta);
+
+ cp_sta_mgr_garbage (&cp);
+ test_fail_if (list_empty (&cp.sta_mgr.release_sta_list) == false);
+
+ /* Verify the store. */
+ sta_store = mac_store_sta_get (cp.mac_store, 1);
+ test_fail_if (sta_store != NULL);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "Change AVLN")
+ {
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+
+ // The same as CCo.
+ cp_sta_own_data_set_tei (&cp, 2);
+ cp_sta_own_data_set_cco_status (&cp, true);
+ cp_sta_mgr_release_station (&cp, 1);
+
+ test_fail_if (sta->tei_lease_date_ms != CP_STA_MGR_STATION_RELEASE_MS +
+ cp_sta_core_get_date_ms (&cp));
+
+ slab_release (sta);
+ cp_sta_mgr_set_our_avln (&cp, NULL);
+ test_fail_if (list_empty (&cp.sta_mgr.release_sta_list) == false);
+
+ /* Verify the store. */
+ sta_store = mac_store_sta_get (cp.mac_store, 1);
+ test_fail_if (sta_store != NULL);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "AVLN1 to AVLN2")
+ {
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ slab_release (sta);
+
+ // The same as CCo.
+ cp_sta_own_data_set_tei (&cp, 2);
+ cp_sta_own_data_set_cco_status (&cp, true);
+ cp_sta_mgr_release_station (&cp, 1);
+
+ net = cp_sta_mgr_add_avln (&cp, 2, 2);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+
+ // The same as CCo.
+ cp_sta_own_data_set_tei (&cp, 2);
+ cp_sta_own_data_set_cco_status (&cp, true);
+ cp_sta_mgr_release_station (&cp, 1);
+
+ test_fail_if (sta->tei_lease_date_ms != CP_STA_MGR_STATION_RELEASE_MS +
+ cp_sta_core_get_date_ms (&cp));
+
+ slab_release (sta);
+ cp_sta_mgr_set_our_avln (&cp, NULL);
+ test_fail_if (list_empty (&cp.sta_mgr.release_sta_list) == false);
+
+ /* Verify the store. */
+ sta_store = mac_store_sta_get (cp.mac_store, 1);
+ test_fail_if (sta_store != NULL);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_partial_ack (test_t test)
+{
+ test_case_begin (test, "Partial acknowledge");
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ cp_net_t *net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_own_data_set_tei (&cp, 254);
+ test_begin (test, "No STA")
+ {
+ cp_sta_mgr_elects_sta_partial_ack (&cp);
+ test_fail_unless (cp.mac_config->partial_ack_tei_default
+ == MAC_TEI_BCAST);
+ }
+ test_end;
+ test_begin (test, "Single STA")
+ {
+ uint i;
+ cp_sta_t *sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ for (i = 0; i < 20; i++)
+ {
+ cp_sta_mgr_elects_sta_partial_ack (&cp);
+ test_fail_unless (cp.mac_config->partial_ack_tei_default
+ == cp_sta_get_tei (sta));
+ }
+ slab_release (sta);
+ }
+ test_end;
+ test_begin (test, "Two STA")
+ {
+ uint i;
+ bool teis[3] = {false, false, false};
+ cp_sta_t *sta = cp_sta_mgr_sta_add (&cp, net, 2, 2);
+ for (i = 0; i < 20; i++)
+ {
+ cp_sta_mgr_elects_sta_partial_ack (&cp);
+ teis[cp.mac_config->partial_ack_tei_default] = true;
+ }
+ test_fail_unless (teis[0] == false);
+ for (i = 1; i < COUNT (teis); i++)
+ test_fail_unless (teis[i] == true);
+ slab_release (sta);
+ }
+ test_end;
+ test_sta_mgr_uninit (&cp);
+}
+
+void
+test_case__cp_sta_mgr_change_snid (test_t test)
+{
+ test_case_begin (test, "Change snid");
+
+ test_begin (test, "CCo")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_own_data_set_tei (&cp, 1);
+ cp_sta_own_data_set_authenticated_status (&cp, true);
+ cp_sta_own_data_set_cco_status (&cp, true);
+
+ /* Change our AVLN. */
+ cp_sta_own_data_set_snid (&cp, 0x3);
+
+ test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x3);
+ test_fail_unless (net->snid == 0x3);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "Station")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+
+ test_fail_unless (net->snid == 0x1);
+
+ /* Change our AVLN. */
+ cp_sta_own_data_set_snid (&cp, 0x3);
+
+ test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x3);
+ test_fail_unless (net->snid == 0x1);
+
+ cp_sta_own_data_set_snid (&cp, 0x1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+
+ cp_sta_own_data_set_snid (&cp, 0x3);
+
+ test_fail_unless (cp_sta_own_data_get_snid (&cp) == 0x3);
+ test_fail_unless (net->snid == 0x3);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+/** SNID present
+ *
+ * \param test the test object.
+ *
+ * Return a flag indicating which SNID is currently in use.
+ * environment 3 AVLNs with SNID 1, 5, 10.
+ * At the end of the test the flag shall contain 0x211.
+ */
+void
+test_case_snid_present (test_t test)
+{
+ cp_t cp;
+ uint i;
+ u16 snidFlags, snidfcmp = 0;
+ memset (&cp, 0, sizeof (cp_t));
+ test_case_begin (test, "Getting present SNID");
+ cp_snid_t snid [] = {1, 5, 10};
+ for (i = 0; i < COUNT (snid); i++)
+ {
+ cp_sta_mgr_add_avln (&cp, snid[i], i);
+ snidfcmp = snidfcmp | ((u16) 1 << snid[i]);
+ }
+ snidFlags = cp_sta_mgr_get_present_snids (&cp);
+ test_begin (test, "Verifying the flags")
+ {
+ test_fail_unless (snidFlags == snidfcmp);
+ }
+ test_end;
+}
+
+/** Get slot usage
+ * \param test the test object.
+ *
+ * Environment
+ * Add three AVLN in the station manager configured as followed:
+ *
+ * * AVLN 1 : Slot id = 4;
+ * * AVLN 2 : Slot id = 7;
+ * * AVLN 3 : Slot id = 2;
+ *
+ * This makes a slot usage equal to 0x94.
+ *
+ * Result
+ * This function shall return 0x94.
+ */
+void
+test_case_slot_usage (test_t test)
+{
+ cp_t cp;
+ cp_net_t *net;
+ bool csma_only = false;
+ lib_rnd_init (&cp.rnd, 0x3421);
+ test_case_begin (test, "Getting the slot usage");
+ test_begin (test, "slot usage.")
+ {
+ uint loop;
+ for (loop = 0; loop < 2; loop++)
+ {
+ test_sta_mgr_init (&cp);
+ uint i;
+ for (i = 1; i < 4; i++)
+ {
+ net = cp_sta_mgr_add_avln (&cp, i, i);
+ net->network_mode =
+ csma_only ? MAC_NM_CSMA_ONLY : MAC_NM_COORDINATED;
+ cp_net_set_slot_id_and_usage (&cp, net, i + 1, i + 1);
+ }
+ test_fail_if (
+ csma_only ? 0 : cp_sta_mgr_get_slot_usage (&cp) != 0x1c);
+ csma_only = true;
+ test_sta_mgr_uninit (&cp);
+ }
+ }
+ test_end;
+}
+
+void
+test_case__cp_net_num_sta_associated (test_t test)
+{
+ test_case_begin (test, "Number of stations associated");
+
+ test_begin (test, "Add 10 STAs")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+
+ memset (&cp, 0, sizeof (cp_t));
+ test_sta_mgr_init (&cp);
+
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+
+ test_fail_unless (cp_net_num_sta_associated (&cp, net) == 0);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, MAC_TEI_UNASSOCIATED, 1);
+ slab_release (sta);
+
+ test_fail_unless (cp_net_num_sta_associated (&cp, net) == 0);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ slab_release (sta);
+
+ test_fail_unless (cp_net_num_sta_associated (&cp, net) == 1);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, MAC_TEI_UNASSOCIATED, 1);
+ slab_release (sta);
+
+ test_fail_unless (cp_net_num_sta_associated (&cp, net) == 0);
+
+ sta = cp_sta_mgr_sta_add (&cp, net, 2, 1);
+ slab_release (sta);
+
+ test_fail_unless (cp_net_num_sta_associated (&cp, net) == 1);
+
+ cp_sta_mgr_sta_remove_from_mac (&cp, 1);
+ test_fail_unless (cp_net_num_sta_associated (&cp, net) == 0);
+
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__net_blacklisted (test_t test)
+{
+ test_case_begin (test, "Network blacklisted");
+ test_begin (test, "set blacklist and check reset flag by garbage")
+ {
+ cp_t ctx;
+ cp_net_t *net;
+ test_sta_mgr_init (&ctx);
+ net = cp_sta_mgr_add_avln (&ctx, 1, 1);
+ test_fail_unless (net);
+ /* Add a station to keep the net alive. */
+ cp_sta_t *sta = cp_sta_mgr_sta_add (&ctx, net, 1, 1);
+ cp_net_blacklisted_status_set (&ctx, net, true);
+ test_fail_unless (net->blacklisted);
+ test_fail_unless (net->blacklisted
+ == cp_net_blacklisted_status_get (&ctx, net));
+ test_fail_unless (net->blacklisted_reset_date ==
+ phy_date () + MAC_MS_TO_TCK
+ (CP_STA_MGR_NET_RESET_BLACK_LISTS_MS));
+ /* Check garbage reset blacklisted flag. */
+ net->blacklisted_reset_date =
+ phy_date () - MAC_MS_TO_TCK
+ (CP_STA_MGR_NET_RESET_BLACK_LISTS_MS + 1);
+ cp_sta_mgr_garbage (&ctx);
+ test_fail_unless (!net->blacklisted);
+ test_fail_unless (net->blacklisted
+ == cp_net_blacklisted_status_get (&ctx, net));
+ test_fail_unless (net->present);
+ slab_release (sta);
+ test_sta_mgr_uninit (&ctx);
+ }
+ test_end;
+}
+
+void
+test_case__cp_sta_mgr_remove_our_avln (test_t t)
+{
+ test_begin (t, "Remove our AVLN")
+ {
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ uint i;
+ cp_net_t *net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_t *sta;
+ for (i = 0; i < 10; i++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i+1, i+1);
+ slab_release (sta);
+ }
+ test_fail_unless (!cp.sta_mgr.our_avln);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ test_fail_unless (cp.sta_mgr.our_avln);
+ cp_sta_mgr_remove_avln (&cp, 1, 1);
+ test_fail_unless (!cp.sta_mgr.our_avln);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__set_tracking (test_t t)
+{
+ test_case_begin (t, "Set tracking");
+ test_begin (t, "track new network")
+ {
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+#if CONFIG_DEBUG
+ dbg_fatal_try_begin
+ {
+ /* No network is present and the debug mode is activated, this
+ * should assert. */
+ cp_av_sta_mgr_set_tracking (&cp, 0x1, 0x1ll);
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ test_verbose_print (fatal_message);
+ }
+ dbg_fatal_try_end;
+#endif
+ /* Add an AVLN. */
+ cp_net_t *net = cp_sta_mgr_add_avln (&cp, 0x10, 0x10ll);
+ /* Request to track this network. */
+ cp_av_sta_mgr_set_tracking (
+ &cp, cp_net_get_snid (&cp, net),
+ cp_net_get_nid (&cp, net));
+ test_fail_unless (
+ cp_sta_own_data_get_snid (&cp) == cp_net_get_snid (&cp, net));
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__commit_to_dataplane (test_t test)
+{
+ test_case_begin (test, "Commit to dataplane");
+ test_begin (test, "Network only")
+ {
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ cp_net_t *net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_t *sta;
+ uint i;
+ for (i = MAC_TEI_STA_MIN; i < MAC_TEI_STA_MAX; i++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i, i);
+ slab_release (sta);
+ }
+ cp_sta_mgr_commit_to_dataplane (&cp);
+ /* Check all the station have been added to both mac store and
+ * cl_mactotei table. */
+ sta_t *ms;
+ for (i = MAC_TEI_STA_MIN; i < MAC_TEI_STA_MAX; i++)
+ {
+ ms = mac_store_sta_get (cp.mac_store, i);
+ test_fail_unless (ms);
+ blk_release (ms);
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, i) == i);
+ }
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+ test_begin (test, "Network + bridged MAC address.")
+ {
+ cp_t cp;
+ test_sta_mgr_init (&cp);
+ cp_net_t *net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_t *sta;
+ uint i;
+ mac_t smac[] = { MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x01),
+ MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x02)};
+ /* Fill the bridge RX table. */
+ for (i = 0; i <= COUNT (smac); i++)
+ {
+ sta = cp_sta_mgr_sta_add (&cp, net, i+1, i+1);
+ slab_release (sta);
+ cl_brg_rx_add (cp.cl, smac[i], i+1);
+ }
+ cl_brg_rx_add (cp.cl, 4, 4);
+ cp_sta_mgr_garbage (&cp);
+ for (i = 0; i < COUNT (smac); i++)
+ {
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, smac[i]) == i+1);
+ }
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, 4) == 0);
+ /* All bridged mac addresses are now behind the same station. */
+ for (i = 0; i < COUNT (smac); i++)
+ cl_brg_rx_add (cp.cl, smac[i], 1);
+ cp_sta_mgr_garbage (&cp);
+ for (i = 0; i < COUNT (smac); i++)
+ {
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, smac[i]) == 1);
+ }
+ /* The Bridged mac addr moved again to their initial position. */
+ for (i = 0; i <= COUNT (smac); i++)
+ cl_brg_rx_add (cp.cl, smac[i], i+1);
+ cp_sta_mgr_garbage (&cp);
+ for (i = 0; i < COUNT (smac); i++)
+ {
+ test_fail_unless (
+ cl_mactotei_table_find_tei_from_mac (cp.cl, smac[i]) == i+1);
+ }
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_case__present_timeout (test_t test)
+{
+ test_case_begin (test, "Station presence timeout");
+ cp_t ctx;
+ test_sta_mgr_init (&ctx);
+ /* Our mac address and station mac address. */
+ mac_t my_mac = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x01);
+ mac_t its_mac = MAC_ADDRESS (0x00, 0x13, 0xd7, 0x00, 0x00, 0x02);
+ /* Add two networks. */
+ cp_net_t *net_our = cp_sta_mgr_add_avln (&ctx, 1, 1);
+ cp_net_t *net_neighbour = cp_sta_mgr_add_avln (&ctx, 2, 2);
+ /* Configure an array of AVLNS. */
+ cp_net_t *avlns[] = {net_our, net_neighbour};
+ /* Array of CCo status. */
+ bool cco_status[] = {false, true};
+ /* Set our AVLN, TEI and mac address. */
+ cp_sta_own_data_set_tei (&ctx, 254);
+ cp_sta_own_data_set_mac_address (&ctx, my_mac);
+ cp_sta_mgr_set_our_avln (&ctx, net_our);
+ /* Test the timeouts, */
+ test_begin (test, "not CCo/CCo")
+ {
+ uint i, j;
+ for (i = 0; i < COUNT (cco_status); i++)
+ {
+ for (j = 0; j < COUNT (avlns); j++)
+ {
+ u32 expired_date_ms = cp_sta_core_get_date_ms (&ctx)
+ + ((avlns[j] == net_our) && cco_status[i] ?
+ HPAV_STA_PRESENCE_TIMEOUT_INSIDE_AVLN_MS :
+ HPAV_DISCOVERED_LIST_EXPIRE_TIME_MS);
+ cp_sta_own_data_set_cco_status (&ctx, cco_status[i]);
+ cp_sta_t *sta = cp_sta_mgr_sta_add (
+ &ctx, avlns[j], 1, its_mac);
+ test_fail_unless (sta->expired_date_ms == expired_date_ms);
+ cp_sta_mgr_sta_remove (&ctx, sta);
+ slab_release (sta);
+ }
+ }
+ }
+ test_end;
+ test_sta_mgr_uninit (&ctx);
+}
+
+void
+test_suite_sta_mgr (test_t test)
+{
+ test_suite_begin (test, "sta mgr");
+ test_case__cp_sta_mgr_sta (test);
+ test_case__cp_net_uninit (test);
+ test_case__cp_sta_manager_garbage (test);
+ test_case__cp_net_pco (test);
+ test_case__cp_net_sta_get_first_next (test);
+ test_case__cp_sta_mgr_get_avln (test);
+ test_case__cp_sta_mgr_get_first_next_avln (test);
+ test_case__cp_net_is_empty (test);
+ test_case__cp_sta_mgr_set_our_avln__no_net (test);
+ test_case__cp_sta_mgr_set_our_avln__with_net (test);
+ test_case__cp_sta_mgr_set_our_avln__with_net_to_unassoc (test);
+ test_case__cp_sta_mgr_release_station (test);
+ test_case__cp_sta_mgr_remove_our_avln (test);
+ test_case__cp_sta_mgr_partial_ack (test);
+ test_case__cp_sta_mgr_change_snid (test);
+ test_case_snid_present (test);
+ test_case_slot_usage (test);
+ test_case__cp_net_num_sta_associated (test);
+ test_case__net_blacklisted (test);
+ test_case__set_tracking (test);
+ test_case__commit_to_dataplane (test);
+ test_case__present_timeout (test);
+}
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/station_test.c b/cesar/cp/av/sta/mgr/test/utest/src/station_test.c
new file mode 100644
index 0000000000..d97cf8a890
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/station_test.c
@@ -0,0 +1,431 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/station_test.c
+ * \brief Test the station.
+ * \ingroup cp_sta_mgr
+ *
+ */
+#include "common/std.h"
+#include "test_sta_mgr.h"
+
+#include "cp/sta/mgr/inc/sta.h"
+
+/**
+ * Initialise a station.
+ *
+ */
+void
+test_case_station_init (test_t test)
+{
+ cp_sta_t *sta;
+ cp_sta_private_t station;
+ slab_cache_t sta_slab_cache;
+
+ test_case_begin (test, "Station init");
+ test_begin (test, "verify data")
+ {
+ slab_cache_init (&sta_slab_cache,
+ "Station cache",
+ sizeof (cp_sta_private_t),
+ (slab_object_destructor_t) cp_sta_uninit);
+
+
+ memset (&station, 0, sizeof (cp_sta_private_t));
+ station.association_confirmed = true;
+ station.visible = true;
+ sta = cp_sta_init (&sta_slab_cache);
+
+ test_fail_if (memcmp(sta, &station,
+ sizeof(cp_sta_private_t)) != 0,
+ "Wrong sta is not initialised");
+
+
+ slab_release (sta);
+ }
+ test_end;
+}
+
+/**
+ * Get the TEI of the station.
+ *
+ * \param test the test object.
+ */
+void
+test_case_get_tei (test_t test)
+{
+ cp_sta_private_t station;
+
+ memset (&station, '\0', sizeof (cp_sta_private_t));
+
+ test_case_begin (test, "get station TEI");
+
+ station.tei = 0xA;
+
+ test_begin (test, "Getting TEI")
+ {
+ test_fail_if (cp_sta_get_tei ((cp_sta_t *) &station) != 0xA,
+ "Wrong TEI");
+ }
+ test_end;
+}
+
+/**
+ * Get the Mac address of the station.
+ *
+ * \param test the test object.
+ */
+void
+test_case_get_mac_addr (test_t test)
+{
+ cp_sta_private_t station;
+
+ memset (&station, '\0', sizeof (cp_sta_private_t));
+
+ test_case_begin (test, "get station Mac address");
+
+ station.mac_address = 0x123456789abcull;
+
+ test_begin (test, "Getting Mac address")
+ {
+ test_fail_if (cp_sta_get_mac_address ((cp_sta_t *) &station)
+ != 0x123456789abcull,
+ "Wrong Mac address");
+ }
+ test_end;
+}
+
+/**
+ * Get the peer structure of the station.
+ *
+ * \param test the test object.
+ */
+void
+test_case_get_peer (test_t test)
+{
+ cp_sta_private_t station;
+
+ memset (&station, '\0', sizeof (cp_sta_private_t));
+
+ test_case_begin (test, "get station peer");
+
+ station.tei = 0xA;
+ station.mac_address = 0x123456789abcull;
+
+ test_begin (test, "Getting peer")
+ {
+ cp_mme_peer_t peer;
+ cp_sta_get_peer ((cp_sta_t *) &station, &peer);
+ test_fail_if (!cp_mme_peer_cmp (
+ &peer, &CP_MME_PEER (0x123456789abcull, 0xA)),
+ "Wrong peer");
+ }
+ test_end;
+}
+
+/**
+ * Get the CCo status of the station.
+ *
+ * \param test the test object.
+ */
+void
+test_case_get_cco_status (test_t test)
+{
+ cp_sta_private_t station;
+
+ memset (&station, '\0', sizeof (cp_sta_private_t));
+
+ test_case_begin (test, "get station CCo status");
+
+ test_begin (test, "Getting CCo status")
+ {
+ test_fail_if (cp_sta_get_cco_status ((cp_sta_t *) &station)
+ != false,
+ "Wrong CCo status");
+ }
+ test_end;
+
+ station.is_cco = true;
+
+ test_begin (test, "Getting CCo status true")
+ {
+ test_fail_if (cp_sta_get_cco_status ((cp_sta_t *) &station)
+ != true,
+ "Wrong CCo status");
+ }
+ test_end;
+}
+
+/**
+ * Get the PCo status of the station.
+ *
+ * \param test the test object.
+ */
+void
+test_case_get_pco_status (test_t test)
+{
+ cp_sta_private_t station;
+
+ memset (&station, '\0', sizeof (cp_sta_private_t));
+
+ test_case_begin (test, "get station PCo status");
+
+ test_begin (test, "Getting PCo status")
+ {
+ test_fail_if (cp_sta_get_pco_status ((cp_sta_t *) &station)
+ != false,
+ "Wrong PCo status");
+ }
+ test_end;
+
+ station.pco_glid = 0x80;
+
+ test_begin (test, "Getting PCo status true")
+ {
+ test_fail_if (cp_sta_get_pco_status ((cp_sta_t *) &station)
+ != true,
+ "Wrong PCo status");
+ }
+ test_end;
+}
+
+void
+test_case_authenticated (test_t test)
+{
+ test_case_begin (test, "Authentication");
+
+ test_begin (test, "set & get authentication")
+ {
+ cp_t cp;
+ cp_net_t net;
+ cp_sta_private_t station;
+ cp_sta_t *sta = (cp_sta_t *) &station;
+
+ memset (&station, 0, sizeof (cp_sta_private_t));
+ memset (&cp, 0, sizeof (cp_t));
+
+ /* configure the test. */
+ cp.mac_store = mac_store_init ();
+ cp.sta_mgr.our_avln = &net;
+ station.tei = 0xA;
+ station.net = &net;
+ mac_store_sta_add (cp.mac_store, station.tei);
+
+ cp_sta_set_authenticated (&cp, sta, true);
+ test_fail_if (cp_sta_get_authenticated (&cp, sta) != true);
+
+ cp_sta_set_authenticated (&cp, sta, false);
+ test_fail_if (cp_sta_get_authenticated (&cp, sta) != false);
+
+ dbg_check (mac_store_sta_remove (cp.mac_store, station.tei));
+
+ station.tei = MAC_TEI_UNASSOCIATED;
+ test_fail_if (cp_sta_get_authenticated (&cp, sta) != false);
+ mac_store_uninit (cp.mac_store);
+ }
+ test_end;
+
+ test_begin (test, "set authentication TEI = 0")
+ {
+ cp_t cp;
+ cp_net_t net;
+ cp_sta_private_t station;
+ cp_sta_t *sta = (cp_sta_t *) &station;
+
+ memset (&station, 0, sizeof (cp_sta_private_t));
+ memset (&cp, 0, sizeof (cp_t));
+
+ /* configure the test. */
+ cp.mac_store = mac_store_init ();
+ cp.sta_mgr.our_avln = &net;
+ station.tei = 0;
+ station.net = &net;
+
+ cp_sta_set_authenticated (&cp, sta, false);
+ mac_store_uninit (cp.mac_store);
+ }
+ test_end;
+}
+
+void
+test_case_visible_state (test_t test)
+{
+ test_case_begin (test, "Visible state");
+
+ test_begin (test, "station visible state")
+ {
+ cp_t cp;
+ cp_net_t net;
+ cp_sta_private_t sta;
+
+ memset (&cp, 0, sizeof (cp_t));
+ memset (&net, 0, sizeof (cp_net_t));
+ memset (&sta, 0, sizeof (cp_sta_private_t));
+
+ /* configure the stations. */
+ sta.net = &net;
+ sta.tei = 1;
+
+ cp_sta_set_visible_status (&cp, (cp_sta_t *) &sta,
+ CP_STA_VISIBLE_STATE_VISIBLE);
+ test_fail_if (cp_net_get_num_discovered_stas (&cp, &net) != 1);
+
+ cp_sta_set_visible_status (&cp, (cp_sta_t *) &sta,
+ CP_STA_VISIBLE_STATE_HIDDEN);
+ test_fail_if (cp_net_get_num_discovered_stas (&cp, &net) != 0);
+ test_fail_if (cp_sta_get_visible_status ((cp_sta_t *) &sta) !=
+ CP_STA_VISIBLE_STATE_HIDDEN);
+ }
+ test_end;
+
+ test_begin (test, "station visible state in our AVLN")
+ {
+ cp_t cp;
+ cp_net_t net;
+ cp_sta_private_t sta;
+ sta_t *sta_store;
+
+ memset (&cp, 0, sizeof (cp_t));
+ memset (&net, 0, sizeof (cp_net_t));
+ memset (&sta, 0, sizeof (cp_sta_private_t));
+
+ /* configure the stations. */
+ sta.net = &net;
+ sta.tei = 1;
+ cp.sta_mgr.our_avln = &net;
+ cp.mac_store = mac_store_init ();
+
+ mac_store_sta_add (cp.mac_store, sta.tei);
+ sta_store = mac_store_sta_get (cp.mac_store, 1);
+
+ cp_sta_set_assoc_confirmed (&cp, (cp_sta_t*) &sta, false);
+ test_fail_unless (sta_store->multi_unicast_receiver == false);
+
+ cp_sta_set_visible_status (&cp, (cp_sta_t *) &sta,
+ CP_STA_VISIBLE_STATE_VISIBLE);
+ test_fail_if (cp_net_get_num_discovered_stas (&cp, &net) != 1);
+ test_fail_unless (sta_store->multi_unicast_receiver == false);
+
+ cp_sta_set_assoc_confirmed (&cp, (cp_sta_t*) &sta, true);
+ test_fail_if (sta_store->multi_unicast_receiver != true);
+
+ cp_sta_set_visible_status (&cp, (cp_sta_t *) &sta,
+ CP_STA_VISIBLE_STATE_HIDDEN);
+ test_fail_if (cp_net_get_num_discovered_stas (&cp, &net) != 0);
+ test_fail_if (cp_sta_get_visible_status ((cp_sta_t *) &sta) !=
+ CP_STA_VISIBLE_STATE_HIDDEN);
+
+ test_fail_if (sta_store->multi_unicast_receiver != false);
+ blk_release (sta_store);
+
+ dbg_check (mac_store_sta_remove (cp.mac_store, 1));
+ mac_store_uninit (cp.mac_store);
+ }
+ test_end;
+
+}
+
+void
+test_case_pco_glid (test_t test)
+{
+ test_case_begin (test, "PCo GLID");
+
+ test_begin (test, "PCo GLID")
+ {
+ cp_sta_private_t sta;
+
+ memset (&sta, 0, sizeof (cp_sta_private_t));
+
+ cp_sta_set_pco_glid ((cp_sta_t *) &sta, 0x95);
+ test_fail_if (cp_sta_get_pco_glid ((cp_sta_t *) &sta) != 0x95);
+ test_fail_if (cp_sta_get_pco_status ((cp_sta_t *) &sta) != true);
+
+ cp_sta_set_pco_glid ((cp_sta_t *) &sta, 0x0);
+ test_fail_if (cp_sta_get_pco_glid ((cp_sta_t *) &sta) != 0x0);
+ test_fail_if (cp_sta_get_pco_status ((cp_sta_t *) &sta) != false);
+ }
+ test_end;
+}
+
+void
+test_case_multi_association_confirmed (test_t test)
+{
+ test_case_begin (test, "Association confirmed");
+ test_begin (test, "Visible station")
+ {
+ cp_t cp;
+ /* Configure the test. */
+ test_sta_mgr_init (&cp);
+ cp_net_t *net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ cp_sta_t *sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ sta_t *sta_store;
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_own_data_set_tei (&cp, 2);
+ cp_sta_own_data_set_cco_status (&cp, true);
+ /* begin the test. */
+ cp_sta_set_visible_status (&cp, sta, CP_STA_VISIBLE_STATE_VISIBLE);
+ cp_sta_set_assoc_confirmed (&cp, sta, true);
+ sta_store = mac_store_sta_get (cp.mac_store, 1);
+ test_fail_unless (cp_sta_get_assoc_confirmed (&cp, sta));
+ test_fail_unless (sta_store->multi_unicast_receiver);
+ /* Change the state. */
+ cp_sta_set_assoc_confirmed (&cp, sta, false);
+ test_fail_unless (!cp_sta_get_assoc_confirmed (&cp, sta));
+ test_fail_unless (!sta_store->multi_unicast_receiver);
+ /* Uninitialise */
+ slab_release (sta);
+ blk_release (sta_store);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+
+ test_begin (test, "Hidden station")
+ {
+ cp_t cp;
+ cp_net_t *net;
+ cp_sta_t *sta;
+ sta_t *sta_store;
+ /* Configure the test. */
+ test_sta_mgr_init (&cp);
+ net = cp_sta_mgr_add_avln (&cp, 1, 1);
+ sta = cp_sta_mgr_sta_add (&cp, net, 1, 1);
+ cp_sta_mgr_set_our_avln (&cp, net);
+ cp_sta_own_data_set_tei (&cp, 2);
+ /* begin the test. */
+ cp_sta_set_visible_status (&cp, sta, CP_STA_VISIBLE_STATE_HIDDEN);
+ cp_sta_set_assoc_confirmed (&cp, sta, true);
+ sta_store = mac_store_sta_get (cp.mac_store, 1);
+ test_fail_unless (cp_sta_get_assoc_confirmed (&cp, sta));
+ test_fail_unless (!sta_store->multi_unicast_receiver);
+ /* Change the state. */
+ cp_sta_set_assoc_confirmed (&cp, sta, false);
+ test_fail_unless (!cp_sta_get_assoc_confirmed (&cp, sta));
+ test_fail_unless (!sta_store->multi_unicast_receiver);
+ /* Uninitialise */
+ slab_release (sta);
+ blk_release (sta_store);
+ test_sta_mgr_uninit (&cp);
+ }
+ test_end;
+}
+
+void
+test_suite_station (test_t test)
+{
+ test_suite_begin (test, "station");
+ test_case_station_init (test);
+ test_case_get_tei (test);
+ test_case_get_mac_addr (test);
+ test_case_get_peer (test);
+ test_case_get_cco_status (test);
+ test_case_get_pco_status (test);
+ test_case_authenticated (test);
+ test_case_visible_state (test);
+ test_case_pco_glid (test);
+ test_case_multi_association_confirmed (test);
+}
diff --git a/cesar/cp/av/sta/mgr/test/utest/src/test_sta_mgr.c b/cesar/cp/av/sta/mgr/test/utest/src/test_sta_mgr.c
new file mode 100644
index 0000000000..8b25b6746f
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/src/test_sta_mgr.c
@@ -0,0 +1,72 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/mgr/test/src/test_sta_mgr.c
+ * \brief Test environment.
+ * \ingroup cp_sta_mgr
+ */
+#include "common/std.h"
+#include "test_sta_mgr.h"
+
+void
+test_sta_mgr_init (cp_t *cp)
+{
+ static mac_config_t mac_config;
+ static cl_t cl;
+ static sar_t sar;
+ mac_config_init (&mac_config);
+ memset (&cl, 0, sizeof (cl_t));
+ memset (&sar, 0, sizeof (sar_t));
+ memset (cp, 0, sizeof (cp_t));
+ cp->mac_config = &mac_config;
+ cp->cl = &cl;
+ cp->sar = &sar;
+ cp->mac_store = sar.mac_store = mac_store_init ();
+ lib_rnd_init (&cp->rnd, 1234);
+ cp_sta_mgr_init (cp);
+}
+
+void
+test_sta_mgr_uninit (cp_t *cp)
+{
+ cp_sta_mgr_uninit (cp);
+ mac_store_uninit (cp->mac_store);
+}
+
+void
+test_suite_sta_mgr (test_t test);
+
+void
+test_suite_net (test_t test);
+
+void
+test_suite_sta_own (test_t test);
+
+void
+test_suite_station (test_t test);
+
+int
+main (int argc, char **argv)
+{
+ test_t test;
+ test_init (test, argc, argv);
+ test_suite_sta_mgr (test);
+ test_suite_net (test);
+ test_suite_sta_own (test);
+ test_suite_station (test);
+
+ test_case_begin (test, "Memory allocation");
+ test_begin (test, "memory leaks")
+ {
+ test_fail_if (blk_check_memory () != true, "Memory leaks");
+ }
+ test_end;
+
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/cp/av/sta/mgr/test/utest/test_sta_mgr.h b/cesar/cp/av/sta/mgr/test/utest/test_sta_mgr.h
new file mode 100644
index 0000000000..fa00768521
--- /dev/null
+++ b/cesar/cp/av/sta/mgr/test/utest/test_sta_mgr.h
@@ -0,0 +1,54 @@
+#ifndef cp_sta_mgr_test_test_sta_mgr_h
+#define cp_sta_mgr_test_test_sta_mgr_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/sta/mgr/test/test_sta_mgr.h
+ * \brief Test environment.
+ * \ingroup cp_sta_mgr
+ */
+#include "lib/test.h"
+#include "cp/cp.h"
+#include "cp/sta/mgr/sta_mgr.h"
+#include "cp/sta/core/core.h"
+
+#include "mac/common/ntb.h"
+#include "mac/common/timings.h"
+#include "mac/sar/sar.h"
+#include "cl/cl.h"
+
+/* Override includes. */
+#include "mac/sar/inc/context.h"
+#include "cl/inc/context.h"
+#include "cp/inc/context.h"
+
+#include "cl/cl_mactotei.h"
+
+struct cl_mactotei_t
+{
+ mac_t mac;
+ cp_tei_t tei;
+ uint tag;
+};
+typedef struct cl_mactotei_t cl_mactotei_t;
+
+/**
+ * Initialise all necessary data for the station manager test.
+ * \param cp the control plane override structure.
+ */
+void
+test_sta_mgr_init (cp_t *cp);
+
+/**
+ * Uninitialise the environment of test for station manager.
+ * \param cp the control plane override structure.
+ */
+void
+test_sta_mgr_uninit (cp_t *cp);
+
+#endif /* cp_sta_mgr_test_test_sta_mgr_h */