summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/mac/pbproc')
-rw-r--r--cesar/mac/pbproc/Config3
-rw-r--r--cesar/mac/pbproc/inc/context.h33
-rw-r--r--cesar/mac/pbproc/inc/fc.h221
-rw-r--r--cesar/mac/pbproc/inc/prep_mpdu.h16
-rw-r--r--cesar/mac/pbproc/pbproc.h16
-rw-r--r--cesar/mac/pbproc/src/fsm.c10
-rw-r--r--cesar/mac/pbproc/src/fsm_handle_fc.c128
-rw-r--r--cesar/mac/pbproc/src/fsm_rx_beacon.c11
-rw-r--r--cesar/mac/pbproc/src/fsm_rx_data.c185
-rw-r--r--cesar/mac/pbproc/src/fsm_rx_sound.c67
-rw-r--r--cesar/mac/pbproc/src/fsm_top.c11
-rw-r--r--cesar/mac/pbproc/src/fsm_tx_data.c210
-rw-r--r--cesar/mac/pbproc/src/fsm_tx_sound.c32
-rw-r--r--cesar/mac/pbproc/src/pbproc.c23
-rw-r--r--cesar/mac/pbproc/src/prep_mpdu.c437
-rw-r--r--cesar/mac/pbproc/src/trace.c67
-rw-r--r--cesar/mac/pbproc/stub/Module1
-rw-r--r--cesar/mac/pbproc/stub/src/pbproc_stub.c26
-rw-r--r--cesar/mac/pbproc/test/fsm/Makefile1
-rw-r--r--cesar/mac/pbproc/test/int/Config7
-rw-r--r--cesar/mac/pbproc/test/int/Makefile2
-rw-r--r--cesar/mac/pbproc/test/int/src/add_seg.c4
-rw-r--r--cesar/mac/pbproc/test/int/src/test_pbproc.c9
-rw-r--r--cesar/mac/pbproc/test/pbproc/src/test_pbproc.c3
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/Config7
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/Makefile15
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/inc/scenario_defs.h349
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/inc/test_pbproc.h96
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/inc/utils.h82
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/ca.c179
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/hal.c27
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/phy.c400
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/prep_mpdu.c1925
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/rx_data.c1932
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/rx_sound.c353
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/scenario_defs.c166
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/test_pbproc.c502
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/tx_data.c923
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/tx_sound.c377
-rw-r--r--cesar/mac/pbproc/test/pbproc_eoc/src/utils.c271
40 files changed, 9060 insertions, 67 deletions
diff --git a/cesar/mac/pbproc/Config b/cesar/mac/pbproc/Config
index 39ca0616a6..5459f97df6 100644
--- a/cesar/mac/pbproc/Config
+++ b/cesar/mac/pbproc/Config
@@ -1,5 +1,8 @@
+CONFIG_MAC_PBPROC_EOC_ILRAM = n
CONFIG_GPIO_LED_TRAFFIC = n
CONFIG_GPIO_LED_TRAFFIC_GPIO = 2
CONFIG_GPIO_LED_PBPROC_ALIVE = n
CONFIG_GPIO_LED_PBPROC_ALIVE_GPIO = 3
+CONFIG_GPIO_LED_PBPROC_WORKING = n
+CONFIG_GPIO_LED_PBPROC_WORKING_GPIO = 0
CONFIG_MAC_PBPROC_BEACON_RTSCTS = n
diff --git a/cesar/mac/pbproc/inc/context.h b/cesar/mac/pbproc/inc/context.h
index e0c294762c..d7cfcbc3ea 100644
--- a/cesar/mac/pbproc/inc/context.h
+++ b/cesar/mac/pbproc/inc/context.h
@@ -30,7 +30,8 @@
#define PBPROC_ANTICIP_TCK MAC_US_TO_TCK (80)
/** Anticipation for TX once MPDU is ready to be sent. */
-#define PBPROC_TX_ANTICIP_TCK MAC_US_TO_TCK (22 + 5)
+#define PBPROC_TX_ANTICIP_TCK \
+ (!CONFIG_MAC_PBPROC_EOC_FC ? MAC_US_TO_TCK (22 + 5) : MAC_US_TO_TCK (8))
/** If the total number of PB exceed this threshold, request an interrupt
* before the end of frame reception to compute SACKD. */
@@ -39,14 +40,22 @@
/** Number of PB before frame end for first step of SACKD computation (there
* can be only one PB in the last symbol, and at most three PB in the symbol
* before. */
-#define PBPROC_SACKD_ANTICIP_PB_NB 4
+#define PBPROC_SACKD_ANTICIP_PB_NB (!CONFIG_MAC_PBPROC_EOC_FC ? 4 : 8)
/** Maximum number of channel data retrieved after a frame reception. */
-#define PBPROC_CHANDATA_NB 11
+#define PBPROC_CHANDATA_NB (!CONFIG_MAC_PBPROC_EOC_FC ? 11 : 15)
/** Delay to keep detection valid for HP 1.0 and 1.1. */
#define PBPROC_HP_DETECT_DELAY_TCK MAC_MS_TO_TCK (2000)
+/** Constants for IFS-s, TODO: remove this! */
+#if CONFIG_MAC_PBPROC_EOC_FC
+/** IFS from SOF-RSOF. */
+#define MAC_CF_SOF_RSOF_IFS_TCK MAC_US_TO_TCK (100)
+/** IFS from RSOF-SOF. Also in CA + 40 uS is added to access time. */
+#define MAC_CF_RSOF_SOF_IFS_TCK MAC_US_TO_TCK (60)
+#endif
+
/** SACK data. */
struct pbproc_sackd_t
{
@@ -96,6 +105,10 @@ struct pbproc_recv_mpdu_t
bool drop;
/** SACK data. */
pbproc_sackd_t sackd;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /** Use infrastructure for ACK but not send */
+ bool send_sack;
+#endif
};
typedef struct pbproc_recv_mpdu_t pbproc_recv_mpdu_t;
@@ -184,6 +197,10 @@ struct pbproc_stat_t
uint aifs;
/** RX: out of an allocation or too near AIFS. */
uint rx_out_of_alloc;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /** RX: out of an allocation or too near AIFS for RSOF. */
+ uint rx_rsof_out_of_alloc;
+#endif
/** RX: no enough PB in pool. */
uint rx_pool_shortage;
/** RX: handle FC. */
@@ -248,6 +265,12 @@ struct pbproc_stat_t
uint tx_sound_ack;
/** TX: sound, no ack received (FIXME: this includes lost access). */
uint tx_sound_noack;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /** TX: number of packets sent empty. */
+ uint tx_data_empty;
+ /** TX: number of PB sent. */
+ uint tx_data_pb_total;
+#endif
};
typedef struct pbproc_stat_t pbproc_stat_t;
@@ -311,6 +334,10 @@ struct pbproc_t
phy_chandata_conf_t chandata_conf[PBPROC_CHANDATA_NB];
/** Number of channel data blocks to retrieve after reception. */
uint chandata_nb;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /** True if station is polled from CCO in current beacon period */
+ bool polled;
+#endif
/** Whether channel data should be collected for data MPDU. */
bool chandata_data;
};
diff --git a/cesar/mac/pbproc/inc/fc.h b/cesar/mac/pbproc/inc/fc.h
index 6c6b004307..686bfe10c5 100644
--- a/cesar/mac/pbproc/inc/fc.h
+++ b/cesar/mac/pbproc/inc/fc.h
@@ -14,11 +14,17 @@
*
* Be careful to bit order.
*/
+#include "common/module.h"
+#include "config/mac/pbproc/eoc.h"
+
+#if MODULE_INCLUDED(mac_common)
#include "mac/common/timings.h"
+#endif
#include "mac/pbproc/inc/sacki_dec.h"
+#if !CONFIG_MAC_PBPROC_EOC_FC
/* See ยง4.4.1.5.6.11 in HPAV specification for RSOF_FL_AV computation. */
/* Convert RSOF_FL_AV value to tick. */
#define PBPROC_FC_RSOF_FL_AV_TO_TCK(fl) \
@@ -29,6 +35,7 @@
((tck) > MAC_FL_TO_TCK (512) ? CEIL_DIV ((tck) - MAC_FL_TO_TCK (512), \
2 * MAC_TCK_PER_FL) + 512 \
: MAC_TCK_TO_FL (tck))
+#endif
/** Delimiter type. */
enum pbproc_fc_dt_t
@@ -120,6 +127,7 @@ typedef struct pbproc_fc_beacon_t pbproc_fc_beacon_t;
#define PBPROC_FC_BEACON_W3__BTO3_MSB8 7, 0
#define PBPROC_FC_BEACON_W3__FCCS_AV 31, 8
+#if !CONFIG_MAC_PBPROC_EOC_FC
/** Start Of Frame frame control. */
struct pbproc_fc_sof_t
{
@@ -192,6 +200,91 @@ struct pbproc_fc_sof_t
/** FCCS. */
uint fccs_av:24;)
};
+#else
+/** Start Of Frame EoC */
+struct pbproc_fc_sof_t
+{
+ BITFIELDS_WORD(
+ /** Delimiter type. */
+ pbproc_fc_dt_t dt_av:3;,
+ /** Access field. */
+ bool access:1;,
+ /** Short network identifier. */
+ uint snid:4;,
+ /** Destination terminal equipment identifier. */
+ uint dtei:8;,
+ /** Link identifier. */
+ uint lid:4;,
+ /** Encryption key select. */
+ uint eks:2;,
+ /** terminal equipment identifier
+ direction 0 C->S, 1 S->C. */
+ bool direction:1;,
+ /** PB size, true for 136. */
+ bool pbsz:1;,
+ /** Number of symbols. */
+ uint num_sym:2;,
+ /** Tone map index. */
+ uint tmi_av:5;,
+ /** Multicast flag. */
+ bool mcf:1;)
+ BITFIELDS_WORD(
+ /** Frame length. */
+ uint fl_av:12;,
+ /** MPDU count. */
+ uint mpdu_cnt:2;,
+ /** Burst count. */
+ uint burst_cnt:2;,
+ /** Max reverse transmission duration. */
+ uint mrdur_fl:12;,
+ /** Multi-network broadcast flag. */
+ bool mnbf:1;,
+ /** Bidirectional burst flag. */
+ bool bbf:1;,
+ uint sackt0:2;)
+ uint sacki0;
+ BITFIELDS_WORD(
+ uint sacki1:8;,
+ /** FCCS. */
+ uint fccs_av:24;)
+};
+
+/** EOC SACK Size. */
+enum pbproc_fc_sacki_eoc_size_t
+{
+ PBPROC_FC_SACKI_EOC_SOF_SIZE = 40, /* two fields: 32+8 */
+ PBPROC_FC_SACKI_EOC_RSOF_SIZE = 53,/* three fields: 32+21 */
+ PBPROC_FC_SACKI_EOC_SOUND_SIZE = 53, /* two fields: 32+21 */
+ PBPROC_FC_SACKI_EOC_SOF_LEFT = PBPROC_FC_SACKI_EOC_SOF_SIZE - 32,
+ PBPROC_FC_SACKI_EOC_RSOF_LEFT = PBPROC_FC_SACKI_EOC_RSOF_SIZE - 32,
+ PBPROC_FC_SACKI_EOC_SOUND_LEFT = PBPROC_FC_SACKI_EOC_SOUND_SIZE - 32,
+};
+
+#define PBPROC_FC_EOC_SOF_W0__DT_AV 2, 0
+#define PBPROC_FC_EOC_SOF_W0__ACCESS 3, 3
+#define PBPROC_FC_EOC_SOF_W0__SNID 7, 4
+#define PBPROC_FC_EOC_SOF_W0__DTEI 15, 8
+#define PBPROC_FC_EOC_SOF_W0__LID 19, 16
+#define PBPROC_FC_EOC_SOF_W0__EKS 21, 20
+#define PBPROC_FC_EOC_SOF_W0__DIRECTION 22, 22
+#define PBPROC_FC_EOC_SOF_W0__PBSZ 23, 23
+#define PBPROC_FC_EOC_SOF_W0__NUM_SYM 25, 24
+#define PBPROC_FC_EOC_SOF_W0__TMI_AV 30, 26
+#define PBPROC_FC_EOC_SOF_W0__MCF 31, 31
+
+#define PBPROC_FC_EOC_SOF_W1__FL_AV 11, 0
+#define PBPROC_FC_EOC_SOF_W1__MPDU_CNT 13, 12
+#define PBPROC_FC_EOC_SOF_W1__BURST_CNT 15, 14
+#define PBPROC_FC_EOC_SOF_W1__MRDUR_FL 27, 16
+#define PBPROC_FC_EOC_SOF_W1__MNBF 28, 28
+#define PBPROC_FC_EOC_SOF_W1__BBF 29, 29
+#define PBPROC_FC_EOC_SOF_W1__SACKT0 31, 30
+
+#define PBPROC_FC_EOC_SOF_W2__SACKI0 31, 0
+
+#define PBPROC_FC_EOC_SOF_W3__SACKI1 7, 0
+
+#endif
typedef struct pbproc_fc_sof_t pbproc_fc_sof_t;
#define PBPROC_FC_SOF_W0__DT_AV 2, 0
@@ -397,6 +490,7 @@ typedef struct pbproc_fc_rts_cts_t pbproc_fc_rts_cts_t;
#define PBPROC_FC_RTS_CTS_W3__RESERVED2 7, 0
#define PBPROC_FC_RTS_CTS_W3__FCCS_AV 31, 8
+#if !CONFIG_MAC_PBPROC_EOC_FC
/** Sound frame control. */
struct pbproc_fc_sound_t
{
@@ -445,6 +539,71 @@ struct pbproc_fc_sound_t
/** FCCS. */
uint fccs_av:24;)
};
+#else
+/** Sound frame control. EOC */
+struct pbproc_fc_sound_t
+{
+ BITFIELDS_WORD(
+ /** Delimiter type. */
+ pbproc_fc_dt_t dt_av:3;,
+ /** Access field. */
+ bool access:1;,
+ /** Short network identifier. */
+ uint snid:4;,
+ /** Destination terminal equipment identifier. */
+ uint dtei:8;,
+ /** Frame length. */
+ uint fl_av:12;,
+ /** Link identifier. */
+ uint lid:4;)
+ BITFIELDS_WORD(
+ /** Type of compression */
+ uint sackt0:2;,
+ /** Direction identifier. */
+ uint direction:1;,
+ /** PB size, true for 136. */
+ bool pbsz:1;,
+ /** Sound ACK flag. */
+ bool saf:1;,
+ /** Sound complete flag. */
+ bool scf:1;,
+ /** Max tone map requested. */
+ uint req_tm:3;,
+ /** MPDU count. */
+ uint mpdu_cnt:2;,
+ /** sacki 0 */
+ uint sacki0:21;)
+ /** sacki 1 */
+ uint sacki1;
+ BITFIELDS_WORD(
+ uint src:8;,
+ /** FCCS. */
+ uint fccs_av:24;)
+};
+
+#define PBPROC_FC_EOC_SOUND_W0__DT_AV 2, 0
+#define PBPROC_FC_EOC_SOUND_W0__ACCESS 3, 3
+#define PBPROC_FC_EOC_SOUND_W0__SNID 7, 4
+#define PBPROC_FC_EOC_SOUND_W0__DTEI 15, 8
+#define PBPROC_FC_EOC_SOUND_W0__FL_AV 27, 16
+#define PBPROC_FC_EOC_SOUND_W0__LID 31, 28
+
+#define PBPROC_FC_EOC_SOUND_W1__SACKT0 1, 0
+#define PBPROC_FC_EOC_SOUND_W1__DIRECTION 2, 2
+#define PBPROC_FC_EOC_SOUND_W1__PBSZ 3, 3
+#define PBPROC_FC_EOC_SOUND_W1__SAF 4, 4
+#define PBPROC_FC_EOC_SOUND_W1__SCF 5, 5
+#define PBPROC_FC_EOC_SOUND_W1__REQ_TM 8, 6
+#define PBPROC_FC_EOC_SOUND_W1__MPDU_CNT 10, 9
+#define PBPROC_FC_EOC_SOUND_W1__SACKI0 31, 11
+
+#define PBPROC_FC_EOC_SOUND_W2__SACKI1 31, 0
+
+#define PBPROC_FC_EOC_SOUND_W3__SRC 7, 0
+#define PBPROC_FC_EOC_SOUND_W3__FCCS_AV 31, 8
+
+
+#endif
typedef struct pbproc_fc_sound_t pbproc_fc_sound_t;
#define PBPROC_FC_SOUND_W0__DT_AV 2, 0
@@ -471,6 +630,7 @@ typedef struct pbproc_fc_sound_t pbproc_fc_sound_t;
#define PBPROC_FC_SOUND_W3__RESERVED2 7, 0
#define PBPROC_FC_SOUND_W3__FCCS_AV 31, 8
+#if !CONFIG_MAC_PBPROC_EOC_FC
/** Reverse SOF frame control. */
struct pbproc_fc_rsof_t
{
@@ -525,6 +685,67 @@ struct pbproc_fc_rsof_t
/** FCCS. */
uint fccs_av:24;)
};
+#else
+/** Reverse SOF frame control EoC. */
+struct pbproc_fc_rsof_t
+{
+ BITFIELDS_WORD(
+ /** Delimiter type. */
+ pbproc_fc_dt_t dt_av:3;,
+ /** Access field. */
+ bool access:1;,
+ /** Short network identifier. */
+ uint snid:4;,
+ /** Destination terminal equipment identifier. */
+ uint dtei:8;,
+ /** SACK type */
+ uint sackt0:2;,
+ /** Reverse SOF frame length. */
+ uint rsof_fl_av:12;,
+ /** Number of symbols. */
+ uint num_sym:2;)
+ /** ACK part 1 */
+ uint sacki0;
+ BITFIELDS_WORD(
+ /** ACK part 2 */
+ uint sacki1:21;,
+ /** LID. */
+ uint lid:4;
+ /** Tone map index. */
+ uint tmi_av:5;,
+ /** Beacon detect flag. */
+ bool bdf:1;,
+ /** PB size, true for 136. */
+ bool pbsz:1;
+ )
+ BITFIELDS_WORD(
+ /** Number of pending PBs in all MFS. */
+ uint sppb:8;,
+ /** FCCS. */
+ uint fccs_av:24;)
+};
+
+#define PBPROC_FC_EOC_RSOF_W0__DT_AV 2, 0
+#define PBPROC_FC_EOC_RSOF_W0__ACCESS 3, 3
+#define PBPROC_FC_EOC_RSOF_W0__SNID 7, 4
+#define PBPROC_FC_EOC_RSOF_W0__DTEI 15, 8
+#define PBPROC_FC_EOC_RSOF_W0__SACKT0 17, 16
+#define PBPROC_FC_EOC_RSOF_W0__RSOF_FL_AV 29, 18
+#define PBPROC_FC_EOC_RSOF_W0__NUM_SYM 31, 30
+
+#define PBPROC_FC_EOC_RSOF_W1__SACKI0 31, 0
+
+#define PBPROC_FC_EOC_RSOF_W2__SACKI1 20, 0
+#define PBPROC_FC_EOC_RSOF_W2__LID 24, 21
+#define PBPROC_FC_EOC_RSOF_W2__TMI_AV 29, 25
+#define PBPROC_FC_EOC_RSOF_W2__BDF 30, 30
+#define PBPROC_FC_EOC_RSOF_W2__PBSZ 31, 31
+
+#define PBPROC_FC_EOC_RSOF_W3__SPPB 7, 0
+#define PBPROC_FC_EOC_RSOF_W3__FCCS_AV 31, 8
+
+#endif
+
typedef struct pbproc_fc_rsof_t pbproc_fc_rsof_t;
#define PBPROC_FC_RSOF_W0__DT_AV 2, 0
diff --git a/cesar/mac/pbproc/inc/prep_mpdu.h b/cesar/mac/pbproc/inc/prep_mpdu.h
index 87eee1deef..d5d7848922 100644
--- a/cesar/mac/pbproc/inc/prep_mpdu.h
+++ b/cesar/mac/pbproc/inc/prep_mpdu.h
@@ -103,6 +103,12 @@ struct pbproc_prep_mpdu_t
bool bypass_aes;
/** AES network encryption key. */
u32 *nek;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /** Network encryption key select, info from RX SOF */
+ u8 eks;
+ /** bidirection transmission, info from RX SOF */
+ bool bbf;
+#endif
/** Data kept for each individual MPDU. */
pbproc_prep_mpdu_single_t mpdu[PBPROC_PREP_MPDU_NB_MAX];
/** Pointer to current MPDU data, should be synchronised with
@@ -251,6 +257,16 @@ pbproc_prep_mpdu_handle_sack (pbproc_t *ctx, pbproc_fc_ack_data_t *ack_data);
void
pbproc_prep_mpdu_commit_burst (pbproc_t *ctx);
+
+#if CONFIG_MAC_PBPROC_EOC_FC
+/**
+ * Track access timeout for prep mpdu/sound.
+ * \param ctx pbproc context
+ */
+void
+pbproc_prep_mpdu_access_track (pbproc_t *ctx);
+#endif
+
/**
* Acknowledge or cancel a SOUND frame.
* \param ctx pbproc context
diff --git a/cesar/mac/pbproc/pbproc.h b/cesar/mac/pbproc/pbproc.h
index 49e62d1063..755c55e938 100644
--- a/cesar/mac/pbproc/pbproc.h
+++ b/cesar/mac/pbproc/pbproc.h
@@ -71,8 +71,13 @@ struct pbproc_rx_params_t
u8 burst_cnt;
/** Bidirectional burst flag. */
bool bbf;
+#if !CONFIG_MAC_PBPROC_EOC_FC
/** Max reverse transmission frame length. */
u8 mrtfl;
+#else
+ /** Max reverse transmission duration. */
+ uint mrdur_tck;
+#endif
/** Different CP PHY clock flag. */
bool dcppcf;
/** Request SACK retransmission. */
@@ -418,6 +423,17 @@ pbproc_mfs_remove_all (mfs_tx_t *mfs);
int
pbproc_get_interval_group (sta_t *sta, uint offset_tck, uint flp_tck);
+/**
+ * Adjust PBProc parameters according to number of carriers
+ * \param ctx PBProc context
+ * \param adjust use 2 symbols in control and extend EIFS time period
+ *
+ */
+#if CONFIG_MAC_PBPROC_EOC_FC
+void
+pbproc_parameters_adjust (pbproc_t *ctx, bool adjust);
+#endif
+
END_DECLS
#endif /* mac_pbproc_pbproc_h */
diff --git a/cesar/mac/pbproc/src/fsm.c b/cesar/mac/pbproc/src/fsm.c
index b036768935..3af9db4559 100644
--- a/cesar/mac/pbproc/src/fsm.c
+++ b/cesar/mac/pbproc/src/fsm.c
@@ -12,6 +12,8 @@
*/
#include "common/std.h"
+#include "hal/gpio/gpio.h"
+
#include "mac/pbproc/pbproc.h"
#include "mac/pbproc/inc/fsm.h"
@@ -106,8 +108,10 @@ pbproc_fsm_handle_rx_fc_event (pbproc_t *ctx, u32 rx_date, const u32 *fc_av)
PBPROC_TRACE (FSM_RX_FC, phy_date (), rx_date,
fc_av ? fc_av[0] : (u32) -1, fc_av ? fc_av[1] : (u32) -1,
fc_av ? fc_av[2] : (u32) -1, fc_av ? fc_av[3] : (u32) -1);
+ GPIO_SET (LED_PBPROC_WORKING, 1);
ctx->fsm.states[ctx->fsm.current_state].
rx_fc_cb (ctx, rx_date, (const pbproc_fc_t *) fc_av);
+ GPIO_SET (LED_PBPROC_WORKING, 0);
if (ctx->fsm.schedule_deferred)
{
ctx->fsm.schedule_deferred = false;
@@ -123,7 +127,9 @@ pbproc_fsm_handle_access_event (pbproc_t *ctx)
dbg_claim (ctx);
dbg_claim (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
PBPROC_TRACE (FSM_ACCESS, phy_date ());
+ GPIO_SET (LED_PBPROC_WORKING, 1);
ctx->fsm.states[ctx->fsm.current_state].access_cb (ctx);
+ GPIO_SET (LED_PBPROC_WORKING, 0);
if (ctx->fsm.schedule_deferred)
{
ctx->fsm.schedule_deferred = false;
@@ -139,7 +145,9 @@ pbproc_fsm_handle_access_conf_event (pbproc_t *ctx)
dbg_claim (ctx);
dbg_claim (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
PBPROC_TRACE (FSM_ACCESS_CONF, phy_date ());
+ GPIO_SET (LED_PBPROC_WORKING, 1);
ctx->fsm.states[ctx->fsm.current_state].access_conf_cb (ctx);
+ GPIO_SET (LED_PBPROC_WORKING, 0);
if (ctx->fsm.schedule_deferred)
{
ctx->fsm.schedule_deferred = false;
@@ -156,7 +164,9 @@ pbproc_fsm_handle_pbdma_event (pbproc_t *ctx, u32 status_word)
dbg_claim (ctx->fsm.current_state < PBPROC_FSM_STATE_NB);
PBPROC_TRACE (FSM_PBDMA, phy_date (), status_word);
ctx->pbdma_status = PHY_PBDMA_STATUS (status_word);
+ GPIO_SET (LED_PBPROC_WORKING, 1);
ctx->fsm.states[ctx->fsm.current_state].pbdma_cb (ctx);
+ GPIO_SET (LED_PBPROC_WORKING, 0);
if (ctx->fsm.schedule_deferred)
{
ctx->fsm.schedule_deferred = false;
diff --git a/cesar/mac/pbproc/src/fsm_handle_fc.c b/cesar/mac/pbproc/src/fsm_handle_fc.c
index ece799b878..fbb2d75c88 100644
--- a/cesar/mac/pbproc/src/fsm_handle_fc.c
+++ b/cesar/mac/pbproc/src/fsm_handle_fc.c
@@ -10,6 +10,8 @@
* \brief FSM handle FC part.
* \ingroup mac_pbproc
*/
+#include "config/av.h"
+
#include "common/std.h"
#include "pbproc.h"
@@ -117,7 +119,8 @@ pbproc_fhfc_handle_fc (pbproc_t *ctx, u32 rx_date, const pbproc_fc_t *fc_av)
if (!fc_av)
{
/* Handle HP 1.0 detection. */
- bool crc_error = pbproc_fhfc_fc10 (ctx, rx_date,
+ bool crc_error = CONFIG_AV_ONLY_MODE
+ || pbproc_fhfc_fc10 (ctx, rx_date,
phy_rx_fc10 (ctx->phy));
if (crc_error)
{
@@ -168,12 +171,15 @@ pbproc_fhfc_beacon (pbproc_t *ctx, u32 rx_date,
static bool ARCH_ILRAM
pbproc_fhfc_parse_sof (pbproc_t *ctx, const pbproc_fc_t *fc_av)
{
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_claim (fc_av->sof.clst == false);
/* TODO features. */
dbg_claim (fc_av->sof.dcppcf == false);
dbg_claim (fc_av->sof.rsr == false);
+#endif
pbproc_rx_params_t *rx_params = &ctx->recv_mpdu.rx_params;
bool fc_ok;
+#if !CONFIG_MAC_PBPROC_EOC_FC
u32 sof_w0 = fc_av->words[0];
rx_params->snid = BF_GET (PBPROC_FC_SOF_W0__SNID, sof_w0);
rx_params->dtei = BF_GET (PBPROC_FC_SOF_W0__DTEI, sof_w0);
@@ -222,6 +228,58 @@ pbproc_fhfc_parse_sof (pbproc_t *ctx, const pbproc_fc_t *fc_av)
BF_GET (PBPROC_FC_SOF_W2__MFS_CMD_DATA, sof_w2);
fc_ok = true;
}
+#else
+ u32 sof_w0 = fc_av->words[0];
+ bool direction = BF_GET (PBPROC_FC_EOC_SOF_W0__DIRECTION, sof_w0);
+ rx_params->snid = BF_GET (PBPROC_FC_EOC_SOF_W0__SNID, sof_w0);
+ rx_params->bcast = BF_GET (PBPROC_FC_EOC_SOF_W0__MCF, sof_w0);
+ u32 sof_w1 = fc_av->words[1];
+ u8 tei = ctx->config->tei;
+ rx_params->multi_net_bcast = BF_GET (PBPROC_FC_EOC_SOF_W1__MNBF, sof_w1);
+ if (direction)
+ {
+ rx_params->tei = BF_GET (PBPROC_FC_EOC_SOF_W0__DTEI, sof_w0);
+ rx_params->dtei = MAC_TEI_CCO_DEF;
+ }
+ else
+ {
+ rx_params->dtei = BF_GET (PBPROC_FC_EOC_SOF_W0__DTEI, sof_w0);
+ rx_params->tei = MAC_TEI_CCO_DEF;
+ }
+ /* frame is for us */
+ if (!BF_GET (PBPROC_FC_SOF_W0__ACCESS, sof_w0)
+ && ((rx_params->snid == ctx->alloc.snid) || rx_params->multi_net_bcast)
+ && ((rx_params->dtei && rx_params->dtei == tei)
+ || rx_params->bcast
+ || (direction && MAC_TEI_IS_EOC_CCO(tei))))
+ {
+ rx_params->sound = false;
+ rx_params->lid = BF_GET (PBPROC_FC_EOC_SOF_W0__LID, sof_w0);
+ rx_params->cfp = ctx->access.cfp;
+ rx_params->bdf = 0;
+ rx_params->hp10df = false;
+ rx_params->hp11df = false;
+ rx_params->eks = BF_GET (PBPROC_FC_EOC_SOF_W0__EKS, sof_w0);
+ rx_params->pending_seg_info = 0;
+ rx_params->ble = 0;
+ rx_params->pb_size = BF_GET (PBPROC_FC_EOC_SOF_W0__PBSZ, sof_w0)
+ ? PHY_PB_SIZE_136 : PHY_PB_SIZE_520;
+ rx_params->num_sym = BF_GET (PBPROC_FC_EOC_SOF_W0__NUM_SYM, sof_w0);
+ rx_params->tmi_av = BF_GET (PBPROC_FC_EOC_SOF_W0__TMI_AV, sof_w0);
+ rx_params->fl_tck = MAC_FL_TO_TCK (
+ BF_GET (PBPROC_FC_EOC_SOF_W1__FL_AV, sof_w1));
+ rx_params->mpdu_cnt = BF_GET (PBPROC_FC_EOC_SOF_W1__MPDU_CNT, sof_w1);
+ rx_params->burst_cnt = BF_GET (PBPROC_FC_EOC_SOF_W1__BURST_CNT, sof_w1);
+ rx_params->mrdur_tck = MAC_FL_TO_TCK (
+ BF_GET (PBPROC_FC_EOC_SOF_W1__MRDUR_FL, sof_w1));
+ rx_params->bbf = BF_GET (PBPROC_FC_EOC_SOF_W1__BBF, sof_w1);
+ rx_params->dcppcf = false;
+ rx_params->rsr = false;
+ rx_params->mfs_cmd_mme = MFS_FSM_CMD_NOP;
+ rx_params->mfs_cmd_data = MFS_FSM_CMD_NOP;
+ fc_ok = true;
+ }
+#endif
else
{
/** FC is not for us, it will be ignored. */
@@ -234,8 +292,55 @@ static bool ARCH_ILRAM
pbproc_fhfc_parse_rsof (pbproc_t *ctx, const pbproc_fc_t *fc_av)
{
bool fc_ok = false;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ pbproc_rx_params_t *rx_params = &ctx->recv_mpdu.rx_params;
+ u32 sof_w0 = fc_av->words[0];
+ rx_params->snid = BF_GET (PBPROC_FC_EOC_RSOF_W0__SNID, sof_w0);
+ if (!BF_GET (PBPROC_FC_EOC_RSOF_W0__ACCESS, sof_w0)
+ && (rx_params->snid == ctx->alloc.snid)
+ && ctx->prep_mpdu.valid
+ && ctx->prep_mpdu.bbf
+ && (fc_av->rsof.dtei == ctx->prep_mpdu.dtei))
+ {
+ rx_params->tei = BF_GET (PBPROC_FC_EOC_RSOF_W0__DTEI, sof_w0);
+ rx_params->dtei = MAC_TEI_CCO_DEF;
+ u32 sof_w2 = fc_av->words[2];
+ rx_params->bcast = false;
+ rx_params->multi_net_bcast = false;
+ rx_params->eks = ctx->prep_mpdu.eks;
+ ctx->recv_mpdu.rx_params.fl_tck = MAC_FL_TO_TCK (
+ BF_GET (PBPROC_FC_EOC_RSOF_W0__RSOF_FL_AV, sof_w0));
+ rx_params->num_sym = BF_GET (PBPROC_FC_EOC_RSOF_W0__NUM_SYM, sof_w0);
+ rx_params->mpdu_cnt = 0;
+ rx_params->bdf = BF_GET (PBPROC_FC_EOC_RSOF_W2__BDF, sof_w2);
+ rx_params->hp10df = false;
+ rx_params->hp11df = false;
+ rx_params->mfs_cmd_data = MFS_FSM_CMD_NOP;
+ rx_params->mfs_cmd_mme = MFS_FSM_CMD_NOP;
+ rx_params->sound = false;
+ rx_params->ble = 0;
+ rx_params->pb_size = BF_GET (PBPROC_FC_EOC_RSOF_W2__PBSZ, sof_w2)
+ ? PHY_PB_SIZE_136 : PHY_PB_SIZE_520;;
+ rx_params->cfp = ctx->access.cfp;
+ rx_params->tmi_av = BF_GET (PBPROC_FC_EOC_RSOF_W2__TMI_AV, sof_w2);
+ rx_params->bbf = false;
+ rx_params->lid = BF_GET (PBPROC_FC_EOC_RSOF_W2__LID, sof_w2);
+ u32 sof_w3 = fc_av->words[3];
+ u8 sppb = BF_GET (PBPROC_FC_EOC_RSOF_W3__SPPB, sof_w3);
+ rx_params->pending_seg_info = sppb >> 4;
+ if ((sppb & 0xf) != 0xf)
+ {
+ /* Support old stations. */
+ rx_params->lid = ctx->prep_mpdu.lid != MAC_LID_NONE
+ ? ctx->prep_mpdu.lid : MAC_LLID_MIN;
+ rx_params->pending_seg_info = sppb ? 1 : 0;
+ }
+ fc_ok = true;
+ }
+#else
/* For the moment, this function returns an error everytime because we do
* not handle RSOFs. So they will be processed as frames not for us. */
+#endif
return fc_ok;
}
@@ -279,8 +384,13 @@ pbproc_fhfc_rsof (pbproc_t *ctx, u32 rx_date, const pbproc_fc_t *fc_av)
* it will be a SACK or a SOF. */
ctx->stats.rx_nfu++;
phy_rx_prepare_short (ctx->phy);
+#if CONFIG_MAC_PBPROC_EOC_FC
+ u32 next_date = rx_date + ctx->times.pre_fcs_tck
+ + MAC_FL_TO_TCK (fc_av->rsof.rsof_fl_av);
+#else
u32 next_date = rx_date + ctx->times.pre_fcs_tck
+ PBPROC_FC_RSOF_FL_AV_TO_TCK (fc_av->rsof.rsof_fl_av);
+#endif
ca_access_vcs_restart_eifs (ctx->ca, next_date);
phy_rx_activate (ctx->phy, false, next_date, true);
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
@@ -349,7 +459,16 @@ pbproc_fhfc_sound (pbproc_t *ctx, u32 rx_date, const pbproc_fc_sound_t *sound)
{
if (sound->access == false
&& sound->snid == ctx->alloc.snid
+#if CONFIG_MAC_PBPROC_EOC_FC
+ && ((sound->dtei == ctx->config->tei && !sound->direction)
+ || (MAC_TEI_IS_EOC_CCO(ctx->config->tei)
+ && sound->direction
+ && ctx->prep_mpdu.valid
+ && ctx->prep_mpdu.bbf
+ && sound->dtei == ctx->prep_mpdu.dtei))
+#else
&& sound->dtei == ctx->config->tei
+#endif
&& !sound->saf
&& ((sound->src <= TONEMAP_SRC_TMI_MAX
&& sound->src >= TONEMAP_SRC_TMI_MIN)
@@ -389,7 +508,12 @@ pbproc_fhfc_bad (pbproc_t *ctx, u32 rx_date)
{
dbg_claim (ctx);
phy_rx_prepare_short (ctx->phy);
- ca_access_vcs_restart_eifs (ctx->ca, rx_date);
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ /* We call this function only to have a EoC reschedule.
+ * As scheduling is done in ca_access_compute. */
+ ca_access_vcs_restart (ctx->ca, rx_date + ctx->times.max_fl_tck);
+ else
+ ca_access_vcs_restart_eifs (ctx->ca, rx_date);
phy_rx_activate (ctx->phy, false, rx_date + ctx->times.pre_fcs_tck
+ PHY_RX_ACTIVATE_DELAY_AFTER_SHORT_TCK, true);
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
diff --git a/cesar/mac/pbproc/src/fsm_rx_beacon.c b/cesar/mac/pbproc/src/fsm_rx_beacon.c
index c9caa57e48..9fa02a5638 100644
--- a/cesar/mac/pbproc/src/fsm_rx_beacon.c
+++ b/cesar/mac/pbproc/src/fsm_rx_beacon.c
@@ -26,7 +26,11 @@ pbproc_frbe_init (pbproc_t *ctx)
CALLBACK (pbproc_frbe__rx_beacon__pbdma);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_frbe__handle (pbproc_t *ctx, u32 rx_date,
const pbproc_fc_beacon_t *beacon)
{
@@ -46,7 +50,8 @@ pbproc_frbe__handle (pbproc_t *ctx, u32 rx_date,
+ MAC_B2BIFS_TCK;
ctx->recv_mpdu.ack_date = rx_date + flp_tck;
/* Ignore frames ending after the allocation, handle pool exhaustion. */
- if ((!ctx->alloc.merge
+ if ((!CONFIG_MAC_PBPROC_EOC_FC
+ && !ctx->alloc.merge
&& less_mod2p32 (ctx->alloc.end_date + MAC_TOLERANCE_TCK,
ctx->recv_mpdu.ack_date - MAC_B2BIFS_TCK))
|| ctx->rx_pool_size < 1)
@@ -84,7 +89,11 @@ pbproc_frbe__handle (pbproc_t *ctx, u32 rx_date,
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_RX_BEACON);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_frbe__rx_beacon__pbdma (pbproc_t *ctx)
{
dbg_claim (ctx);
diff --git a/cesar/mac/pbproc/src/fsm_rx_data.c b/cesar/mac/pbproc/src/fsm_rx_data.c
index f54629f1ac..ba75a36321 100644
--- a/cesar/mac/pbproc/src/fsm_rx_data.c
+++ b/cesar/mac/pbproc/src/fsm_rx_data.c
@@ -33,7 +33,11 @@ pbproc_frda_vcs_restart (pbproc_t *ctx);
* Anticipate SACK sending for hybrid mode.
* \param ctx pbproc context
*/
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+static inline void
+#else
static void
+#endif
pbproc_frda_send_sack_anticip (pbproc_t *ctx);
/**
@@ -85,6 +89,56 @@ pbproc_frda_init (pbproc_t *ctx)
CALLBACK (pbproc_frda__rx_burst__access);
}
+#if CONFIG_MAC_COMMON_EOC_SCHED
+/**
+ * The number of active stations which change the poll behavior, under this
+ * value, all stations are polled at each new beacon period.
+ */
+#define PBPROC_STA_ACTIVE_CHANGE_POLL_ALGO 4
+#define PBPROC_EMPTY_POLL_SPC_ALGO 1
+
+static inline void
+pbproc_next_poll_update (pbproc_t *ctx)
+{
+ /* examine only unicast frames */
+ if (MAC_TEI_IS_STA (ctx->prep_mpdu.dtei))
+ {
+ sta_t *sta = mac_store_sta_get_noref (ctx->store,
+ ctx->prep_mpdu.dtei);
+ /* check last poll */
+ if (sta)
+ {
+ u32 bp_delay [] = {0, 0, 1, 1, 2, 2, 3};
+ if (!ctx->recv_mpdu.pb_nb && !ctx->prep_mpdu.burst_seg_nb)
+ {
+ if (sta->empty_poll < COUNT (bp_delay))
+ sta->empty_poll++;
+ }
+ else
+ {
+ sta->empty_poll = 0;
+ }
+ /* Poll now. */
+ sta->bp_before_poll = 0;
+ sta->sppb = ctx->recv_mpdu.rx_params.pending_seg_info;
+ if (ca_sta_active_nb (ctx->ca)
+ < PBPROC_STA_ACTIVE_CHANGE_POLL_ALGO
+ && sta->empty_poll > PBPROC_EMPTY_POLL_SPC_ALGO)
+ {
+ /* Wait one beacon period before polling. */
+ sta->bp_before_poll += 1;
+ }
+ else
+ {
+ /* Update bp_before_poll. */
+ sta->bp_before_poll += bp_delay [sta->empty_poll];
+ }
+ ca_sta_update (ctx->ca, sta);
+ }
+ }
+}
+#endif
+
void ARCH_ILRAM
pbproc_frda__handle (pbproc_t *ctx, u32 rx_date)
{
@@ -101,6 +155,9 @@ pbproc_frda__handle (pbproc_t *ctx, u32 rx_date)
&& rx_params->dtei == ctx->config->tei;
/* PB Size. */
pb_size = rx_params->pb_size;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ ctx->recv_mpdu.send_sack = true;
+#endif
/* Ignore frames ending after the allocation. */
uint fl_tck = rx_params->fl_tck;
if (!ctx->alloc.merge
@@ -174,7 +231,7 @@ pbproc_frda__handle (pbproc_t *ctx, u32 rx_date)
pb_nb = ((symb_nb - 1) * tm->bits_per_symbol + bits_per_pb)
/ bits_per_pb;
/* Stop if no PB. */
- if (!pb_nb)
+ if ((!CONFIG_MAC_PBPROC_EOC_FC || symb_nb > 0) && !pb_nb)
{
ctx->stats.rx_data_empty++;
pbproc_frda_error (ctx, rx_date, wack,
@@ -247,8 +304,16 @@ pbproc_frda__handle (pbproc_t *ctx, u32 rx_date)
/* First thing to do: unblock the hardware. */
if (rx_params->tmi_av >= PHY_MOD_ROBO_NB)
phy_set_tonemap (ctx->phy, tm->tmdma_desc_head);
- phy_rx_prepare (ctx->phy, pb_nb, tm->phy_combo_params[pb_size],
- tm->gil, symb_nb, tm->tcc_halfit);
+ if (!CONFIG_MAC_PBPROC_EOC_FC || pb_nb)
+ {
+ phy_rx_prepare (ctx->phy, pb_nb, tm->phy_combo_params[pb_size],
+ tm->gil, symb_nb, tm->tcc_halfit);
+ }
+ else
+ {
+ phy_rx_prepare_short (ctx->phy);
+ ctx->stats.rx_data_empty++;
+ }
/* Save received MPDU parameters. */
ctx->recv_mpdu.rx_params.preamble_ntb = rx_date
+ ctx->config->ntb_offset_tck;
@@ -297,8 +362,36 @@ pbproc_frda__handle (pbproc_t *ctx, u32 rx_date)
else
pb_it = pb_nb;
ctx->recv_mpdu.pb_head = pool;
- phy_pbdma_start (ctx->phy, bypass_aes, key, pb_nb, pb_it, &pool->phy_pb,
- &ctx->recv_mpdu.chandata_head->phy_pb.chandata, true);
+ if (!CONFIG_MAC_PBPROC_EOC_FC || pb_nb)
+ phy_pbdma_start (ctx->phy, bypass_aes, key, pb_nb, pb_it, &pool->phy_pb,
+ &ctx->recv_mpdu.chandata_head->phy_pb.chandata, true);
+#if CONFIG_MAC_COMMON_EOC_SCHED
+ if (MAC_TEI_IS_EOC_CCO (ctx->config->tei))
+ pbproc_next_poll_update (ctx);
+ else if (ctx->config->tei == rx_params->dtei)
+ ctx->polled = true;
+#endif
+#if CONFIG_MAC_PBPROC_EOC_FC
+ rx_params->agc_gain = phy_rx_agc_gain (ctx->phy);
+ bool near_end_of_alloc = false;
+ /* Check SOF/RSOF do not overflow allocation. */
+ if (!ctx->alloc.merge
+ && less_mod2p32 (ctx->alloc.end_date, ctx->recv_mpdu.ack_date
+ + MAC_CF_SOF_RSOF_IFS_TCK
+ + (rx_params->bbf ? rx_params->mrdur_tck
+ : (2 * ctx->times.pre_fcs_tck
+ + MAC_RIFS_DEFAULT_TCK))))
+ {
+ near_end_of_alloc = true;
+ if (rx_params->bbf)
+ ctx->stats.rx_rsof_out_of_alloc++;
+ }
+ /* Determine if a SACK must be sent. */
+ ctx->recv_mpdu.send_sack = wack
+ && (!rx_params->cfp
+ || (!rx_params->bbf && MAC_TEI_IS_EOC_STA (rx_params->dtei))
+ || near_end_of_alloc);
+#endif
/* Get AGC gain value for this MPDU. */
rx_params->agc_gain = phy_rx_agc_gain (ctx->phy);
/* Program VCS. */
@@ -312,16 +405,27 @@ pbproc_frda__handle (pbproc_t *ctx, u32 rx_date)
pbproc_fsm_change_state (ctx, sack_last_pb
? PBPROC_FSM_STATE_RX_DATA_WACK
: PBPROC_FSM_STATE_RX_DATA_WACK_LAST_PB);
+ if (CONFIG_MAC_PBPROC_EOC_FC && !pb_nb)
+ {
+ u32 status_word = 0;
+ ctx->pbdma_status = PHY_PBDMA_STATUS (status_word);
+ pbproc_frda__rx_data_wack_last_pb__pbdma(ctx); /* simulation */
+ }
ctx->stats.rx_data_wack++;
}
else
{
/* Wait end of frame. */
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_RX_DATA_WOACK);
+ if (CONFIG_MAC_PBPROC_EOC_FC && !pb_nb)
+ pbproc_frda__rx_data_woack__pbdma(ctx); /* simulation */
ctx->stats.rx_data_woack++;
}
- /* Signal received traffic. */
- GPIO_SET (LED_TRAFFIC, 1);
+ if (!CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Signal received traffic. */
+ GPIO_SET (LED_TRAFFIC, 1);
+ }
}
void ARCH_ILRAM
@@ -348,7 +452,11 @@ pbproc_frda__rx_data_wack_last_pb__pbdma (pbproc_t *ctx)
dbg_claim (ctx);
uint mpdu_cnt = ctx->recv_mpdu.rx_params.mpdu_cnt;
/* Prepare FC 1.0 in advance. */
+#if CONFIG_MAC_PBPROC_EOC_FC
+ if (ctx->recv_mpdu.send_sack && mpdu_cnt == 0)
+#else
if (mpdu_cnt == 0)
+#endif
pbproc_frda_send_sack_anticip (ctx);
/* Prepare SACKD. */
ctx->recv_mpdu.sackd.any_pb_crc_error =
@@ -391,7 +499,11 @@ pbproc_frda__rx_data_wack_last_pb__pbdma (pbproc_t *ctx)
}
/* TODO: Handle bidir. */
/* Send SACK if not a burst MPDU. */
+#if CONFIG_MAC_PBPROC_EOC_FC
+ if (ctx->recv_mpdu.send_sack && mpdu_cnt == 0)
+#else
if (mpdu_cnt == 0)
+#endif
pbproc_frda_send_sack (ctx);
/* Unchain and give received frame to upper layer. */
pbproc_frda_commit (ctx);
@@ -417,6 +529,11 @@ static void ARCH_ILRAM
pbproc_frda_commit (pbproc_t *ctx)
{
dbg_claim (ctx);
+ if (CONFIG_MAC_PBPROC_EOC_FC && !ctx->recv_mpdu.pb_nb)
+ {
+ /* Early return from empty message. */
+ return;
+ }
if (!ctx->recv_mpdu.drop)
{
pbproc_rx_desc_t *rx = ctx->recv_mpdu.rx_desc;
@@ -442,7 +559,11 @@ pbproc_frda_commit (pbproc_t *ctx)
dbg_invalid_ptr (ctx->recv_mpdu.chandata_head);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_frda__rx_burst__rx_fc (pbproc_t *ctx, u32 rx_date,
const pbproc_fc_t *fc_av)
{
@@ -451,7 +572,11 @@ pbproc_frda__rx_burst__rx_fc (pbproc_t *ctx, u32 rx_date,
pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_frda__rx_burst__access (pbproc_t *ctx)
{
dbg_claim (ctx);
@@ -469,6 +594,7 @@ pbproc_frda_sackd_init (pbproc_t *ctx)
/* Clear current SACKD if this frame is not part of the previous burst. */
bool reinit = false;
pbproc_sackd_t *sackd = &ctx->recv_mpdu.sackd;
+ /* no burst, always reset sackd fields */
if (!sackd->valid
|| sackd->tei != rx_params->tei
|| sackd->lid != rx_params->lid
@@ -492,13 +618,21 @@ pbproc_frda_sackd_init (pbproc_t *ctx)
sackd->last_mpdu_cnt = rx_params->mpdu_cnt;
/* Initialise SACKD preparation. */
sackd->any_pb_crc_error = false;
- pbproc_sacki_enc_init (&sackd->sacki_enc,
- PBPROC_FC_SACK_SACKI_BITS
- - (MAC_LID_IS_PLID (rx_params->lid) ? 4 : 0),
- reinit);
+ if (!CONFIG_MAC_PBPROC_EOC_FC)
+ pbproc_sacki_enc_init (&sackd->sacki_enc,
+ PBPROC_FC_SACK_SACKI_BITS
+ - (MAC_LID_IS_PLID (rx_params->lid) ? 4 : 0),
+ reinit);
+ else
+ pbproc_sacki_enc_init (&sackd->sacki_enc, PBPROC_FC_SACK_SACKI_BITS,
+ reinit);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+static void
+#else
static void ARCH_ILRAM
+#endif
pbproc_frda_error (pbproc_t *ctx, u32 rx_date,
bool wack, uint sacki_uniform)
{
@@ -509,6 +643,11 @@ pbproc_frda_error (pbproc_t *ctx, u32 rx_date,
/* ACK date. */
ctx->recv_mpdu.ack_date = rx_date + ctx->times.pre_fcs_tck
+ ctx->recv_mpdu.rx_params.fl_tck;
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Prevent reverse response in error state. */
+ ctx->recv_mpdu.rx_params.bbf = false;
+ }
/* With acknowledge? */
uint mpdu_cnt = ctx->recv_mpdu.rx_params.mpdu_cnt;
if (wack)
@@ -535,7 +674,11 @@ pbproc_frda_error (pbproc_t *ctx, u32 rx_date,
ctx->stats.rx_data_error++;
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+static inline void
+#else
static void ARCH_ILRAM
+#endif
pbproc_frda_send_sack_anticip (pbproc_t *ctx)
{
dbg_claim (ctx);
@@ -610,9 +753,29 @@ pbproc_frda_vcs_restart (pbproc_t *ctx)
/* Burst? */
if (ctx->recv_mpdu.rx_params.mpdu_cnt == 0)
{
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /* Check if this is a reverse transmission
+ * else do ordinary sack confirmation, only STA context could use */
+ if (ctx->recv_mpdu.rx_params.bbf && !ctx->recv_mpdu.send_sack)
+ {
+ u32 access_date = ctx->recv_mpdu.ack_date
+ + MAC_CF_SOF_RSOF_IFS_TCK;
+ ca_access_reprogram (ctx->ca, access_date,
+ ctx->recv_mpdu.rx_params.mrdur_tck,
+ ctx->recv_mpdu.rx_params.tei);
+ }
+ else
+ /* Prepare for next MPDU. */
+ /* if there is no SACK in tdma use shorter time */
+ ca_access_vcs_restart (ctx->ca, ctx->recv_mpdu.ack_date +
+ (!ctx->recv_mpdu.send_sack ?
+ MAC_CF_RSOF_SOF_IFS_TCK :
+ ctx->times.pre_fcs_tck + MAC_CIFS_TCK));
+#else
/* Prepare for next MPDU. */
ca_access_vcs_restart (ctx->ca, ctx->recv_mpdu.ack_date
+ ctx->times.pre_fcs_tck + MAC_CIFS_TCK);
+#endif
}
else
{
diff --git a/cesar/mac/pbproc/src/fsm_rx_sound.c b/cesar/mac/pbproc/src/fsm_rx_sound.c
index bcc2e22653..8b381b630f 100644
--- a/cesar/mac/pbproc/src/fsm_rx_sound.c
+++ b/cesar/mac/pbproc/src/fsm_rx_sound.c
@@ -41,6 +41,9 @@ pbproc_frso_init (pbproc_t *ctx)
* \return true if sound is completed
*/
static bool
+#if CONFIG_MAC_PBPROC_EOC_FC
+__attribute__ ((noinline))
+#endif
pbproc_frso_sound_complete (sta_t *sta, uint src, int int_group)
{
if (sta)
@@ -73,6 +76,25 @@ pbproc_frso__handle (pbproc_t *ctx, u32 rx_date,
{
dbg_claim (ctx);
dbg_claim (sound);
+#if !CONFIG_MAC_PBPROC_EOC_FC
+ uint tei = sound->stei;
+#else
+ uint tei = sound->direction ? sound->dtei : MAC_TEI_CCO_DEF;
+ if (MAC_TEI_IS_EOC_STA (ctx->config->tei))
+ ctx->polled = true;
+#if CONFIG_MAC_COMMON_EOC_SCHED
+ else /* cco */
+ {
+ sta_t *sta = mac_store_sta_get_noref (ctx->store, ctx->prep_mpdu.dtei);
+ if (sta)
+ {
+ sta->empty_poll = 0;
+ sta->bp_before_poll = 0;
+ ca_sta_update (ctx->ca, sta);
+ }
+ }
+#endif
+#endif
/* Update stats. */
ctx->stats.rx_sound++;
/* Get tonemap. */
@@ -118,7 +140,7 @@ pbproc_frso__handle (pbproc_t *ctx, u32 rx_date,
/* Unblock hardware. */
phy_rx_prepare_sound (ctx->phy, 1, tm->phy_combo_params[pb_size],
tm->gil, symb_nb);
- sta_t *sta = mac_store_sta_get_noref (ctx->store, sound->stei);
+ sta_t *sta = mac_store_sta_get_noref (ctx->store, tei);
/* Match the frame on the corresponding interval. */
int_group = pbproc_get_interval_group (sta,
rx_date + ctx->times.pre_fcs_tck
@@ -141,19 +163,26 @@ pbproc_frso__handle (pbproc_t *ctx, u32 rx_date,
ctx->recv_mpdu.rx_params.preamble_ntb = rx_date
+ ctx->config->ntb_offset_tck;
ctx->recv_mpdu.rx_params.fl_tck = fl_tck;
- ctx->recv_mpdu.rx_params.tei = sound->stei;
ctx->recv_mpdu.rx_params.lid = sound->lid;
ctx->recv_mpdu.rx_params.snid = sound->snid;
ctx->recv_mpdu.rx_params.bcast = false;
- ctx->recv_mpdu.rx_params.cfp = sound->cfs;
ctx->recv_mpdu.rx_params.multi_net_bcast = false;
ctx->recv_mpdu.rx_params.sound = true;
ctx->recv_mpdu.rx_params.eks = MAC_EKS_CLEAR;
- ctx->recv_mpdu.rx_params.pending_seg_info = sound->ppb;
ctx->recv_mpdu.rx_params.ble = 0;
ctx->recv_mpdu.rx_params.pb_size = pb_size;
ctx->recv_mpdu.rx_params.tmi_av = mod;
+#if !CONFIG_MAC_PBPROC_EOC_FC
+ ctx->recv_mpdu.rx_params.tei = sound->stei;
+ ctx->recv_mpdu.rx_params.pending_seg_info = sound->ppb;
ctx->recv_mpdu.rx_params.bdf = sound->bdf;
+ ctx->recv_mpdu.rx_params.cfp = sound->cfs;
+#else
+ ctx->recv_mpdu.rx_params.pending_seg_info = 0;
+ ctx->recv_mpdu.rx_params.bdf = true;
+ ctx->recv_mpdu.rx_params.cfp = true;
+ ctx->recv_mpdu.rx_params.tei = tei;
+#endif
ctx->recv_mpdu.rx_params.hp10df = false;
ctx->recv_mpdu.rx_params.hp11df = false;
ctx->recv_mpdu.rx_params.mfs_cmd_data = MFS_FSM_CMD_NOP;
@@ -213,6 +242,7 @@ pbproc_frso__rx_sound__pbdma (pbproc_t *ctx)
phy_tx_fc10 (ctx->phy, ctx->recv_mpdu.ack_date, 0);
/* Prepare SOUND acknowledgment. */
pbproc_fc_t fc;
+#if !CONFIG_MAC_PBPROC_EOC_FC
fc.words[0] = BF_FILL (
PBPROC_FC_SOUND_W0,
(DT_AV, PBPROC_FC_DT_SOUND),
@@ -240,6 +270,31 @@ pbproc_frso__rx_sound__pbdma (pbproc_t *ctx)
fc.words[3] = BF_FILL (
PBPROC_FC_SOUND_W3,
(RESERVED2, 0));
+#else
+ fc.words[0] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W0,
+ (DT_AV, PBPROC_FC_DT_SOUND),
+ (ACCESS, false),
+ (SNID, ctx->alloc.snid),
+ (DTEI, MAC_TEI_IS_EOC_CCO(ctx->config->tei)
+ ? ctx->recv_mpdu.rx_params.tei : ctx->config->tei),
+ (FL_AV, 0),
+ (LID, ctx->recv_mpdu.rx_params.lid));
+ fc.words[1] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W1,
+ (SACKT0, PBPROC_FC_SACKT_UNIFORM),
+ (DIRECTION, !MAC_TEI_IS_EOC_CCO(ctx->config->tei)),
+ (PBSZ, false),
+ (SAF, true),
+ (SCF, ctx->recv_mpdu.rx_params.sound_complete),
+ (REQ_TM, 0),
+ (MPDU_CNT, 0),
+ (SACKI0, PBPROC_FC_SACKI_UNIFORM_NOT_AVAILABLE));
+ fc.words[2] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W2,
+ (SACKI1, 0));
+ fc.words[3] = 0;
+#endif
/* Send it. */
phy_tx_param_short (ctx->phy,
PHY_FC_MODE (hybrid, ctx->config->fc_symbols_nb));
@@ -266,7 +321,11 @@ pbproc_frso__rx_sound__pbdma (pbproc_t *ctx)
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+static void
+#else
static void ARCH_ILRAM_PRIO (2)
+#endif
pbproc_frso_vcs_restart (pbproc_t *ctx)
{
dbg_claim (ctx);
diff --git a/cesar/mac/pbproc/src/fsm_top.c b/cesar/mac/pbproc/src/fsm_top.c
index 23b7cf54d1..9416482d83 100644
--- a/cesar/mac/pbproc/src/fsm_top.c
+++ b/cesar/mac/pbproc/src/fsm_top.c
@@ -10,6 +10,8 @@
* \brief FSM top part, handle idle and generic transitions.
* \ingroup mac_pbproc
*/
+#include "config/av.h"
+
#include "common/std.h"
#include "hal/gpio/gpio.h"
@@ -74,11 +76,13 @@ pbproc_ftop_aifs (pbproc_t *ctx)
&& lesseq_mod2p32 (ctx->detect.beacon_detect_expiration_date,
now))
ctx->detect.beacon_detected = false;
- if (ctx->detect.hp10_detected
+ if (!CONFIG_AV_ONLY_MODE
+ && ctx->detect.hp10_detected
&& lesseq_mod2p32 (ctx->detect.hp10_detect_date
+ PBPROC_HP_DETECT_DELAY_TCK, now))
ctx->detect.hp10_detected = false;
- if (ctx->detect.hp11_detected
+ if (!CONFIG_AV_ONLY_MODE
+ && ctx->detect.hp11_detected
&& lesseq_mod2p32 (ctx->detect.hp11_detect_date
+ PBPROC_HP_DETECT_DELAY_TCK, now))
ctx->detect.hp11_detected = false;
@@ -163,6 +167,9 @@ pbproc_ftop__idle__access (pbproc_t *ctx)
if (!ctx->prep_mpdu.valid)
{
PBPROC_TRACE (FTOP_TX_INVALID);
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ ca_backoff_deferred (ctx->ca,
+ ctx->access.duration_tck / MAC_SLOT_TCK);
ca_access_done (ctx->ca);
ca_access_defer (ctx->ca, ctx->access.access_date);
ctx->stats.tx_invalid++;
diff --git a/cesar/mac/pbproc/src/fsm_tx_data.c b/cesar/mac/pbproc/src/fsm_tx_data.c
index 29cfad3506..a23b78a38a 100644
--- a/cesar/mac/pbproc/src/fsm_tx_data.c
+++ b/cesar/mac/pbproc/src/fsm_tx_data.c
@@ -49,15 +49,27 @@ pbproc_ftda__handle (pbproc_t *ctx)
dbg_claim (ctx);
if (PHY_FC_MODE_IS_HYBRID (ctx->prep_mpdu.fc_mode))
phy_tx_fc10 (ctx->phy, ctx->prep_mpdu.tx_date, ctx->prep_mpdu.fc10);
- phy_pbdma_start (ctx->phy, ctx->prep_mpdu.bypass_aes, ctx->prep_mpdu.nek,
- mpdu->pb_nb_total,
- ctx->prep_mpdu.wack ? 0 : mpdu->pb_nb_total,
- &mpdu->main_head->phy_pb, NULL, false);
- if (mpdu->tmi >= PHY_MOD_ROBO_NB)
- phy_set_tonemap (ctx->phy, ctx->prep_mpdu.tonemap);
- phy_tx_param (ctx->phy, ctx->prep_mpdu.fc_mode,
- ctx->prep_mpdu.phy_combo_params, ctx->prep_mpdu.gil,
- ctx->prep_mpdu.symb_nb);
+#if CONFIG_MAC_PBPROC_EOC_FC
+ if (mpdu->pb_nb_total)
+#endif
+ {
+ phy_pbdma_start (ctx->phy, ctx->prep_mpdu.bypass_aes,
+ ctx->prep_mpdu.nek, mpdu->pb_nb_total,
+ ctx->prep_mpdu.wack ? 0 : mpdu->pb_nb_total,
+ &mpdu->main_head->phy_pb, NULL, false);
+ if (mpdu->tmi >= PHY_MOD_ROBO_NB)
+ phy_set_tonemap (ctx->phy, ctx->prep_mpdu.tonemap);
+ phy_tx_param (ctx->phy, ctx->prep_mpdu.fc_mode,
+ ctx->prep_mpdu.phy_combo_params, ctx->prep_mpdu.gil,
+ ctx->prep_mpdu.symb_nb);
+ }
+#if CONFIG_MAC_PBPROC_EOC_FC
+ else
+ {
+ phy_tx_param_short (ctx->phy, ctx->prep_mpdu.fc_mode);
+ ctx->stats.tx_data_empty++;
+ }
+#endif
bool prp = ctx->access.prp && !ctx->prep_mpdu.rts_cts;
phy_tx_frame (ctx->phy, ctx->prep_mpdu.tx_date, true, prp,
ctx->prep_mpdu.fc_av.words);
@@ -84,12 +96,24 @@ pbproc_ftda__tx_wait_access_conf__rx_fc (pbproc_t *ctx, u32 rx_date,
ctx->stats.tx_data_cancel++;
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_ftda__tx_wait_access_conf__access (pbproc_t *ctx)
{
dbg_claim (ctx);
pbproc_prep_mpdu_cancel_burst (ctx);
- pbproc_ftop__idle__access (ctx);
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Prepare next schedule, start access timer. */
+ ca_access_vcs_restart (ctx->ca, phy_date ()
+ + ctx->times.pre_fcs_tck + MAC_CIFS_TCK);
+ pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
+ }
+ else
+ pbproc_ftop__idle__access (ctx);
ctx->stats.prp_lost++;
ctx->stats.tx_data_cancel++;
}
@@ -98,11 +122,15 @@ void ARCH_ILRAM
pbproc_ftda__tx_wait_access_conf__access_conf (pbproc_t *ctx)
{
dbg_claim (ctx);
- /* Start DMA. */
- phy_tx_prepare (ctx->phy);
- /* Chain remaining PB. */
- pbproc_prep_mpdu_chain (ctx);
- uint stats_num_pbs = ctx->prep_mpdu.current->pb_nb_total;
+ uint pb_nb_total = ctx->prep_mpdu.current->pb_nb_total;
+ /* Check PB total. */
+ if (pb_nb_total || !CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Start DMA. */
+ phy_tx_prepare (ctx->phy);
+ /* Chain remaining PB. */
+ pbproc_prep_mpdu_chain (ctx);
+ }
if (ctx->prep_mpdu.mpdu_count != 0)
{
phy_access_timer_cancel (ctx->phy);
@@ -135,6 +163,7 @@ pbproc_ftda__tx_wait_access_conf__access_conf (pbproc_t *ctx)
}
else
{
+ ctx->prep_mpdu.main_mfs->stats.num_bursts++;
if (ctx->prep_mpdu.wack)
{
/* With ACK. */
@@ -157,17 +186,24 @@ pbproc_ftda__tx_wait_access_conf__access_conf (pbproc_t *ctx)
ctx->stats.tx_data_beacon++;
else
ctx->stats.tx_data_woack++;
+ if (CONFIG_MAC_PBPROC_EOC_FC && pb_nb_total == 0)
+ /* If Short SOF is sent goto tx end, but tx_end is here. */
+ pbproc_ftda__tx_wait_tx_end__pbdma(ctx);
}
- ctx->prep_mpdu.main_mfs->stats.num_bursts++;
}
- /* Update link stats. */
- ctx->prep_mpdu.main_mfs->stats.num_mpdus++;
- ctx->prep_mpdu.main_mfs->stats.num_pbs += stats_num_pbs;
- /* If there is a pending SPOC update and enough time, program it. */
- if (ctx->prep_mpdu.ifs_tck >= PHY_PREPARE_DELAY_TCK)
- pbproc_spoc_schedule_update (ctx, ctx->prep_mpdu.tx_date
- + ctx->prep_mpdu.flp_tck
- - ctx->prep_mpdu.ifs_tck);
+
+ /* in EoC it is possible to prematurely ack prep_mpdu, short msgs */
+ if (!CONFIG_MAC_PBPROC_EOC_FC || ctx->prep_mpdu.valid)
+ {
+ /* Update link stats. */
+ ctx->prep_mpdu.main_mfs->stats.num_mpdus++;
+ ctx->prep_mpdu.main_mfs->stats.num_pbs += pb_nb_total;
+ /* If there is a pending SPOC update and enough time, program it. */
+ if (ctx->prep_mpdu.ifs_tck >= PHY_PREPARE_DELAY_TCK)
+ pbproc_spoc_schedule_update (ctx, ctx->prep_mpdu.tx_date
+ + ctx->prep_mpdu.flp_tck
+ - ctx->prep_mpdu.ifs_tck);
+ }
}
static bool ARCH_ILRAM
@@ -229,6 +265,76 @@ pbproc_ftda_parse_sack (pbproc_t *ctx, const pbproc_fc_t *fc_av,
return fc_ok;
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+
+PRIVATE bool ARCH_ILRAM
+pbproc_ftda_parse_sackd (pbproc_t *ctx, const pbproc_fc_t *fc_av,
+ pbproc_fc_ack_data_t *ack_data)
+{
+ dbg_claim (ack_data);
+ bool valid_ack = false;
+ /* Place for EOC SACKD encapsulated in next frame.
+ * Direction should be as expected; for CCO frame should be from
+ * expected station. STA shouldn't consider RSOF at all. */
+ if (fc_av
+ && fc_av->generic.access == false
+ && fc_av->generic.snid == ctx->alloc.snid
+ && ctx->prep_mpdu.valid)
+ {
+ uint direction = MAC_TEI_IS_EOC_CCO (ctx->config->tei);
+ uint tei = ctx->prep_mpdu.dtei;
+ uint type = fc_av->generic.dt_av;
+ if (type == PBPROC_FC_DT_SOUND)
+ valid_ack = (direction == fc_av->sound.direction)
+ && (!direction || fc_av->sound.dtei == tei);
+ else if (type == PBPROC_FC_DT_SOF)
+ valid_ack = (direction == fc_av->sof.direction)
+ && (!direction || fc_av->sof.dtei == tei);
+ else if (type == PBPROC_FC_DT_RSOF)
+ valid_ack = direction && (fc_av->rsof.dtei == tei);
+ }
+ if (valid_ack)
+ {
+ uint sackt0 = PBPROC_FC_SACKT_NOT_RECEIVED, si[3] = {0, 0, 0}, sil = 0;
+ /* Compute bitmap and size */
+ switch(fc_av->generic.dt_av)
+ {
+ case PBPROC_FC_DT_SOF:
+ sackt0 = fc_av->sof.sackt0;
+ si[0] = fc_av->sof.sacki0;
+ si[1] = fc_av->sof.sacki1;
+ sil = PBPROC_FC_SACKI_EOC_SOF_SIZE;
+ break;
+ case PBPROC_FC_DT_RSOF:
+ sackt0 = fc_av->rsof.sackt0;
+ si[0] = fc_av->rsof.sacki0;
+ si[1] = fc_av->rsof.sacki1;
+ sil = PBPROC_FC_SACKI_EOC_RSOF_SIZE;
+ break;
+ case PBPROC_FC_DT_SOUND:
+ sackt0 = fc_av->sound.sackt0;
+ si[0] = fc_av->sound.sacki0
+ | (fc_av->sound.sacki1 << PBPROC_FC_SACKI_EOC_SOUND_LEFT);
+ si[1] = fc_av->sound.sacki1 >> (32 - PBPROC_FC_SACKI_EOC_SOUND_LEFT);
+ sil = PBPROC_FC_SACKI_EOC_SOUND_SIZE;
+ break;
+ default:
+ dbg_assert_default ();
+ }
+ pbproc_sacki_dec_init (&ack_data->sacki_dec, si[0], si[1], si[2], sil);
+ ack_data->sackt[0] = sackt0;
+ ack_data->sackt[1] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ack_data->sackt[2] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ack_data->sackt[3] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ack_data->rrtl_tck = 0;
+ ack_data->mfs_rsp = MFS_FSM_RSP_NB;
+ ack_data->rxwsz = MFS_WINDOW_SIZE_NB;
+ }
+ return valid_ack;
+}
+
+#endif
+
void ARCH_ILRAM
pbproc_ftda__tx_wait_sackd__rx_fc (pbproc_t *ctx, u32 rx_date,
const pbproc_fc_t *fc_av)
@@ -253,24 +359,66 @@ pbproc_ftda__tx_wait_sackd__rx_fc (pbproc_t *ctx, u32 rx_date,
}
else
{
- //handle_access ();
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ ca_access_vcs_restart (ctx->ca, rx_date
+ + ctx->times.pre_fcs_tck
+ + MAC_CIFS_TCK);
+ pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
+ }
+ else
+ {
+ //handle_access ();
+ }
}
ctx->stats.tx_data_wack_ack++;
}
else
{
- pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
- pbproc_prep_mpdu_cancel_burst (ctx);
- ctx->stats.tx_data_wack_noack++;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /* Not our SACK, may contain our SACKD. */
+ if (less_mod2p32 (rx_date, ctx->prep_mpdu.tx_date /* TODO chk timeval*/
+ + ctx->prep_mpdu.flp_tck
+ + MAC_FL_TO_TCK (MAC_MAX_FL_MAX_FL))
+ && pbproc_ftda_parse_sackd (ctx, fc_av, &ack_data))
+ {
+ if (!ctx->access.cfp)
+ ca_backoff_success (ctx->ca);
+ pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
+ pbproc_prep_mpdu_ack (ctx, ack_data.sackt, &ack_data.sacki_dec);
+ ctx->stats.tx_data_wack_ack++;
+ }
+ else
+#endif
+ {
+ pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
+ pbproc_prep_mpdu_cancel_burst (ctx);
+ ctx->stats.tx_data_wack_noack++;
+ }
}
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_ftda__tx_wait_sackd__access (pbproc_t *ctx)
{
dbg_claim (ctx);
+#if CONFIG_MAC_COMMON_EOC_MFS
+ pbproc_prep_mpdu_access_track (ctx);
+#endif
pbproc_prep_mpdu_cancel_burst (ctx);
- pbproc_ftop__idle__access (ctx);
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Prepare next schedule, start access timer. */
+ ca_access_vcs_restart (ctx->ca, phy_date ()
+ + ctx->times.pre_fcs_tck + MAC_CIFS_TCK);
+ pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
+ }
+ else
+ pbproc_ftop__idle__access (ctx);
ctx->stats.tx_data_wack_noack++;
}
@@ -287,7 +435,11 @@ pbproc_ftda__tx_wait_tx_end__pbdma (pbproc_t *ctx)
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_ftda__tx_burst__access_conf (pbproc_t *ctx)
{
dbg_claim (ctx);
diff --git a/cesar/mac/pbproc/src/fsm_tx_sound.c b/cesar/mac/pbproc/src/fsm_tx_sound.c
index b43fed10ca..4381f88b28 100644
--- a/cesar/mac/pbproc/src/fsm_tx_sound.c
+++ b/cesar/mac/pbproc/src/fsm_tx_sound.c
@@ -63,12 +63,20 @@ pbproc_ftso__tx_sound_wait_ack__rx_fc (pbproc_t *ctx, u32 rx_date,
&& fc_av->generic.access == false
&& fc_av->generic.snid == ctx->alloc.snid
&& fc_av->sound.saf == true
+#if !CONFIG_MAC_PBPROC_EOC_FC
&& fc_av->sound.stei == prep->dtei
&& fc_av->sound.dtei == prep->stei
+#else
+ && ((fc_av->sound.dtei == prep->dtei && fc_av->sound.direction)
+ || (fc_av->sound.dtei == prep->stei && !fc_av->sound.direction))
+#endif
&& less_mod2p32 (rx_date, prep->tx_date + prep->flp_tck
+ MAC_TOLERANCE_TCK))
{
phy_rx_prepare_short (ctx->phy);
+#if CONFIG_MAC_COMMON_EOC_MFS
+ prep->main_mfs->no_reply_count = 0;
+#endif
/* Handle acknowledgement. */
pbproc_prep_mpdu_sound_ack (ctx, fc_av->sound.scf);
/* Next. */
@@ -82,6 +90,13 @@ pbproc_ftso__tx_sound_wait_ack__rx_fc (pbproc_t *ctx, u32 rx_date,
else
{
//handle_access ();
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Prepare next schedule, start access timer. */
+ ca_access_vcs_restart (ctx->ca, rx_date
+ + ctx->times.pre_fcs_tck + MAC_CIFS_TCK);
+ pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
+ }
}
/* Update stats. */
ctx->stats.tx_sound_ack++;
@@ -99,16 +114,31 @@ pbproc_ftso__tx_sound_wait_ack__rx_fc (pbproc_t *ctx, u32 rx_date,
}
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void
+#else
void ARCH_ILRAM_PRIO (2)
+#endif
pbproc_ftso__tx_sound_wait_ack__access (pbproc_t *ctx)
{
dbg_claim (ctx);
+#if CONFIG_MAC_COMMON_EOC_MFS
+ pbproc_prep_mpdu_access_track (ctx);
+#endif
/* Cancel transmission. */
pbproc_prep_mpdu_sound_ack (ctx, false);
/* Update backoff. */
pbproc_backoff_lost (ctx);
/* Handle ACCESS. */
- pbproc_ftop__idle__access (ctx);
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* Prepare next schedule, start access timer. */
+ ca_access_vcs_restart (ctx->ca, phy_date () + ctx->times.pre_fcs_tck
+ + MAC_CIFS_TCK);
+ pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_IDLE);
+ }
+ else
+ pbproc_ftop__idle__access (ctx);
/* Update stats. */
ctx->stats.tx_sound_noack++;
}
diff --git a/cesar/mac/pbproc/src/pbproc.c b/cesar/mac/pbproc/src/pbproc.c
index a20755b749..66881b7b0c 100644
--- a/cesar/mac/pbproc/src/pbproc.c
+++ b/cesar/mac/pbproc/src/pbproc.c
@@ -156,6 +156,9 @@ pbproc_stats_init (pbproc_t *ctx)
PBPROC_STAT (cw_lost);
PBPROC_STAT (aifs);
PBPROC_STAT (rx_out_of_alloc);
+#if CONFIG_MAC_PBPROC_EOC_FC
+ PBPROC_STAT (rx_rsof_out_of_alloc);
+#endif
PBPROC_STAT (rx_pool_shortage);
PBPROC_STAT (rx_handle_fc);
PBPROC_STAT (rx_beacon);
@@ -188,6 +191,10 @@ pbproc_stats_init (pbproc_t *ctx)
PBPROC_STAT (tx_sound);
PBPROC_STAT (tx_sound_ack);
PBPROC_STAT (tx_sound_noack);
+#if CONFIG_MAC_PBPROC_EOC_FC
+ PBPROC_STAT (tx_data_empty);
+ PBPROC_STAT (tx_data_pb_total);
+#endif
#endif /* CONFIG_STATS */
}
@@ -259,6 +266,8 @@ pbproc_init (mac_config_t *config, mac_store_t *store)
/* Setup live indicator. */
GPIO_SETUP (LED_PBPROC_ALIVE, GPIO_DIRECTION_OUT);
GPIO_SET (LED_PBPROC_ALIVE, 1);
+ GPIO_SETUP (LED_PBPROC_WORKING, GPIO_DIRECTION_OUT);
+ GPIO_SET (LED_PBPROC_WORKING, 0);
/* All done! */
PBPROC_TRACE (INIT);
return ctx;
@@ -521,3 +530,17 @@ pbproc_get_interval_group (sta_t *sta, uint offset_tck, uint flp_tck)
return interval_group;
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+void
+pbproc_parameters_adjust (pbproc_t *ctx, bool adjust)
+{
+ dbg_assert (ctx);
+ /* adjust only non-hybrid time */
+ if (adjust)
+ {
+ ctx->times_array[0].max_fl_tck =
+ ctx->times_array[2].max_fl_tck = MAC_MS_TO_TCK (4);
+ }
+}
+#endif
+
diff --git a/cesar/mac/pbproc/src/prep_mpdu.c b/cesar/mac/pbproc/src/prep_mpdu.c
index 5452ae863f..3ab2470ebf 100644
--- a/cesar/mac/pbproc/src/prep_mpdu.c
+++ b/cesar/mac/pbproc/src/prep_mpdu.c
@@ -20,12 +20,13 @@
#include "inc/sacki_dec.h"
#include "inc/mfs.h"
+#include "hal/gpio/gpio.h"
#include "config/mac/pbproc.h"
#include <string.h>
/** Number of prepared PB before ACCESS_CONF. */
-#define PBPROC_PB_START_NB 4
+#define PBPROC_PB_START_NB (CONFIG_MAC_PBPROC_EOC_FC ? 16 : 4)
/**
* Commit MPDU.
@@ -52,8 +53,10 @@ pbproc_prep_mpdu_commit (pbproc_t *ctx, uint mpdu_count,
* Commit FSM changes.
* \param ctx pbproc context
*/
+#if !CONFIG_MAC_PBPROC_EOC_FC
static void
pbproc_prep_mpdu_commit_fsm (pbproc_t *ctx);
+#endif
/**
* Prepare a SOUND MPDU.
@@ -68,8 +71,10 @@ pbproc_prep_mpdu_sound (pbproc_t *ctx, mfs_tx_t *mfs, uint fl_tck);
* Prepare a SHORT MPDU for burst interruption.
* \param ctx pbproc context
*/
+#if !CONFIG_MAC_PBPROC_EOC_FC
static void
pbproc_prep_mpdu_short (pbproc_t *ctx);
+#endif
void
pbproc_prep_mpdu_init (pbproc_t *ctx)
@@ -86,6 +91,58 @@ pbproc_prep_mpdu_init (pbproc_t *ctx)
slist_init (prep->main_commit_return_);
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+/* mfs window_size calculation on tx_side
+ * WARNING: mfs size is already checked against <=0 value.
+ * return value: distance between start PB and end PB in mfs.
+ */
+static inline u16
+pbproc_get_segments_nb (mfs_tx_t *mfs)
+{
+ int distance = mfs->window_size
+ - distance_mod2p16 (mfs->next_ssn, mfs->head->header.ssn)
+ + mfs->seg_nb;
+ /* send at least one segment to other side */
+ if (distance <= 0)
+ return 1;
+ else
+ return (u16)distance;
+}
+
+/**
+ * Compute SPPB value to be sent in FC.
+ * \param ctx pbproc context
+ * \param dtei destination TEI
+ * \param current_mfs MFS being sent
+ * \param current_seg_nb PB being sent on the current MFS
+ * \return SPPB value
+ */
+static u8 ARCH_ILRAM
+pbproc_prep_mpdu_sppb (pbproc_t *ctx, u8 dtei,
+ mfs_tx_t *current_mfs, uint current_seg_nb)
+{
+ int cap;
+ u8 sppb = 0x0f;
+ if (MAC_TEI_IS_STA (dtei))
+ {
+ for (cap = 0; cap < MAC_CAP_NB; cap++)
+ {
+ mfs_tx_t *mfs = mac_store_mfs_get_sta_tx_data_locked (
+ ctx->store, MAC_LLID_MIN + cap, dtei);
+ if (mfs)
+ {
+ int seg_nb = mfs->seg_nb;
+ if (mfs == current_mfs)
+ seg_nb -= current_seg_nb;
+ if (seg_nb)
+ sppb |= 0x10 << cap;
+ }
+ }
+ }
+ return sppb;
+}
+#endif
+
/**
* Prepare a RTS_CTS frame.
* \param ctx pbproc context
@@ -128,7 +185,11 @@ pbproc_prep_rts_cts_fc (pbproc_t *ctx, mfs_tx_t *mfs, uint ack_dtei,
(RESERVED2, 0));
}
+#if CONFIG_MAC_PBPROC_EOC_ILRAM
+void /*ARCH_ILRAM: TODO ugly */
+#else
void ARCH_ILRAM_PRIO (1)
+#endif
pbproc_prep_beacon (pbproc_t *ctx, mfs_tx_t *mfs)
{
ca_access_param_t *access;
@@ -153,7 +214,12 @@ pbproc_prep_beacon (pbproc_t *ctx, mfs_tx_t *mfs)
prep->burst_mpdu_nb = 1;
prep->mpdu_count = 0;
prep->current = &prep->mpdu[0];
+#if CONFIG_MAC_PBPROC_EOC_FC
+ prep->bbf = false;
+ prep->fc_mode = PHY_FC_MODE (false, ctx->config->fc_symbols_nb);
+#else
prep->fc_mode = PHY_FC_MODE (true, ctx->config->fc_symbols_nb);
+#endif
prep->sound_reason_code = TONEMAP_SRC_NULL;
prep->bypass_aes = true;
/* Modulation. */
@@ -193,8 +259,12 @@ pbproc_prep_beacon (pbproc_t *ctx, mfs_tx_t *mfs)
+ tm->bits_per_symbol - 1) / tm->bits_per_symbol;
u32 data_tck = MAC_PAYLOAD_TCK (symb_nb, ctx->symbol_tck[tm->gil]);
prep->ifs_tck = MAC_B2BIFS_TCK;
- uint pre_fcs_tck = ctx->times_array[PBPROC_TIMES_ARRAY_INDEX
- (true, MAC_COEXISTENCE_FULL_HYBRID_MODE)].pre_fcs_tck;
+ uint pre_fcs_tck;
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ pre_fcs_tck = ctx->times.pre_fcs_tck;
+ else
+ pre_fcs_tck = ctx->times_array[PBPROC_TIMES_ARRAY_INDEX
+ (true, MAC_COEXISTENCE_FULL_HYBRID_MODE)].pre_fcs_tck;
prep->flp_tck = pre_fcs_tck + data_tck + MAC_B2BIFS_TCK;
prep->symb_nb = symb_nb;
/* Does it fit? */
@@ -263,7 +333,11 @@ pbproc_prep_beacon (pbproc_t *ctx, mfs_tx_t *mfs)
prep->valid = true;
}
+#if (CONFIG_TRACE && CONFIG_MAC_PBPROC_EOC_ILRAM)
+void
+#else
void ARCH_ILRAM
+#endif
pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
{
ca_access_param_t *access;
@@ -286,6 +360,9 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
access_duration_tck = access->duration_tck;
/* If prepared frame is valid, this is a bursts continuation. */
uint ack_dtei;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ bool rsof_fc = false, authenticated = false, mcf = false, mnbf = false;
+#endif
if (!prep->valid)
{
/* Fill easy fields. Work around Intellon behaviour: they do not
@@ -318,6 +395,26 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
{
prep->tx_date = access->access_date;
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+ rsof_fc = access->cfp && ctx->recv_mpdu.rx_params.bbf;
+ authenticated = true;
+ mcf = mfs->common.bcast;
+ mnbf = mfs->common.bcast && (mfs->common.mme || prep->unassociated);
+ /* No way to respect such a short schedule, give up. This is needed
+ * because later code will almost always send something in EoC. */
+ if (access_duration_tck < 2 * times->pre_fcs_tck
+ + MAC_RIFS_DEFAULT_TCK)
+ return;
+ /* dont create rsof while in unassoc state.
+ * avoid conflicts with station removal */
+ if (rsof_fc && ctx->config->tei == MAC_TEI_UNASSOCIATED)
+ {
+ /* set fields used in EoC for SACK + bidirectional */
+ ctx->recv_mpdu.rx_params.bbf = 0;
+ ctx->recv_mpdu.sackd.valid = false;
+ return;
+ }
+#endif
}
else
{
@@ -347,9 +444,16 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
* instead and we always send them in ROBO (see #3988). */
if (!mfs->common.mme && MAC_TEI_IS_STA (prep->dtei))
{
+#if CONFIG_MAC_PBPROC_EOC_FC
+ sta_t *sta = mac_store_sta_get_noref (ctx->store, prep->dtei);
+#else
sta_t *sta = mac_store_sta_get (ctx->store, prep->dtei);
+#endif
if (sta)
{
+#if CONFIG_MAC_PBPROC_EOC_FC
+ authenticated = sta->authenticated;
+#endif
tonemaps_t *tms = sta->tx_tonemaps;
uint default_tmi = tms->default_tmi;
if (default_tmi == TONEMAP_INDEX_INITIAL_START)
@@ -358,7 +462,7 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
sound_reason_code = TONEMAP_SRC_ERROR;
else if (default_tmi == TONEMAP_INDEX_INITIAL_SOUND_COMPLETE)
/* ROBO */;
- else
+ else if (!CONFIG_MAC_PBPROC_EOC_FC || mfs->seg_nb > 0)
{
uint offset_atu = MAC_TCK_TO_ATU (
prep->tx_date + times->pre_fcs_tck
@@ -446,12 +550,19 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
if (tm_data_max_tck < tm->one_pb_data_tck)
tm_data_max_tck = tm->one_pb_data_tck;
}
- blk_release (sta);
+ if (!CONFIG_MAC_PBPROC_EOC_FC)
+ blk_release (sta);
}
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /* No sound outside TDMA region in EoC, auth, CE run. */
+ if (!ctx->chandata_nb || !access->cfp || !authenticated)
+ sound_reason_code = TONEMAP_SRC_NULL;
+#else
/* No sound unless a CE is running. */
if (!ctx->chandata_nb)
sound_reason_code = TONEMAP_SRC_NULL;
+#endif
/* Prepare parameters. */
phy_gil_t previous_gil = prep->gil;
prep->phy_combo_params = tm->phy_combo_params[PHY_PB_SIZE_520];
@@ -479,6 +590,12 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
}
else
{
+#if CONFIG_MAC_PBPROC_EOC_FC
+ if (mfs->seg_nb > 0)
+ max_seg_nb = MIN (mfs->seg_nb, pbproc_get_segments_nb (mfs));
+ else
+ max_seg_nb = 0;
+#else
if (mfs->ca_state == CA_MFS_STATE_REMOVED)
max_seg_nb = 0;
else if (mfs->fsm_state == MFS_FSM_CMD_RE_SYNC
@@ -489,7 +606,9 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
max_seg_nb = MIN (mfs->seg_nb, (int) (mfs->window_size
- mfs->holes_seg_nb - prep->burst_seg_nb
- mfs->delta_between_ssn_min));
+#endif
}
+#if !CONFIG_MAC_PBPROC_EOC_FC
/* Early return if no segments. */
if (!max_seg_nb)
{
@@ -497,6 +616,7 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
pbproc_prep_mpdu_short (ctx);
return;
}
+#endif
bits_per_pb = tm->bits_per_pb[PHY_PB_SIZE_520];
/* Do not put more than one segment in the last symbol. Add one symbol if
* this arise. */
@@ -591,6 +711,7 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
&& symb_nb >= 2
&& tmi >= PHY_MOD_ROBO_NB
&& old_max_seg_nb > max_seg_nb + 1
+ && !CONFIG_MAC_PBPROC_EOC_FC
&& data_tck + 25 * 2000 < access_duration_tck)
{
dbg_claim (sound_reason_code == TONEMAP_SRC_NULL);
@@ -618,6 +739,7 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
prep->ifs_tck = rifs_tck;
prep->flp_tck = times->pre_fcs_tck + data_tck + rifs_tck;
prep->symb_nb = symb_nb;
+#if !CONFIG_MAC_PBPROC_EOC_FC
/* Early return if no symbol. */
if (max_seg_nb == 0)
{
@@ -625,6 +747,13 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
pbproc_prep_mpdu_short (ctx);
return;
}
+#else
+ /* Early return if no symbol only in CSMA region or bcast mfs,
+ * else wait for RSOF */
+ if (max_seg_nb == 0 && !access->cfp)
+ return;
+#endif
+#if !CONFIG_MAC_PBPROC_EOC_FC
/* Prepare RTS FC. */
if (prep->rts_cts)
{
@@ -634,8 +763,10 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
/* Invalid FC 1.0, HP 1.0 stations will defer (20 symbols and ROBO). */
prep->rts_fc10 = 0x200000;
}
+#endif
/* Stop here for SOUND. */
- if (sound_reason_code != TONEMAP_SRC_NULL)
+ if (sound_reason_code != TONEMAP_SRC_NULL
+ && (!CONFIG_MAC_PBPROC_EOC_FC || symb_nb))
{
pbproc_prep_mpdu_sound (ctx, mfs, data_tck + rifs_tck);
return;
@@ -646,7 +777,8 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
{
/* No encryption. */
}
- else if (mfs->common.bcast)
+ else if (mfs->common.bcast
+ && (!CONFIG_MAC_PBPROC_EOC_FC || !mfs->common.mme))
{
if (ctx->config->authenticated)
{
@@ -660,7 +792,11 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
}
else if (MAC_TEI_IS_STA (prep->dtei))
{
+#if CONFIG_MAC_PBPROC_EOC_FC
+ sta_t *sta = mac_store_sta_get_noref (ctx->store, prep->dtei);
+#else
sta_t *sta = mac_store_sta_get (ctx->store, prep->dtei);
+#endif
if (sta)
{
if (sta->authenticated)
@@ -677,14 +813,35 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
prep->nek = nek->nek_enc;
}
}
- blk_release (sta);
+ if (!CONFIG_MAC_PBPROC_EOC_FC)
+ blk_release (sta);
}
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+ /* for rsof keep received key type */
+ if (rsof_fc)
+ {
+ eks = ctx->recv_mpdu.rx_params.eks;
+ if (eks != MAC_EKS_CLEAR)
+ {
+ mac_nek_t *nek = ctx->config->nek_mgr.use[0];
+ dbg_claim (nek);
+ if (nek->eks != eks)
+ nek = ctx->config->nek_mgr.use[1];
+ dbg_claim (nek);
+ dbg_claim (nek->in_use);
+ dbg_assert (nek->eks == eks);
+ prep->nek = nek->nek_enc;
+ }
+ }
+ prep->eks = eks; /* Easy life */
+#endif
prep->bypass_aes = eks == MAC_EKS_CLEAR;
// TODO: dbg_assert (mfs->common.mme || !prep->bypass_aes);
/* Data FC. */
prep->main_mfs_cmd = mfs->fsm_state;
prep->main_mfs_rsp = MFS_FSM_RSP_NB;
+#if !CONFIG_MAC_PBPROC_EOC_FC
if (1 /* TODO */)
{
mfs_fsm_cmd_t mfs_cmd_mgmt, mfs_cmd_data;
@@ -738,6 +895,109 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
(MFS_RSP_DATA, MFS_FSM_RSP_ACK), /* TODO */
(BM_SACKI, 0xf)); /* TODO */
}
+#else
+ uint sackt0=PBPROC_FC_SACKT_UNIFORM, sacki0, sacki1=0;
+ if (ctx->recv_mpdu.sackd.valid)
+ {
+ sackt0 = ctx->recv_mpdu.sackd.sackt[0];
+ sacki0 = ctx->recv_mpdu.sackd.sacki_enc.si[0];
+ sacki1 = ctx->recv_mpdu.sackd.sacki_enc.si[1]
+ & BITS_ONES (rsof_fc ? PBPROC_FC_SACKI_EOC_RSOF_LEFT :
+ PBPROC_FC_SACKI_EOC_SOF_LEFT);
+ }
+ else
+ /* Could be also ALL_ERROR */
+ sacki0 = PBPROC_FC_SACKI_UNIFORM_NOT_AVAILABLE;
+ /* decision what to choose SOF or RSOF depend on position,
+ * SOF = cco or BCAST/MCAST, RSOF = sta only
+ * prepare RSOF/SOF by EOC specification */
+ if (rsof_fc)
+ {
+ prep->bbf = false;
+ dbg_assert(MAC_TEI_IS_EOC_STA(ctx->config->tei));
+ prep->fc_av.words[0] = BF_FILL (
+ PBPROC_FC_EOC_RSOF_W0,
+ (DT_AV, PBPROC_FC_DT_RSOF),
+ (ACCESS, false),
+ (SNID, ctx->alloc.snid),
+ (DTEI, prep->stei),
+ (RSOF_FL_AV, MAC_TCK_TO_FL (data_tck + rifs_tck)),
+ (NUM_SYM, symb_nb < 3 ? symb_nb : 3),
+ (SACKT0, sackt0));
+ prep->fc_av.words[1] = BF_FILL (
+ PBPROC_FC_EOC_RSOF_W1,
+ (SACKI0, sacki0));
+ prep->fc_av.words[2] = BF_FILL (
+ PBPROC_FC_EOC_RSOF_W2,
+ (SACKI1, sacki1),
+ (LID, prep->lid & 0xf),
+ (TMI_AV, tmi),
+ (BDF, true), /*TODO: status to be added */
+ (PBSZ, false));
+ prep->fc_av.words[3] = BF_FILL (
+ PBPROC_FC_EOC_RSOF_W3,
+ (SPPB, pbproc_prep_mpdu_sppb (ctx, prep->dtei, mfs, max_seg_nb)));
+ }
+ else
+ {
+ bool direction = !MAC_TEI_IS_EOC_CCO (ctx->config->tei);
+ prep->bbf = !mfs->common.bcast
+ && access->cfp
+ && !direction;
+ uint mrdur_tck = 0;
+ if (prep->bbf)
+ {
+ /* TODO: remove MAC_CF_SOF_RSOF_IFS_TCK, and therefore comparison
+ * with 0. */
+ mrdur_tck = MIN (2 * times->pre_fcs_tck + times->max_fl_tck
+ + MAC_TOLERANCE_TCK + MAC_TCK_PER_FL - 1,
+ (uint) MAX (0, (int) (access_duration_tck
+ - prep->flp_tck
+ - MAC_CF_SOF_RSOF_IFS_TCK)));
+ /* Include margin for reception date jitter, make sure slave will
+ * not send an out_of_alloc frame. */
+ if (mrdur_tck > MAC_TOLERANCE_TCK)
+ mrdur_tck -= MAC_TOLERANCE_TCK;
+ /* Cancel ridiculous durations. */
+ if (mrdur_tck < 2 * times->pre_fcs_tck + MAC_RIFS_DEFAULT_TCK)
+ {
+ prep->bbf = false;
+ mrdur_tck = 0;
+ }
+ }
+ prep->fc_av.words[0] = BF_FILL (
+ PBPROC_FC_EOC_SOF_W0,
+ (DT_AV, PBPROC_FC_DT_SOF),
+ (ACCESS, false),
+ (SNID, ctx->alloc.snid),
+ (DTEI, direction ? prep->stei : ack_dtei),
+ (LID, prep->lid & 0xF),
+ (EKS, eks),
+ (DIRECTION, direction),
+ (PBSZ, false),
+ (NUM_SYM, symb_nb < 3 ? symb_nb : 3),
+ (TMI_AV, tmi),
+ (MCF, mcf));
+ prep->fc_av.words[1] = BF_FILL (
+ PBPROC_FC_EOC_SOF_W1,
+ (FL_AV, MAC_TCK_TO_FL (data_tck + rifs_tck)),
+ (MPDU_CNT, 0),
+ (BURST_CNT, 0),
+ (MRDUR_FL, mrdur_tck / MAC_TCK_PER_FL),
+ (MNBF, mnbf),
+ (BBF, prep->bbf),
+ (SACKT0, sackt0));
+ prep->fc_av.words[2] = BF_FILL (
+ PBPROC_FC_EOC_SOF_W2,
+ (SACKI0, sacki0));
+ prep->fc_av.words[3] = BF_FILL (
+ PBPROC_FC_EOC_SOF_W3,
+ (SACKI1, sacki1));
+ }
+ /* Reset dangerous fields */
+ ctx->recv_mpdu.rx_params.bbf = 0;
+ ctx->recv_mpdu.sackd.valid = false;
+#endif
/* Invalid FC 1.0, HP 1.0 stations will defer (20 symbols and ROBO). */
prep->fc10 = 0x200000;
/* Prepare PB. */
@@ -748,7 +1008,7 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
seg_nb_reserved = max_seg_nb - seg_nb;
/* Get head and tail. */
pb_t *seg;
- seg = mfs->head;
+ seg = (!CONFIG_MAC_PBPROC_EOC_FC || seg_nb) ? mfs->head : 0;
mpdu->main_head = seg;
for (i = 1; i < seg_nb; i++, seg = seg->next)
{
@@ -756,18 +1016,24 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
}
mpdu->main_tail = seg;
/* Set Oldest Pending Segment Flag. */
- if (!prep->valid)
+ if (!prep->valid
+ && (!CONFIG_MAC_PBPROC_EOC_FC || mpdu->main_head))
mpdu->main_head->header.opsf = true;
/* Change MFS. */
mfs->seg_nb -= max_seg_nb;
- slist_slice (mfs->, seg, bare);
+ if (!CONFIG_MAC_PBPROC_EOC_FC || max_seg_nb)
+ slist_slice (mfs->, seg, bare);
mpdu->main_seg_nb = seg_nb;
prep->burst_seg_nb += seg_nb;
prep->main_seg_nb_reserved = seg_nb_reserved;
/* Prepare PB chain, simple one. */
mpdu->pb_nb_total = max_seg_nb + seg_nb_pending;
+#if CONFIG_MAC_PBPROC_EOC_FC
+ ctx->stats.tx_data_pb_total += mpdu->pb_nb_total;
+#endif
/* Loop over the last PB, PBDMA null PB is not working. */
- mpdu->main_tail->next = mpdu->main_tail;
+ if (!CONFIG_MAC_PBPROC_EOC_FC || mpdu->main_tail)
+ mpdu->main_tail->next = mpdu->main_tail;
/* Ok, ready to go! */
if (!prep->valid)
{
@@ -775,6 +1041,8 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
blk_addref (mfs);
prep->valid = true;
}
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ GPIO_SET (LED_TRAFFIC, (seg_nb) ? 1 : 0);
}
static void __attribute__ ((noinline))
@@ -809,9 +1077,22 @@ pbproc_prep_mpdu_chain (pbproc_t *ctx)
pbproc_prep_mpdu_single_t *mpdu = prep->current;
dbg_claim (prep->valid);
dbg_claim_ptr (prep->main_mfs);
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_claim_ptr (mpdu->main_head);
dbg_claim_ptr (mpdu->main_tail);
dbg_claim (mpdu->main_seg_nb);
+#else
+ if (mpdu->main_seg_nb)
+ {
+ dbg_claim_ptr (mpdu->main_head);
+ dbg_claim_ptr (mpdu->main_tail);
+ }
+ else
+ {
+ dbg_claim (!mpdu->main_head);
+ dbg_claim (!mpdu->main_tail);
+ }
+#endif
/* Already chained? */
if (prep->main_seg_nb_reserved != 0)
{
@@ -885,9 +1166,22 @@ pbproc_prep_mpdu_cancel (pbproc_t *ctx, uint mpdu_count)
pbproc_prep_mpdu_single_t *mpdu = &prep->mpdu[mpdu_count];
dbg_claim (prep->valid);
dbg_claim_ptr (prep->main_mfs);
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_claim_ptr (mpdu->main_head);
dbg_claim_ptr (mpdu->main_tail);
- dbg_claim (mpdu->main_seg_nb);
+ dbg_claim (mpdu->main_seg_nb); /* possible on EoC */
+#else
+ if (mpdu->main_seg_nb)
+ {
+ dbg_claim_ptr (mpdu->main_head);
+ dbg_claim_ptr (mpdu->main_tail);
+ }
+ else
+ {
+ dbg_claim (!mpdu->main_head);
+ dbg_claim (!mpdu->main_tail);
+ }
+#endif
/* Commit. */
pbproc_prep_mpdu_commit (ctx, mpdu_count, NULL, NULL,
mpdu->main_head, mpdu->main_tail,
@@ -919,11 +1213,26 @@ pbproc_prep_mpdu_ack_all (pbproc_t *ctx, uint mpdu_count)
pbproc_prep_mpdu_single_t *mpdu = &prep->mpdu[mpdu_count];
dbg_claim (prep->valid);
dbg_claim_ptr (prep->main_mfs);
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_claim_ptr (mpdu->main_head);
dbg_claim_ptr (mpdu->main_tail);
dbg_claim (mpdu->main_seg_nb);
dbg_claim (prep->main_seg_nb_reserved == 0);
dbg_claim (mpdu->pb_nb_total >= mpdu->main_seg_nb);
+#else
+ if (mpdu->main_seg_nb)
+ {
+ dbg_claim_ptr (mpdu->main_head);
+ dbg_claim_ptr (mpdu->main_tail);
+ }
+ else
+ {
+ dbg_claim (!mpdu->main_head);
+ dbg_claim (!mpdu->main_tail);
+ }
+ dbg_claim (prep->main_seg_nb_reserved == 0);
+ dbg_claim (mpdu->pb_nb_total >= mpdu->main_seg_nb);
+#endif
/* Commit. */
pbproc_prep_mpdu_commit (ctx, mpdu_count,
mpdu->main_head, mpdu->main_tail,
@@ -942,9 +1251,22 @@ pbproc_prep_mpdu_ack_bitmap (pbproc_t *ctx, uint mpdu_count,
pbproc_prep_mpdu_single_t *mpdu = &prep->mpdu[mpdu_count];
dbg_claim (prep->valid);
dbg_claim_ptr (prep->main_mfs);
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_claim_ptr (mpdu->main_head);
dbg_claim_ptr (mpdu->main_tail);
dbg_claim (mpdu->main_seg_nb);
+#else
+ if (mpdu->main_seg_nb)
+ {
+ dbg_claim_ptr (mpdu->main_head);
+ dbg_claim_ptr (mpdu->main_tail);
+ }
+ else
+ {
+ dbg_claim (!mpdu->main_head);
+ dbg_claim (!mpdu->main_tail);
+ }
+#endif
dbg_claim (prep->main_seg_nb_reserved == 0);
dbg_claim (mpdu->pb_nb_total >= mpdu->main_seg_nb);
/* Read bitmap and collect acknowledged PB. */
@@ -1069,11 +1391,26 @@ pbproc_prep_mpdu_ack_encoded (pbproc_t *ctx, uint mpdu_count,
pbproc_prep_mpdu_single_t *mpdu = &prep->mpdu[mpdu_count];
dbg_claim (prep->valid);
dbg_claim_ptr (prep->main_mfs);
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_claim_ptr (mpdu->main_head);
dbg_claim_ptr (mpdu->main_tail);
dbg_claim (mpdu->main_seg_nb);
dbg_claim (prep->main_seg_nb_reserved == 0);
dbg_claim (mpdu->pb_nb_total >= mpdu->main_seg_nb);
+#else
+ if (mpdu->main_seg_nb)
+ {
+ dbg_claim_ptr (mpdu->main_head);
+ dbg_claim_ptr (mpdu->main_tail);
+ }
+ else
+ {
+ dbg_claim (!mpdu->main_head);
+ dbg_claim (!mpdu->main_tail);
+ }
+ dbg_claim (prep->main_seg_nb_reserved == 0);
+ dbg_claim (mpdu->pb_nb_total >= mpdu->main_seg_nb);
+#endif
/* Uncompress. */
pbproc_prep_mpdu_ack_encoded_t enc =
{
@@ -1170,6 +1507,9 @@ pbproc_prep_mpdu_ack (pbproc_t *ctx, const u8 sackt[],
dbg_claim (sacki_dec);
pbproc_prep_mpdu_t *prep = &ctx->prep_mpdu;
dbg_claim (prep->valid);
+#if CONFIG_MAC_COMMON_EOC_MFS
+ prep->main_mfs->no_reply_count = 0;
+#endif
/* Handle SACKD for each MPDU. */
for (mpdu_count = prep->burst_mpdu_nb - 1; mpdu_count >= 0; mpdu_count--)
{
@@ -1316,6 +1656,29 @@ pbproc_prep_mpdu_commit_fsm (pbproc_t *ctx)
}
}
+#if CONFIG_MAC_PBPROC_EOC_FC
+
+/** Maximum number of transmissions toward STA which does not reply*/
+#define PBPROC_TX_ATTEMPTS_NB 5
+
+void
+pbproc_prep_mpdu_access_track (pbproc_t *ctx)
+{
+ dbg_claim (ctx);
+ pbproc_prep_mpdu_t * mpdu = &ctx->prep_mpdu;
+ if (mpdu->valid && !mpdu->main_mfs->common.bcast)
+ {
+ mfs_tx_t * mfs = mpdu->main_mfs;
+ if (++mfs->no_reply_count > PBPROC_TX_ATTEMPTS_NB)
+ {
+ sta_t *sta = mac_store_sta_get_noref (ctx->store, mfs->common.tei);
+ if (sta)
+ sta->poll_off |= 1;
+ }
+ }
+}
+#endif
+
void ARCH_ILRAM
pbproc_prep_mpdu_commit_burst (pbproc_t *ctx)
{
@@ -1401,8 +1764,10 @@ pbproc_prep_mpdu_commit_burst (pbproc_t *ctx)
u16 min_tx_ssn = mfs->head ? mfs->head->header.ssn : mfs->next_ssn;
mfs->delta_between_ssn_min += min_tx_ssn - prep->min_rx_ssn;
}
+#if !CONFIG_MAC_PBPROC_EOC_FC
/* Commit FSM change. */
pbproc_prep_mpdu_commit_fsm (ctx);
+#endif
/* Inform CA. */
ca_access_done (ctx->ca);
/* No longer valid. */
@@ -1413,6 +1778,7 @@ pbproc_prep_mpdu_commit_burst (pbproc_t *ctx)
prep->valid = false;
}
+#if !CONFIG_MAC_PBPROC_EOC_FC
static void
pbproc_prep_mpdu_short (pbproc_t *ctx)
{
@@ -1470,6 +1836,7 @@ pbproc_prep_mpdu_short (pbproc_t *ctx)
/* Invalid FC 1.0, HP 1.0 stations will defer (20 symbols and ROBO). */
prep->fc10 = 0x200000;
}
+#endif
static void
pbproc_prep_mpdu_sound (pbproc_t *ctx, mfs_tx_t *mfs, uint fl_tck)
@@ -1482,6 +1849,7 @@ pbproc_prep_mpdu_sound (pbproc_t *ctx, mfs_tx_t *mfs, uint fl_tck)
/* No encryption. */
prep->bypass_aes = true;
/* SOUND FC. */
+#if !CONFIG_MAC_PBPROC_EOC_FC
prep->fc_av.words[0] = BF_FILL (
PBPROC_FC_SOUND_W0,
(DT_AV, PBPROC_FC_DT_SOUND),
@@ -1509,12 +1877,55 @@ pbproc_prep_mpdu_sound (pbproc_t *ctx, mfs_tx_t *mfs, uint fl_tck)
prep->fc_av.words[3] = BF_FILL (
PBPROC_FC_SOUND_W3,
(RESERVED2, 0));
+#else
+ uint sackt0 = PBPROC_FC_SACKT_UNIFORM;
+ uint sacki0 = PBPROC_FC_SACKI_UNIFORM_NOT_AVAILABLE, sacki1 = 0;
+ /* Inject sacki data */
+ if (ctx->recv_mpdu.sackd.valid)
+ {
+ sackt0 = ctx->recv_mpdu.sackd.sackt[0];
+ sacki0 = ctx->recv_mpdu.sackd.sacki_enc.si[0]
+ & BITS_ONES (PBPROC_FC_SACKI_EOC_SOUND_LEFT);
+ sacki1 = (ctx->recv_mpdu.sackd.sacki_enc.si[0] >> PBPROC_FC_SACKI_EOC_SOUND_LEFT)
+ | (ctx->recv_mpdu.sackd.sacki_enc.si[1] << (32 - PBPROC_FC_SACKI_EOC_SOUND_LEFT));
+ }
+ prep->fc_av.words[0] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W0,
+ (DT_AV, PBPROC_FC_DT_SOUND),
+ (ACCESS, false),
+ (SNID, ctx->alloc.snid),
+ (DTEI, (MAC_TEI_IS_EOC_STA(ctx->config->tei))
+ ? prep->stei : prep->dtei),
+ (FL_AV, MAC_TCK_TO_FL (fl_tck)),
+ (LID, prep->lid));
+ prep->fc_av.words[1] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W1,
+ (SACKT0, sackt0),
+ (DIRECTION, MAC_TEI_IS_EOC_STA(ctx->config->tei)),
+ (PBSZ, false), /* TODO */
+ (SAF, false),
+ (SCF, false),
+ (REQ_TM, TONEMAP_MAX),
+ (MPDU_CNT, 0), /* TODO */
+ (SACKI0, sacki0));
+ prep->fc_av.words[2] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W2,
+ (SACKI1, sacki1));
+ prep->fc_av.words[3] = BF_FILL (
+ PBPROC_FC_EOC_SOUND_W3,
+ (SRC, prep->sound_reason_code));
+#endif
/* Invalid FC 1.0, HP 1.0 stations will defer (20 symbols and ROBO). */
prep->fc10 = 0x200000;
/* Ok, ready to go! */
prep->main_mfs = mfs;
blk_addref (mfs);
prep->valid = true;
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ {
+ /* reset sackd */
+ ctx->recv_mpdu.sackd.valid = false;
+ }
}
void
diff --git a/cesar/mac/pbproc/src/trace.c b/cesar/mac/pbproc/src/trace.c
index 21a1e5edb4..d15bc62682 100644
--- a/cesar/mac/pbproc/src/trace.c
+++ b/cesar/mac/pbproc/src/trace.c
@@ -26,11 +26,15 @@ static int
pbproc_trace_format_fc (char *text, uint text_size, const int *data,
uint size)
{
+#if !CONFIG_MAC_PBPROC_EOC_FC
static const char *mfs_cmd_str[] = { "INIT", "IN_SYNC", "RE_SYNC",
"RELEASE", "NOP", "RES=5", "RES=6", "RES=7" };
+ char mrtfl[sizeof ("bbf mrtfl=0xn ")];
+#else
+ char mrdur_fl[sizeof ("bbf mrdur_fl=0xnnn ")];
+#endif
static const char *mfs_rsp_str[] = { "ACK", "NACK", "FAIL", "HOLD" };
static const char *sackt[] = { "m", "mc", "nr", "u" };
- char mrtfl[sizeof ("bbf mrtfl=0xn ")];
char mpdu_cnt[sizeof ("mpdu_cnt=n ")];
char burst_cnt[sizeof ("burst_cnt=n ")];
dbg_assert (size == 4);
@@ -54,13 +58,38 @@ pbproc_trace_format_fc (char *text, uint text_size, const int *data,
| fc->beacon.bto3_msb8 << 8);
break;
case PBPROC_FC_DT_SOF:
+#if !CONFIG_MAC_PBPROC_EOC_FC
dbg_check (snprintf (mrtfl, sizeof (mrtfl), "bbf mrtfl=0x%x ",
fc->sof.mrtfl) < (int) sizeof (mrtfl));
+#else
+ dbg_check (snprintf (mrdur_fl, sizeof (mrdur_fl),
+ "bbf mrdur_fl=0x%x ",
+ fc->sof.mrdur_fl) < (int) sizeof (mrdur_fl));
+#endif
dbg_check (snprintf (mpdu_cnt, sizeof (mpdu_cnt), "mpdu_cnt=%d ",
fc->sof.mpdu_cnt) < (int) sizeof (mpdu_cnt));
dbg_check (snprintf (burst_cnt, sizeof (burst_cnt),
"burst_cnt=%d ", fc->sof.burst_cnt)
< (int) sizeof (burst_cnt));
+#if CONFIG_MAC_PBPROC_EOC_FC
+ r = snprintf (text, text_size,
+ "SOF snid=%s%d dir=%s dtei=0x%02x lid=0x%02x"
+ " %s%seks=%d"
+ " %snum_sym=%d tmi=%d fl_av=%d "
+ "%s%s%s"
+ "sackt0=0x%x sacki0=0x%x, sacki1=0x%x",
+ FC_ACCESS_SNID (fc),
+ fc->sof.direction ? "STA->CCO" : "CCO->STA",
+ fc->sof.dtei, fc->sof.lid,
+ fc->sof.mcf ? "mcf " : "",
+ fc->sof.mnbf ? "mnbf " : "", fc->sof.eks,
+ fc->sof.pbsz ? "pb136 " : "", fc->sof.num_sym,
+ fc->sof.tmi_av, fc->sof.fl_av,
+ fc->sof.mpdu_cnt ? mpdu_cnt : "",
+ fc->sof.burst_cnt ? burst_cnt : "",
+ fc->sof.bbf ? mrdur_fl : "",
+ fc->sof.sackt0, fc->sof.sacki0, fc->sof.sacki1);
+#else
r = snprintf (text, text_size,
"SOF snid=%s%d stei=0x%02x dtei=0x%02x lid=0x%02x"
" %s%s%s%s%s%seks=%d ppb=0x%02x ble=0x%02x"
@@ -88,6 +117,7 @@ pbproc_trace_format_fc (char *text, uint text_size, const int *data,
mfs_rsp_str[fc->sof.mfs_rsp_mgmt],
mfs_rsp_str[fc->sof.mfs_rsp_data],
fc->sof.bm_sacki);
+#endif
break;
case PBPROC_FC_DT_SACK:
r = snprintf (text, text_size,
@@ -127,6 +157,25 @@ pbproc_trace_format_fc (char *text, uint text_size, const int *data,
dbg_check (snprintf (mpdu_cnt, sizeof (mpdu_cnt), "mpdu_cnt=%d ",
fc->sound.mpdu_cnt)
< (int) sizeof (mpdu_cnt));
+#if CONFIG_MAC_PBPROC_EOC_FC
+ r = snprintf (text, text_size,
+ "SOUND snid=%s%d dir=%s dtei=0x%02x lid=0x%02x"
+ " %s%s%sreq_tm=%d fl_av=%d %s"
+ "src=0x%02x"
+ " sackt0=0x%x sacki0=0x%x, sacki1=0x%x",
+ FC_ACCESS_SNID (fc),
+ fc->sof.direction ? "STA->CCO" : "CCO->STA",
+ fc->sound.dtei,
+ fc->sound.lid,
+ fc->sound.pbsz ? "pb136 " : "",
+ fc->sound.saf ? "saf " : "",
+ fc->sound.scf ? "scf " : "",
+ fc->sound.req_tm, fc->sound.fl_av,
+ fc->sound.mpdu_cnt ? mpdu_cnt : "",
+ fc->sound.src,
+ fc->sound.sackt0, fc->sound.sacki0,
+ fc->sound.sacki1);
+#else
r = snprintf (text, text_size,
"SOUND snid=%s%d stei=0x%02x dtei=0x%02x lid=0x%02x"
" %s%s%s%s%sreq_tm=%d fl_av=%d %sppb=0x%02x"
@@ -141,8 +190,23 @@ pbproc_trace_format_fc (char *text, uint text_size, const int *data,
fc->sound.req_tm, fc->sound.fl_av,
fc->sound.mpdu_cnt ? mpdu_cnt : "", fc->sound.ppb,
fc->sound.src);
+#endif
break;
case PBPROC_FC_DT_RSOF:
+#if CONFIG_MAC_PBPROC_EOC_FC
+ r = snprintf (text, text_size,
+ "RSOF snid=%s%d dtei=0x%02x lid=0x%02x"
+ " %s%ssppb=0x%x"
+ " fl_av=%d tmi=%d num_sym=%d"
+ " sackt0=0x%x sacki0=0x%x sacki1=0x%x",
+ FC_ACCESS_SNID (fc), fc->rsof.dtei,
+ fc->rsof.lid,
+ fc->rsof.bdf ? "bdf " : "",
+ fc->rsof.pbsz ? "pb136 " : "", fc->rsof.sppb,
+ fc->rsof.rsof_fl_av, fc->rsof.tmi_av,
+ fc->rsof.num_sym,
+ fc->rsof.sackt0, fc->rsof.sacki0, fc->rsof.sacki1);
+#else
r = snprintf (text, text_size,
"RSOF snid=%s%d dtei=0x%02x"
" %s%s%s%smfs=m%s,%s,%s,m%s sackt=%s,%s,%s,%s"
@@ -165,6 +229,7 @@ pbproc_trace_format_fc (char *text, uint text_size, const int *data,
: fc->rsof.rsof_fl_av * 2 - 0x200, fc->rsof.tmi_av,
fc->rsof.pbsz ? "pb136 " : "",
fc->rsof.num_sym);
+#endif
break;
default:
r = snprintf (text, text_size, "UNKNOWN dt=%d snid=%s%d",
diff --git a/cesar/mac/pbproc/stub/Module b/cesar/mac/pbproc/stub/Module
new file mode 100644
index 0000000000..6faf57c78a
--- /dev/null
+++ b/cesar/mac/pbproc/stub/Module
@@ -0,0 +1 @@
+SOURCES := pbproc_stub.c
diff --git a/cesar/mac/pbproc/stub/src/pbproc_stub.c b/cesar/mac/pbproc/stub/src/pbproc_stub.c
new file mode 100644
index 0000000000..22f77358ec
--- /dev/null
+++ b/cesar/mac/pbproc/stub/src/pbproc_stub.c
@@ -0,0 +1,26 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cesar/mac/pbproc/stub/src/pbproc_stub.c
+ * \brief PBproc stubs.
+ * \ingroup mac_pbproc
+ */
+#include "common/std.h"
+#include "mac/pbproc/pbproc.h"
+
+void
+pbproc_parameters_adjust (pbproc_t *ctx, bool adjust) __attribute__ ((weak));
+
+void
+pbproc_parameters_adjust (pbproc_t *ctx, bool adjust) {}
+
+void
+pbproc_activate (pbproc_t *ctx, bool flag) __attribute__((weak));
+
+void
+pbproc_activate (pbproc_t *ctx, bool flag) {}
diff --git a/cesar/mac/pbproc/test/fsm/Makefile b/cesar/mac/pbproc/test/fsm/Makefile
index ee1f48266a..232d57ced5 100644
--- a/cesar/mac/pbproc/test/fsm/Makefile
+++ b/cesar/mac/pbproc/test/fsm/Makefile
@@ -4,5 +4,6 @@ HOST_PROGRAMS = test_fsm
test_fsm_SOURCES = test_fsm.c
test_fsm_MODULES = lib mac/pbproc
mac_pbproc_MODULE_SOURCES = fsm.c
+test_fsm_CONFIG_MODULES = mac/common
include $(BASE)/common/make/top.mk
diff --git a/cesar/mac/pbproc/test/int/Config b/cesar/mac/pbproc/test/int/Config
index 2fad84bb33..8c0f945778 100644
--- a/cesar/mac/pbproc/test/int/Config
+++ b/cesar/mac/pbproc/test/int/Config
@@ -4,3 +4,10 @@ CONFIG_STATS = n
CONFIG_DEBUG_CLAIM[target] = n
CONFIG_INTERFACE_SNIFFER[target] = n
CONFIG_ARCH_ILRAM_PRIO_LOW[target] = 0
+
+CONFIG_AV_ONLY_MODE = y
+CONFIG_MAC_COMMON_EOC_SCHED = y
+CONFIG_MAC_COMMON_EOC_MFS = y
+CONFIG_MAC_COMMON_EOC_TEI = y
+CONFIG_MAC_PBPROC_EOC_FC = y
+CONFIG_MAC_PBPROC_EOC_ILRAM = y
diff --git a/cesar/mac/pbproc/test/int/Makefile b/cesar/mac/pbproc/test/int/Makefile
index 0a04d4c852..0d15643383 100644
--- a/cesar/mac/pbproc/test/int/Makefile
+++ b/cesar/mac/pbproc/test/int/Makefile
@@ -16,9 +16,11 @@ common_MODULES = lib hal host mac/pbproc mac/ca mac/common \
TARGET_PROGRAMS = test_pbproc
test_pbproc_SOURCES = $(common_SOURCES) dataplane_stub.c
test_pbproc_MODULES = $(common_MODULES) hle/tools interface cl/stub bufmgr
+#test_pbproc_CONFIG_MODULES = cp/sta/mgr
TARGET_maximus_PROGRAMS = test_pbproc_maximus
test_pbproc_maximus_SOURCES = $(common_SOURCES)
test_pbproc_maximus_MODULES = $(common_MODULES)
+#test_pbproc_maximus_CONFIG_MODULES = cp/sta/mgr
include $(BASE)/common/make/top.mk
diff --git a/cesar/mac/pbproc/test/int/src/add_seg.c b/cesar/mac/pbproc/test/int/src/add_seg.c
index 9537ed820a..d6e7f63a8d 100644
--- a/cesar/mac/pbproc/test/int/src/add_seg.c
+++ b/cesar/mac/pbproc/test/int/src/add_seg.c
@@ -48,7 +48,11 @@ test_pbproc_add_seg (test_pbproc_t *ctx, bool mme, uint lid, uint tei,
mfs = mac_store_mfs_add_tx (ctx->store, tei == MAC_TEI_BCAST, mme,
mme ? MAC_LID_NONE : lid, tei, &added);
if (added)
+ {
+ if (CONFIG_MAC_PBPROC_EOC_FC)
+ mfs->cfp = false;
ca_mfs_add (ctx->ca, mfs);
+ }
/* Generate segments. */
blk_t *blk_first, *blk_last;
blk_first = blk_alloc_desc_range (seg_nb, &blk_last);
diff --git a/cesar/mac/pbproc/test/int/src/test_pbproc.c b/cesar/mac/pbproc/test/int/src/test_pbproc.c
index 199c2119ab..fec62542e7 100644
--- a/cesar/mac/pbproc/test/int/src/test_pbproc.c
+++ b/cesar/mac/pbproc/test/int/src/test_pbproc.c
@@ -508,3 +508,12 @@ cyg_user_start (void)
test_pbproc_init (&test_pbproc_global, fcall);
}
+void
+phy_freq_error_set (phy_t *ctx, bool sync, s32 rho_q30) __attribute__ ((weak));
+
+void
+phy_freq_error_set (phy_t *ctx, bool sync, s32 rho_q30)
+{
+ dbg_assert_ptr (ctx);
+ /* Ignored. */
+}
diff --git a/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c b/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c
index e3d6b412cd..23238d271a 100644
--- a/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c
+++ b/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c
@@ -148,6 +148,9 @@ test_pbproc_check_stats_ (test_t t, test_pbproc_t *ctx,
TEST_PBPROC_CHECK_STAT(cw_lost);
TEST_PBPROC_CHECK_STAT(aifs);
TEST_PBPROC_CHECK_STAT(rx_out_of_alloc);
+#if CONFIG_MAC_PBPROC_EOC_FC
+ TEST_PBPROC_CHECK_STAT(rx_rsof_out_of_alloc);
+#endif
TEST_PBPROC_CHECK_STAT(rx_pool_shortage);
TEST_PBPROC_CHECK_STAT(rx_handle_fc);
TEST_PBPROC_CHECK_STAT(rx_beacon);
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/Config b/cesar/mac/pbproc/test/pbproc_eoc/Config
new file mode 100644
index 0000000000..016152a6d0
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/Config
@@ -0,0 +1,7 @@
+CONFIG_TRACE = y
+CONFIG_STATS = n
+CONFIG_AV_ONLY_MODE = y
+CONFIG_MAC_PBPROC_EOC_FC = y
+CONFIG_MAC_COMMON_EOC_MFS = y
+CONFIG_MAC_COMMON_EOC_SCHED = y
+CONFIG_MAC_COMMON_EOC_TEI = y
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/Makefile b/cesar/mac/pbproc/test/pbproc_eoc/Makefile
new file mode 100644
index 0000000000..eebb4a2252
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/Makefile
@@ -0,0 +1,15 @@
+BASE = ../../../..
+
+DEFS = -DNO_PRIVATE
+
+INCLUDES = mac/pbproc/test/pbproc/override mac/pbproc/test/pbproc_eoc
+
+HOST_PROGRAMS = test_pbproc
+test_pbproc_SOURCES = test_pbproc.c prep_mpdu.c tx_data.c tx_sound.c \
+ rx_data.c rx_sound.c \
+ scenario_defs.c ca.c phy.c hal.c utils.c
+test_pbproc_MODULES = lib lib/scenario mac/pbproc mac/common hal/watchdog
+test_pbproc_MODULES_CONFIG = cp/sta/mgr cl
+hal_watchdog_MODULE_SOURCES =
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/inc/scenario_defs.h b/cesar/mac/pbproc/test/pbproc_eoc/inc/scenario_defs.h
new file mode 100644
index 0000000000..37f88e5ce0
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/inc/scenario_defs.h
@@ -0,0 +1,349 @@
+#ifndef inc_scenario_defs_h
+#define inc_scenario_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/scenario_defs.h
+ * \brief Scenario entries definition.
+ * \ingroup test
+ */
+
+#include "inc/test_pbproc.h"
+
+/* Scenario globals. */
+#define SCENARIO_DEFS_GLOBALS \
+ test_pbproc_t *tp;
+
+/* Scenario actions. */
+#define SCENARIO_DEFS_ACTIONS \
+ phy_rx_fc, \
+ phy_access, \
+ phy_access_conf, \
+ phy_pbdma, \
+ phy_deferred, \
+ phy_extra_timer, \
+ pbproc_activate
+
+typedef struct
+{
+ u32 rx_date;
+ u32 rx_sysdate;
+ u32 *fc_av;
+ bool prp_won;
+ uint slot_count;
+ u32 fc10;
+} scenario_action_phy_rx_fc_t;
+
+void
+scenario_action_phy_rx_fc_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+typedef struct
+{
+ mfs_tx_t *mfs;
+ ca_access_param_t *access_param;
+ bool prp_won;
+ uint slot_count;
+ uint delay_tck;
+} scenario_action_phy_access_t;
+
+void
+scenario_action_phy_access_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+typedef scenario_empty_t scenario_action_phy_access_conf_t;
+
+void
+scenario_action_phy_access_conf_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+typedef struct
+{
+ bool pb_null;
+ bool pb_crc_error;
+ bool pb_it;
+ bool end_rx_pb;
+ bool end_tx_pb;
+ bool end_chandata;
+ uint null_pb_index;
+ u32 *crc_bitmap;
+ uint crc_bitmap_bits;
+} scenario_action_phy_pbdma_t;
+
+void
+scenario_action_phy_pbdma_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+typedef scenario_empty_t scenario_action_phy_deferred_t;
+
+void
+scenario_action_phy_deferred_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+typedef scenario_empty_t scenario_action_phy_extra_timer_t;
+
+void
+scenario_action_phy_extra_timer_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+typedef struct
+{
+ bool flag;
+} scenario_action_pbproc_activate_t;
+
+void
+scenario_action_pbproc_activate_cb (scenario_globals_t *globals,
+ scenario_params_t *params);
+
+/* Scenario events. */
+#define SCENARIO_DEFS_EVENTS \
+ phy_prepare, \
+ phy_deferred_schedule, \
+ phy_set_tonemap, \
+ phy_freq_error_set, \
+ phy_tx_fc10, \
+ phy_tx_param, \
+ phy_tx_param_short, \
+ phy_tx_param_sound, \
+ phy_tx_frame, \
+ phy_tx_prepare, \
+ phy_tx_cancel, \
+ phy_rx_param, \
+ phy_rx_activate, \
+ phy_rx_prepare, \
+ phy_rx_prepare_short, \
+ phy_rx_prepare_sound, \
+ phy_access_timer_cancel, \
+ phy_extra_timer_program, \
+ phy_pbdma_start, \
+ phy_pbdma_update, \
+ phy_pbdma_start_chandata, \
+ phy_spoc_tx_set, \
+ phy_spoc_rx_set, \
+ ca_access_activate, \
+ ca_access_deactivate, \
+ ca_access_hold, \
+ ca_access_vcs_restart, \
+ ca_access_vcs_restart_eifs, \
+ ca_access_program, \
+ ca_access_reprogram, \
+ ca_access_defer, \
+ ca_access_aifs, \
+ ca_access_get_mfs, \
+ ca_access_done, \
+ ca_backoff_deferred, \
+ ca_backoff_success, \
+ ca_backoff_cancel, \
+ pbproc_rx_cb, \
+ pbproc_rx_beacon_cb
+
+typedef struct
+{
+ phy_prepare_type_t type;
+ bool wait;
+} scenario_event_phy_prepare_t;
+
+typedef scenario_empty_t scenario_event_phy_deferred_schedule_t;
+
+typedef scenario_empty_t scenario_event_phy_set_tonemap_t;
+
+typedef struct
+{
+ bool sync;
+ s32 rho_q30;
+} scenario_event_phy_freq_error_set_t;
+
+typedef struct
+{
+ u32 date;
+ u32 fc10;
+} scenario_event_phy_tx_fc10_t;
+
+typedef struct
+{
+ phy_fc_mode_t fc_mode;
+ phy_mod_t mod;
+ phy_fecrate_t fecrate;
+ phy_pb_size_t pb_size;
+ phy_gil_t gil;
+ uint symbol_nb;
+} scenario_event_phy_tx_param_t;
+
+typedef struct
+{
+ phy_fc_mode_t fc_mode;
+} scenario_event_phy_tx_param_short_t;
+
+typedef struct
+{
+ phy_fc_mode_t fc_mode;
+ uint nb_pb;
+ phy_mod_t mod;
+ phy_fecrate_t fecrate;
+ phy_pb_size_t pb_size;
+ phy_gil_t gil;
+ uint symbol_nb;
+} scenario_event_phy_tx_param_sound_t;
+
+typedef struct
+{
+ u32 date;
+ bool want_conf;
+ bool stop_tx_on_prp_lost;
+} scenario_event_phy_tx_frame_t;
+
+typedef scenario_empty_t scenario_event_phy_tx_prepare_t;
+
+typedef scenario_empty_t scenario_event_phy_tx_cancel_t;
+
+typedef struct
+{
+ phy_fc_mode_t fc_mode;
+} scenario_event_phy_rx_param_t;
+
+typedef struct
+{
+ bool now;
+ u32 date;
+ bool pre_detection;
+} scenario_event_phy_rx_activate_t;
+
+typedef struct
+{
+ uint nb_pb;
+ phy_mod_t mod;
+ phy_fecrate_t fecrate;
+ phy_pb_size_t pb_size;
+ phy_gil_t gil;
+ uint symbol_nb;
+ uint tcc_halfit;
+} scenario_event_phy_rx_prepare_t;
+
+typedef scenario_empty_t scenario_event_phy_rx_prepare_short_t;
+
+typedef struct
+{
+ uint nb_pb;
+ phy_mod_t mod;
+ phy_fecrate_t fecrate;
+ phy_pb_size_t pb_size;
+ phy_gil_t gil;
+ uint symbol_nb;
+} scenario_event_phy_rx_prepare_sound_t;
+
+typedef scenario_empty_t scenario_event_phy_access_timer_cancel_t;
+
+typedef struct
+{
+ u32 date;
+} scenario_event_phy_extra_timer_program_t;
+
+typedef struct
+{
+ bool bypass_aes;
+ uint nb_total;
+ uint nb_pb_it;
+ bool chandata;
+ bool now;
+} scenario_event_phy_pbdma_start_t;
+
+typedef struct
+{
+ uint nb_pb_it;
+} scenario_event_phy_pbdma_update_t;
+
+typedef scenario_empty_t scenario_event_phy_pbdma_start_chandata_t;
+
+typedef scenario_empty_t scenario_event_phy_spoc_tx_set_t;
+
+typedef scenario_empty_t scenario_event_phy_spoc_rx_set_t;
+
+typedef struct
+{
+ u32 date;
+ mac_coexistence_mode_t coexistence_mode;
+ u8 snid;
+ bool hybrid;
+ bool merge;
+ uint nek_switch;
+} scenario_event_ca_access_activate_t;
+
+typedef scenario_empty_t scenario_event_ca_access_deactivate_t;
+
+typedef scenario_empty_t scenario_event_ca_access_hold_t;
+
+typedef struct
+{
+ u32 end_date;
+} scenario_event_ca_access_vcs_restart_t;
+
+typedef struct
+{
+ u32 start_date;
+} scenario_event_ca_access_vcs_restart_eifs_t;
+
+typedef struct
+{
+ u32 date;
+} scenario_event_ca_access_program_t;
+
+typedef struct
+{
+ u32 date;
+ uint duration_tck;
+ uint tei;
+} scenario_event_ca_access_reprogram_t;
+
+typedef struct
+{
+ u32 date;
+} scenario_event_ca_access_defer_t;
+
+typedef struct
+{
+ mac_coexistence_mode_t coexistence_mode;
+ u8 snid;
+ bool hybrid;
+ bool merge;
+ uint nek_switch;
+} scenario_event_ca_access_aifs_t;
+
+typedef scenario_empty_t scenario_event_ca_access_get_mfs_t;
+
+typedef scenario_empty_t scenario_event_ca_access_done_t;
+
+typedef struct
+{
+ uint slot_count;
+} scenario_event_ca_backoff_deferred_t;
+
+typedef scenario_empty_t scenario_event_ca_backoff_success_t;
+
+typedef scenario_empty_t scenario_event_ca_backoff_cancel_t;
+
+typedef struct
+{
+ uint pb_nb;
+ uint chandata_nb;
+ u32 beacon_period_start_date;
+ uint lid;
+ uint fl_tck;
+ u8 pending_seg_info;
+ uint pb_size;
+ uint mpdu_cnt;
+ mfs_fsm_cmd_t mfs_cmd_data;
+ mfs_fsm_cmd_t mfs_cmd_mme;
+ uint duration_tck;
+} scenario_event_pbproc_rx_cb_t;
+
+typedef struct
+{
+ uint duration_tck;
+} scenario_event_pbproc_rx_beacon_cb_t;
+
+#endif /* inc_scenario_defs_h */
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/inc/test_pbproc.h b/cesar/mac/pbproc/test/pbproc_eoc/inc/test_pbproc.h
new file mode 100644
index 0000000000..db29992dbb
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/inc/test_pbproc.h
@@ -0,0 +1,96 @@
+#ifndef inc_test_pbproc_h
+#define inc_test_pbproc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/test_pbproc.h
+ * \brief PBProc test.
+ * \ingroup test
+ */
+#include "lib/test.h"
+#include "lib/rnd.h"
+#include "mac/common/config.h"
+#include "mac/common/ntb.h"
+#include "mac/common/store.h"
+#include "mac/ca/ca.h"
+#include "mac/pbproc/pbproc.h"
+#include "mac/pbproc/inc/context.h"
+
+/** Default NTB offset value. */
+#define TEST_PBPROC_NTB_OFFSET_TCK 0x12345
+
+/** Date offset for expiration tests. */
+#define TEST_PBPROC_EXPIRATION_DATE_OFFSET 1000000000
+
+/** End date of default allocation. */
+#define TEST_PBPROC_ALLOC_END_DATE 0x80000000
+
+/** Test pbproc context. */
+struct test_pbproc_t
+{
+ /** Random context. */
+ lib_rnd_t rnd[1];
+ /** Mac configuration. */
+ mac_config_t config;
+ /** Short network identifier. */
+ u8 snid;
+ /** Mac MFS and STA store. */
+ mac_store_t *store;
+ /** PB Processing context. */
+ pbproc_t *pbproc;
+ /** Channel Access context. */
+ ca_t *ca;
+ /** Recorded stats before test. */
+ pbproc_stat_t recorded_stats;
+};
+typedef struct test_pbproc_t test_pbproc_t;
+
+BEGIN_DECLS
+
+void
+test_pbproc_init (test_pbproc_t *ctx);
+
+/**
+ * Setup allocation in PBProc.
+ * \param ctx test context
+ * \param hybrid whether to use hybrid mode
+ * \param beacon_period_start_date start date of the beacon period
+ *
+ * This is to be done by PBProc on activate or AIFS, but this is a shortcut
+ * for tests.
+ */
+void
+test_pbproc_alloc (test_pbproc_t *ctx, bool hybrid,
+ u32 beacon_period_start_date);
+
+/**
+ * Check stats have been incremented.
+ * \param t test context
+ * \param ctx test pbproc context
+ * \param stats expected stats increment
+ */
+void
+test_pbproc_check_stats_ (test_t t, test_pbproc_t *ctx,
+ const pbproc_stat_t *stats);
+
+#define test_pbproc_check_stats(t, ctx, params...) \
+ test_pbproc_check_stats_ ((t), (ctx), & (pbproc_stat_t) { params })
+
+/**
+ * Reset stats.
+ * \param ctx test pbproc context
+ */
+void
+test_pbproc_check_stats_reset (test_pbproc_t *ctx);
+
+void
+test_pbproc_uninit (test_pbproc_t *ctx);
+
+END_DECLS
+
+#endif /* inc_test_pbproc_h */
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/inc/utils.h b/cesar/mac/pbproc/test/pbproc_eoc/inc/utils.h
new file mode 100644
index 0000000000..8de5d1f8b5
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/inc/utils.h
@@ -0,0 +1,82 @@
+#ifndef inc_utils_h
+#define inc_utils_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/utils.h
+ * \brief Utilities.
+ * \ingroup test
+ */
+#include "mac/common/mfs.h"
+#include "mac/common/tonemap.h"
+#include "mac/common/store.h"
+#include "inc/test_pbproc.h"
+
+/** Step between created PBs' expiration date. Needed, because of the hysteresis
+ * offset used in the expiration process, to have some control on the number of
+ * expired PBs. */
+#define UTILS_MFS_EXPIRATION_NTB_STEP PBPROC_EXPIRATION_HYSTERESIS_OFFSET
+
+/** Define interval properties. */
+struct utils_interval_t
+{
+ /** Interval end offset, 0 to stop. */
+ uint end_offset_tck;
+ /** TMI for this interval. */
+ u8 tmi;
+ /** Number of bits in this tonemap if it has to be created, else 0. */
+ uint tm_mod;
+};
+typedef struct utils_interval_t utils_interval_t;
+
+BEGIN_DECLS
+
+mfs_tx_t *
+utils_mfs_tx_prepare (bool bcast, bool mme, uint lid, uint tei, int seg_nb);
+
+mfs_tx_t *
+utils_mfs_tx_holes_prepare (bool bcast, bool mme, uint lid, uint tei,
+ int seg_nb, u64 holes_bmp, mac_store_t *store);
+
+void
+utils_mfs_tx_cleanup (mfs_tx_t *mfs);
+
+tonemap_t *
+utils_sta_prepare_default_tonemap (test_pbproc_t *tp, bool tx, uint tei,
+ uint tmi, uint tm_mod, uint tm_max_fl_tck,
+ uint *dx);
+
+/**
+ * Prepare tonemaps intervals.
+ * \param tp test context
+ * \param tei STA TEI
+ * \param intervals list of intervals to prepare
+ * \param default_tmi new default TMI
+ * \return intervals version
+ *
+ * utils_sta_prepare_default_tonemap should have been called before.
+ */
+uint
+utils_sta_prepare_intervals (test_pbproc_t *tp, uint tei,
+ utils_interval_t *intervals, uint default_tmi);
+
+void
+utils_prepare_encryption (test_pbproc_t *tp, bool encrypted, bool sta_auth,
+ uint tei, uint nek_switch);
+
+void
+utils_delete_mfs_saved(void);
+
+mfs_tx_t *
+utils_mfs_tx_prepare_save (bool bcast, bool mme, uint lid, uint tei,
+ uint seg_nb);
+
+
+END_DECLS
+
+#endif /* inc_utils_h */
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/ca.c b/cesar/mac/pbproc/test/pbproc_eoc/src/ca.c
new file mode 100644
index 0000000000..34df951f67
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/ca.c
@@ -0,0 +1,179 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/ca.c
+ * \brief Override CA functions.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "mac/ca/ca.h"
+
+#include "mac/ca/inc/context.h"
+
+#include "lib/scenario/scenario.h"
+#include "inc/utils.h"
+
+ca_t *
+ca_init (phy_t *phy, mac_config_t *config, mac_store_t *store,
+ uint anticipation_tck)
+{
+ static ca_t ca_ctx;
+ ca_t *ctx = &ca_ctx;
+ ctx->mfs = NULL;
+ dbg_assert (anticipation_tck);
+ return ctx;
+}
+
+void
+ca_uninit (ca_t *ctx)
+{
+}
+
+void
+ca_mfs_hold_common (ca_t *ctx, mfs_tx_t *mfs, bool locked)
+{
+ dbg_assert (mfs);
+ dbg_assert (locked);
+ mfs->ca_state = CA_MFS_STATE_HELD;
+}
+
+void
+ca_sta_update (ca_t *ctx, sta_t *sta)
+{
+ dbg_assert (sta);
+}
+
+const ca_alloc_param_t *
+ca_access_activate (ca_t *ctx, u32 date)
+{
+ scenario_event (ca_access_activate, params);
+ test_fail_unless (date == params->date);
+ ctx->current_allocation_param.coexistence_mode = params->coexistence_mode;
+ ctx->current_allocation_param.snid = params->snid;
+ ctx->current_allocation_param.hybrid = params->hybrid;
+ ctx->current_allocation_param.merge = params->merge;
+ ctx->current_allocation_param.nek_switch = params->nek_switch;
+ ctx->current_allocation_param.end_date = TEST_PBPROC_ALLOC_END_DATE;
+ ctx->current_allocation_param.aifs_date = TEST_PBPROC_ALLOC_END_DATE;
+ return &ctx->current_allocation_param;
+}
+
+void
+ca_access_deactivate (ca_t *ctx)
+{
+ scenario_event (ca_access_deactivate);
+}
+
+void
+ca_access_hold (ca_t *ctx)
+{
+ scenario_event (ca_access_hold);
+}
+
+void
+ca_access_vcs_restart (ca_t *ctx, u32 end_date)
+{
+ scenario_event (ca_access_vcs_restart, params);
+ test_fail_unless (end_date == params->end_date);
+}
+
+void
+ca_access_vcs_restart_eifs (ca_t *ctx, u32 start_date)
+{
+ scenario_event (ca_access_vcs_restart_eifs, params);
+ test_fail_unless (start_date == params->start_date);
+}
+
+void
+ca_access_program (ca_t *ctx, u32 date)
+{
+ scenario_event (ca_access_program, params);
+ test_fail_unless (date == params->date);
+}
+
+void
+ca_access_reprogram (ca_t *ctx, u32 date, uint duration_tck, uint tei)
+{
+ scenario_event (ca_access_reprogram, params);
+ test_fail_unless (date == params->date);
+ test_fail_unless (duration_tck == params->duration_tck);
+ test_fail_unless (tei == params->tei);
+ ctx->access_param.access_date = date;
+ ctx->access_param.duration_tck = duration_tck;
+ ctx->access_param.prp = false;
+ ctx->access_param.cfp = true;
+}
+
+void
+ca_access_defer (ca_t *ctx, u32 date)
+{
+ scenario_event (ca_access_defer, params);
+ test_fail_unless (date == params->date);
+}
+
+const ca_alloc_param_t *
+ca_access_aifs (ca_t *ctx)
+{
+ scenario_event (ca_access_aifs, params);
+ ctx->current_allocation_param.coexistence_mode = params->coexistence_mode;
+ ctx->current_allocation_param.snid = params->snid;
+ ctx->current_allocation_param.hybrid = params->hybrid;
+ ctx->current_allocation_param.merge = params->merge;
+ ctx->current_allocation_param.nek_switch = params->nek_switch;
+ ctx->current_allocation_param.end_date = TEST_PBPROC_ALLOC_END_DATE;
+ ctx->current_allocation_param.aifs_date = TEST_PBPROC_ALLOC_END_DATE;
+ return &ctx->current_allocation_param;
+}
+
+const ca_access_param_t *
+ca_access_get_param (ca_t *ctx)
+{
+ return &ctx->access_param;
+}
+
+mfs_tx_t *
+ca_access_get_mfs (ca_t *ctx)
+{
+ scenario_event (ca_access_get_mfs);
+ return ctx->mfs;
+}
+
+void
+ca_access_done (ca_t *ctx)
+{
+ if (scenario.current)
+ {
+ scenario_event (ca_access_done);
+ }
+}
+
+void
+ca_backoff_deferred (ca_t *ctx, int slot_counter)
+{
+ scenario_event (ca_backoff_deferred, params);
+ test_fail_unless (slot_counter == (int) params->slot_count);
+}
+
+void
+ca_backoff_success (ca_t *ctx)
+{
+ scenario_event (ca_backoff_success);
+}
+
+void
+ca_backoff_cancel (ca_t *ctx)
+{
+ scenario_event (ca_backoff_cancel);
+}
+
+int
+ca_sta_active_nb (ca_t *ctx)
+{
+ /* default value to not activate the specific algorithm. */
+ return 256;
+}
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/hal.c b/cesar/mac/pbproc/test/pbproc_eoc/src/hal.c
new file mode 100644
index 0000000000..0c727a126c
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/hal.c
@@ -0,0 +1,27 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/hal.c
+ * \brief HAL stub.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "hal/watchdog/watchdog.h"
+
+void
+hal_watchdog_activate (uint event, bool active)
+{
+ dbg_claim (event == HAL_WATCHDOG_EVENT_PBPROC);
+}
+
+void
+hal_watchdog_trigger (uint event)
+{
+ dbg_claim (event == HAL_WATCHDOG_EVENT_PBPROC);
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/phy.c b/cesar/mac/pbproc/test/pbproc_eoc/src/phy.c
new file mode 100644
index 0000000000..a25696b83b
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/phy.c
@@ -0,0 +1,400 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/phy.c
+ * \brief Override HAL Phy functions.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "hal/phy/phy.h"
+#include "hal/phy/pbdma.h"
+
+#include "hal/phy/inc/context.h"
+
+#include "lib/scenario/scenario.h"
+
+static phy_t phy_global;
+
+phy_t *
+phy_init (void *user_data, phy_rx_fc_cb_t rx_fc_cb, phy_access_cb_t access_cb,
+ phy_access_conf_cb_t access_conf_cb, phy_pbdma_cb_t pbdma_cb,
+ phy_tx_false_alarm_cb_t tx_false_alarm_cb,
+ phy_deferred_cb_t deferred_cb)
+{
+ phy_t *ctx = &phy_global;
+ ctx->current_date = 0;
+ ctx->user_data = user_data;
+ ctx->rx_fc_cb = rx_fc_cb;
+ ctx->access_cb = access_cb;
+ ctx->access_conf_cb = access_conf_cb;
+ ctx->pbdma_cb = pbdma_cb;
+ ctx->tx_false_alarm_cb = tx_false_alarm_cb;
+ ctx->deferred_cb = deferred_cb;
+ ctx->prp_won = false;
+ ctx->slot_count = 0;
+ ctx->pbdma_nb_total = 0;
+ ctx->pbdma_first_pb = NULL;
+ uint i;
+ for (i = 0; i < COUNT (ctx->tx_fc); i++)
+ ctx->tx_fc[i] = 0;
+ for (i = 0; i < COUNT (ctx->crc_bitmap); i++)
+ ctx->crc_bitmap[i] = 0;
+ return ctx;
+}
+
+void
+phy_check_hardware (phy_t *ctx)
+{
+}
+
+void
+phy_uninit (phy_t *ctx)
+{
+}
+
+void
+phy_prepare (phy_t *ctx, phy_prepare_type_t type, bool wait)
+{
+ scenario_event (phy_prepare, params);
+ dbg_assert (ctx);
+ test_fail_unless (type == params->type);
+ test_fail_unless (wait == params->wait);
+}
+
+void
+phy_deferred_schedule (phy_t *ctx)
+{
+ scenario_event (phy_deferred_schedule);
+ dbg_assert (ctx);
+ ctx->dsr_scheduled = true;
+}
+
+u32
+phy_date (void)
+{
+ return phy_global.current_date;
+}
+
+void
+phy_set_tonemask (phy_t *ctx, u32 *tonemask, uint carrier_nb)
+{
+}
+
+void
+phy_set_tonemap (phy_t *ctx, blk_t *tonemap)
+{
+ scenario_event (phy_set_tonemap);
+ /* Test tonemap? */
+}
+
+void
+phy_freq_error_set (phy_t *ctx, bool sync, s32 rho_q30)
+{
+ scenario_event (phy_freq_error_set, params);
+ test_fail_unless (sync == params->sync);
+ test_fail_unless (rho_q30 == params->rho_q30);
+}
+
+void
+phy_tx_fc10 (phy_t *ctx, u32 date, u32 fc_10)
+{
+ scenario_event (phy_tx_fc10, params);
+ test_fail_unless (date == params->date);
+ test_fail_unless (fc_10 == params->fc10);
+}
+
+void
+phy_tx_param_ (phy_t *ctx, phy_fc_mode_t fc_mode, u32 mod_fecrate_pb_size,
+ phy_gil_t gil PHY_TRACE_SYMBOL_NB (uint symbol_nb))
+{
+ phy_mod_t mod = BF_GET (PHY_COMBO_PARAMS__MOD, mod_fecrate_pb_size);
+ phy_fecrate_t fecrate = BF_GET (PHY_COMBO_PARAMS__FECRATE,
+ mod_fecrate_pb_size);
+ phy_pb_size_t pb_size = BF_GET (PHY_COMBO_PARAMS__PB_SIZE,
+ mod_fecrate_pb_size);
+ scenario_event (phy_tx_param, params);
+ test_fail_unless (fc_mode == params->fc_mode);
+ test_fail_unless (mod == params->mod);
+ test_fail_unless (fecrate == params->fecrate);
+ test_fail_unless (pb_size == params->pb_size);
+ test_fail_unless (gil == params->gil);
+#if CONFIG_TRACE
+ test_fail_unless (symbol_nb == params->symbol_nb);
+#endif
+}
+
+void
+phy_tx_param_short (phy_t *ctx, phy_fc_mode_t fc_mode)
+{
+ scenario_event (phy_tx_param_short, params);
+ test_fail_unless (fc_mode == params->fc_mode);
+}
+
+void
+phy_tx_param_sound_ (phy_t *ctx, phy_fc_mode_t fc_mode, uint nb_pb,
+ u32 mod_fecrate_pb_size, phy_gil_t gil
+ PHY_TRACE_SYMBOL_NB (uint symbol_nb))
+{
+ phy_mod_t mod = BF_GET (PHY_COMBO_PARAMS__MOD, mod_fecrate_pb_size);
+ phy_fecrate_t fecrate = BF_GET (PHY_COMBO_PARAMS__FECRATE,
+ mod_fecrate_pb_size);
+ phy_pb_size_t pb_size = BF_GET (PHY_COMBO_PARAMS__PB_SIZE,
+ mod_fecrate_pb_size);
+ scenario_event (phy_tx_param_sound, params);
+ test_fail_unless (fc_mode == params->fc_mode);
+ test_fail_unless (nb_pb == params->nb_pb);
+ test_fail_unless (mod == params->mod);
+ test_fail_unless (fecrate == params->fecrate);
+ test_fail_unless (pb_size == params->pb_size);
+ test_fail_unless (gil == params->gil);
+#if CONFIG_TRACE
+ test_fail_unless (symbol_nb == params->symbol_nb);
+#endif
+}
+
+void
+phy_tx_frame_ (phy_t *ctx, u32 date, u32 want_conf__stop_tx_on_prp_lost,
+ const u32 fc_av[4])
+{
+ bool want_conf = (want_conf__stop_tx_on_prp_lost & PHY_WANT_CONF)
+ ? true : false;
+ bool stop_tx_on_prp_lost = (want_conf__stop_tx_on_prp_lost
+ & PHY_STOP_ON_PRP_LOST) ? true : false;
+ scenario_event (phy_tx_frame, params);
+ test_fail_unless (date == params->date);
+ test_fail_unless (want_conf == params->want_conf);
+ test_fail_unless (stop_tx_on_prp_lost == params->stop_tx_on_prp_lost);
+ ctx->tx_fc[0] = fc_av[0];
+ ctx->tx_fc[1] = fc_av[1];
+ ctx->tx_fc[2] = fc_av[2];
+ ctx->tx_fc[3] = fc_av[3];
+}
+
+void
+phy_tx_prepare (phy_t *ctx)
+{
+ scenario_event (phy_tx_prepare);
+ test_fail_unless (ctx->pbdma_nb_total != 0);
+}
+
+void
+phy_tx_cancel (phy_t *ctx)
+{
+ scenario_event (phy_tx_cancel);
+}
+
+void
+phy_rx_param (phy_t *ctx, phy_fc_mode_t fc_mode)
+{
+ scenario_event (phy_rx_param, params);
+ test_fail_unless (fc_mode == params->fc_mode);
+}
+
+void
+phy_rx_activate (phy_t *ctx, bool now, u32 date, bool pre_detection)
+{
+ scenario_event (phy_rx_activate, params);
+ test_fail_unless (now == params->now);
+ test_fail_unless (date == params->date);
+ test_fail_unless (pre_detection == params->pre_detection);
+}
+
+void
+phy_rx_prepare (phy_t *ctx, uint nb_pb, u32 mod_fecrate_pb_size,
+ phy_gil_t gil, uint symbol_nb, uint tcc_halfit)
+{
+ phy_mod_t mod = BF_GET (PHY_COMBO_PARAMS__MOD, mod_fecrate_pb_size);
+ phy_fecrate_t fecrate = BF_GET (PHY_COMBO_PARAMS__FECRATE,
+ mod_fecrate_pb_size);
+ phy_pb_size_t pb_size = BF_GET (PHY_COMBO_PARAMS__PB_SIZE,
+ mod_fecrate_pb_size);
+ scenario_event (phy_rx_prepare, params);
+ test_fail_unless (nb_pb == params->nb_pb);
+ test_fail_unless (mod == params->mod);
+ test_fail_unless (fecrate == params->fecrate);
+ test_fail_unless (pb_size == params->pb_size);
+ test_fail_unless (gil == params->gil);
+ test_fail_unless (symbol_nb == params->symbol_nb);
+ test_fail_unless (tcc_halfit == params->tcc_halfit);
+}
+
+void
+phy_rx_prepare_short (phy_t *ctx)
+{
+ scenario_event (phy_rx_prepare_short);
+}
+
+void
+phy_rx_prepare_sound (phy_t *ctx, uint nb_pb, u32 mod_fecrate_pb_size,
+ phy_gil_t gil, uint symbol_nb)
+{
+ phy_mod_t mod = BF_GET (PHY_COMBO_PARAMS__MOD, mod_fecrate_pb_size);
+ phy_fecrate_t fecrate = BF_GET (PHY_COMBO_PARAMS__FECRATE,
+ mod_fecrate_pb_size);
+ phy_pb_size_t pb_size = BF_GET (PHY_COMBO_PARAMS__PB_SIZE,
+ mod_fecrate_pb_size);
+ scenario_event (phy_rx_prepare_sound, params);
+ test_fail_unless (nb_pb == params->nb_pb);
+ test_fail_unless (mod == params->mod);
+ test_fail_unless (fecrate == params->fecrate);
+ test_fail_unless (pb_size == params->pb_size);
+ test_fail_unless (gil == params->gil);
+ test_fail_unless (symbol_nb == params->symbol_nb);
+}
+
+u32
+phy_rx_fc10 (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ return ctx->fc10;
+}
+
+u32
+phy_rx_sysdate (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ return ctx->rx_sysdate;
+}
+
+void
+phy_access_timer_cancel (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ scenario_event (phy_access_timer_cancel);
+}
+
+void
+phy_extra_timer_init (phy_t *ctx, void *extra_timer_user_data,
+ phy_extra_timer_cb_t extra_timer_cb)
+{
+ dbg_assert (ctx);
+ dbg_assert (extra_timer_user_data == ctx->user_data);
+ ctx->extra_timer_cb = extra_timer_cb;
+}
+
+void
+phy_extra_timer_program (phy_t *ctx, u32 date)
+{
+ dbg_assert (ctx);
+ scenario_event (phy_extra_timer_program, params);
+ test_fail_unless (date == params->date);
+}
+
+void
+phy_access_timer_program (phy_t *ctx, u32 date)
+{
+ dbg_assert (ctx);
+}
+
+uint
+phy_access_backoff_slot_count (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ return ctx->slot_count;
+}
+
+bool
+phy_access_backoff_prp_won (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ return ctx->prp_won;
+}
+
+void
+phy_pbdma_start (phy_t *ctx, bool bypass_aes, const u32 nek[4], uint nb_total,
+ uint nb_pb_it, phy_pb_t *first_pb,
+ phy_chandata_t *first_chandata, bool now)
+{
+ scenario_event (phy_pbdma_start, params);
+ test_fail_unless (bypass_aes == params->bypass_aes);
+ test_fail_unless (nb_total == params->nb_total);
+ test_fail_unless (nb_pb_it == params->nb_pb_it);
+ test_fail_unless ((first_chandata ? true : false) == params->chandata);
+ test_fail_unless (now == params->now);
+ ctx->pbdma_nb_total = nb_total;
+ ctx->pbdma_first_pb = first_pb;
+}
+
+void
+phy_pbdma_update (phy_t *ctx, uint nb_pb_it)
+{
+ scenario_event (phy_pbdma_update, params);
+ test_fail_unless (nb_pb_it == params->nb_pb_it);
+}
+
+phy_pb_t *
+phy_pbdma_get_tail (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ uint i;
+ phy_pb_t *pb;
+ for (i = 1, pb = ctx->pbdma_first_pb;
+ i < ctx->pbdma_nb_total;
+ i++, pb = PARENT_OF (phy_pb_t, blk, pb->blk.next))
+ ;
+ return pb;
+}
+
+volatile const u32 *
+phy_pbdma_get_crc_bitmap (phy_t *ctx)
+{
+ return ctx->crc_bitmap;
+}
+
+void
+phy_pbdma_start_chandata (phy_t *ctx, phy_chandata_t *first_chandata)
+{
+ scenario_event (phy_pbdma_start_chandata);
+}
+
+void
+phy_spoc_tx_set (phy_t *ctx, phy_spoc_coeff_t *coeff)
+{
+ scenario_event (phy_spoc_tx_set);
+ dbg_assert (ctx);
+ dbg_assert (coeff);
+ dbg_assert (coeff->part2);
+}
+
+void
+phy_spoc_rx_set (phy_t *ctx, phy_spoc_coeff_t *coeff)
+{
+ scenario_event (phy_spoc_rx_set);
+ dbg_assert (ctx);
+ dbg_assert (coeff);
+ dbg_assert (coeff->part2);
+}
+
+u32
+phy_rx_agc_gain (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ return 0;
+}
+
+void
+phy_debug_unexpected (phy_t *ctx, uint expected_event_mask,
+ uint unexpected_event)
+{
+ ctx->expected_event_mask = expected_event_mask;
+ ctx->unexpected_event = unexpected_event;
+}
+
+void
+phy_compute_spoc_coeff (s32 rho_q30, phy_spoc_coeff_t *coeff)
+{
+ dbg_assert (coeff);
+ coeff->rho_q30 = rho_q30;
+}
+
+void
+phy_compute_spoc_initial_coeff (phy_spoc_coeff_t *coeff)
+{
+ phy_compute_spoc_coeff (0, coeff);
+}
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/prep_mpdu.c b/cesar/mac/pbproc/test/pbproc_eoc/src/prep_mpdu.c
new file mode 100644
index 0000000000..fc650759d6
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/prep_mpdu.c
@@ -0,0 +1,1925 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/prep_mpdu.c
+ * \brief PBProc prep_mpdu test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/test_pbproc.h"
+#include "inc/utils.h"
+
+#include "mac/common/timings.h"
+
+#include "hal/phy/inc/context.h"
+
+/* Maximum number of bits usable in a CRC bitmap. */
+#define PREP_MPDU_TEST_CRC_BITMAP_SIZE 72u
+
+/** Test parameters. */
+struct prep_mpdu_test_t
+{
+ /** Multicast. */
+ bool bcast;
+ /** MME. */
+ bool mme;
+ /** LID. */
+ uint lid;
+ /** Partial acknowledgement. */
+ bool partial_ack;
+ /** Number of MFS segments. */
+ int mfs_seg_nb;
+ /** Duration of the access, measured as a number of symbol. */
+ uint duration_symb_nb;
+ /** Expected number of symbols. */
+ uint symb_nb;
+ /** Expected total number of segments for the main MFS. */
+ uint main_seg_nb_total;
+ /** Expected pending segments. */
+ uint seg_nb_pending;
+ /** Expected MPDU count (non zero for bursts). */
+ uint mpdu_count;
+ /** If set, CRC checking is done. */
+ bool crc;
+ /** If set (and crc not set), acknowledge all, else cancel
+ * transmission. */
+ bool all_ok;
+ /** If not zero and crc not set, uniform SACK information. */
+ uint sacki;
+ /** Updated default TMI after SACKI handling. */
+ uint tmi_sacki;
+ /** Indicate PBs with bad CRC. */
+ u32 crc_error[3];
+ /** Encoded SACK information, or 0 for bitmap. */
+ u64 encoded_sack;
+ /** Length of encoded SACK (to be eaten). */
+ uint encoded_sack_length;
+ /** Tonemap index. */
+ uint tmi;
+ /** Tonemap updated during transmission (by CE). */
+ uint tmi_update;
+ /** Tonemap number of bits per carrier. */
+ uint tm_mod;
+ /** Maximum frame length limited by the tonemap. */
+ uint tm_max_fl_tck;
+ /** Table of intervals. */
+ utils_interval_t *intervals;
+ /** Used interval. */
+ uint interval;
+ /** Updated interval TMI after SACKI handling. */
+ uint interval_tmi_sacki;
+ /** If not 0, override sound_reason_code. */
+ tonemap_sound_reason_code_t sound_reason_code;
+ /** Wether encryption is done. */
+ bool encrypted;
+ /** True for unassociated TX (unassociated unicast or multi network
+ * broadcast). */
+ bool unassociated;
+ /** Remove the MFS during preparation:
+ * - 1: before first call (obsolete).
+ * - 2: before chaining remaining segments.
+ * - 3: before acknowledge or cancel. */
+ uint remove;
+ /** True to simulate that ACCESS_CONF event has never been received. */
+ bool no_access_conf;
+ /** Sound completed flag. */
+ bool scf;
+ /** Beacon detected. */
+ bool beacon_detected;
+ /** HP 1.0 detected. */
+ bool hp10_detected;
+ /** HP 1.1 detected. */
+ bool hp11_detected;
+ /** STA pending PB (or 0 for default value). */
+ u8 sppb;
+ /** Current date for expiration tests. */
+ uint expiration_date;
+ /** Receiver window size. */
+ uint window_size;
+ /** Bitmap used to create holes in the generated MFS. */
+ u64 mfs_holes_bitmap;
+ /* If set, MFS FSM state test is done. */
+ bool mfs_fsm_state_test;
+ /* Expected MFS FSM state after SACK reception. */
+ mfs_fsm_cmd_t expected_mfs_fsm_state;
+ /* Force contention free period to test reverse duration. */
+ bool cfp;
+ /* for RSOF */
+ bool bbf;
+ /* Piggy back sacki */
+ bool pg_sacki;
+};
+
+#define prep_mpdu_test(t, tp, date, params...) \
+ prep_mpdu_test_f ((t), (tp), (date), \
+ &(struct prep_mpdu_test_t) { params })
+
+void
+prep_mpdu_test_f (test_t t, test_pbproc_t *tp, u32 date,
+ const struct prep_mpdu_test_t *params)
+{
+ uint i;
+ tp->pbproc->config->tei = params->bbf ? 31 : 1;
+ const uint stei = (!params->bcast && params->unassociated
+ ? 0 : tp->config.tei);
+ const uint dtei = (params->bcast ? MAC_TEI_BCAST : params->bbf ? 1 : 31);
+ const uint ack_dtei = params->partial_ack ? 3 : dtei;
+ const uint lid = params->mme ? MAC_LID_NONE : params->lid;
+ const uint fclid = params->mme ? MAC_LID_NO_DATA : lid;
+ pb_t *seg;
+ test_within (t);
+ uint nack_count;
+ if (!params->crc)
+ nack_count = params->all_ok ? 0 : params->main_seg_nb_total;
+ else
+ {
+ nack_count = 0;
+ for (i = 0; i < COUNT (params->crc_error); i++)
+ {
+ u32 x = params->crc_error[i];
+ nack_count += BITS_ONES_COUNT (x);
+ }
+ nack_count = MIN (params->main_seg_nb_total, nack_count);
+ }
+ uint seg_nb_pending = params->seg_nb_pending;
+ tp->config.partial_ack_tei_default =
+ params->partial_ack || params->unassociated ? 3 : MAC_TEI_BCAST;
+ /* Ask for channel data to enable sound transmission. */
+ u32 chandata_conf[1] = { 0 };
+ pbproc_set_chandata_conf (
+ tp->pbproc, (phy_chandata_conf_t *) chandata_conf, 1, false);
+ /* Prepare tone map. */
+ tonemap_t *tm = &tp->config.tonemask_info.tonemap_robo[PHY_MOD_ROBO];
+ uint dx = MAC_DX417_TCK;
+ bool sta_created = false;
+ if (params->tmi != PHY_MOD_ROBO
+ || (params->encrypted && !params->bcast)
+ || params->intervals)
+ {
+ tm = utils_sta_prepare_default_tonemap (tp, true, dtei, params->tmi,
+ params->tm_mod,
+ params->tm_max_fl_tck, &dx);
+ sta_created = true;
+ }
+ uint interval = TONEMAP_INTERVAL_NB;
+ uint intervals_version;
+ if (params->intervals)
+ {
+ intervals_version = utils_sta_prepare_intervals (
+ tp, dtei, params->intervals, PHY_MOD_ROBO);
+ interval = params->interval;
+ }
+ tonemap_sound_reason_code_t sound_reason_code =
+ params->sound_reason_code ? params->sound_reason_code :
+ params->mme ? TONEMAP_SRC_NULL :
+ params->tmi == TONEMAP_INDEX_INITIAL_START ? TONEMAP_SRC_INITIAL :
+ params->tmi == TONEMAP_INDEX_INITIAL_ERROR ? TONEMAP_SRC_ERROR :
+ TONEMAP_SRC_NULL;
+ uint tmi = params->tmi < TONEMAP_INDEX_NB && !sound_reason_code
+ ? params->tmi : PHY_MOD_ROBO;
+ phy_mod_t mod = tmi < PHY_MOD_ROBO_NB ? tmi : PHY_MOD_TM;
+ uint rifs_tck = params->symb_nb == 0 || tmi < PHY_MOD_ROBO_NB
+ ? MAC_RIFS_DEFAULT_TCK : MAC_RIFS_SPC_ANY_TCK;
+ uint eff_rifs_tck = params->mpdu_count ? MAC_BIFS_TCK : rifs_tck;
+ /* Create an MFS. */
+ bool mfs_in_store = !!params->sppb;
+ sta_created = sta_created ||
+ (mfs_in_store && MAC_LID_IS_LLID (params->lid));
+ mfs_tx_t *mfs = utils_mfs_tx_holes_prepare (
+ params->bcast, params->mme, lid, dtei, params->mfs_seg_nb,
+ params->mfs_holes_bitmap, mfs_in_store ? tp->store : NULL);
+ mfs->last_seg_offset = 1;
+ if (params->unassociated)
+ mfs->common.unassociated = true;
+ pb_t *seg_first = mfs->head;
+ /* Setup receiver window size */
+ if (params->window_size)
+ mfs->window_size = mfs_window_size[params->window_size];
+ /* Encrypted? */
+ utils_prepare_encryption (tp, params->encrypted, !params->bcast, dtei, 0);
+ /* Setup an access. */
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 25;
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ ca_access_param_t *access = &tp->pbproc->access;
+ access->access_date = date;
+ access->duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (params->duration_symb_nb, MAC_DX417_TCK)
+ + rifs_tck + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ bool cfp = (tmi != PHY_MOD_ROBO && params->tm_max_fl_tck) || params->bbf
+ || params->cfp;
+ /* in Eoc sounds in TDMA period */
+ if (sound_reason_code != TONEMAP_SRC_NULL)
+ {
+ /* sound frame in authenticated state cco & sta */
+ cfp = true;
+ tp->config.authenticated = true;
+ sta_t * sta = mac_store_sta_get(tp->store, dtei);
+ if (sta)
+ { /* need authenticated sta to send sound frames */
+ sta->authenticated = true;
+ blk_release (sta);
+ }
+ }
+ access->prp = false;
+ access->cfp = cfp;
+ tp->pbproc->detect.beacon_detected = params->beacon_detected;
+ tp->pbproc->detect.hp10_detected = params->hp10_detected;
+ tp->pbproc->detect.hp11_detected = params->hp11_detected;
+ /* Set the current date for expiration tests. */
+ if (params->expiration_date)
+ tp->pbproc->phy->current_date = params->expiration_date
+ + TEST_PBPROC_EXPIRATION_DATE_OFFSET;
+ else
+ tp->pbproc->phy->current_date = 0;
+ if (params->remove == 1)
+ mfs->ca_state = CA_MFS_STATE_REMOVED;
+ if (params->bbf)
+ {
+ tp->pbproc->prep_mpdu.bbf = false;
+ tp->pbproc->recv_mpdu.rx_params.bbf = true;
+ tp->pbproc->recv_mpdu.rx_params.eks = (params->encrypted ?
+ tp->pbproc->config->nek_mgr.use[tp->pbproc->alloc.nek_switch]->eks
+ : MAC_EKS_CLEAR);
+ }
+ if (params->pg_sacki)
+ {
+ pbproc_sackd_t *sackd = &tp->pbproc->recv_mpdu.sackd;
+ sackd->valid = true;
+ sackd->sackt[0] = PBPROC_FC_SACKT_MIXED;
+ sackd->sackt[1] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ sackd->sackt[2] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ sackd->sackt[3] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ sackd->any_pb_crc_error = true;
+ pbproc_sacki_enc_init (&sackd->sacki_enc, 64, true);
+ /* Warning: actually crc_error was intended to be used as CRC status
+ * to acknowledge the prepared frame. Here it is used as the
+ * acknowledge data to put in the prepared frame, which is a
+ * completely different meaning! */
+ pbproc_sacki_enc_copy (&sackd->sacki_enc, params->crc_error, 64);
+ }
+ /* Prepare MPDU. */
+ pbproc_prep_mpdu (tp->pbproc, params->remove != 1 ? mfs : NULL);
+ /* Check result. */
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ if (params->remove != 1)
+ {
+ test_fail_unless (prep->stei == stei);
+ test_fail_unless (prep->dtei == dtei);
+ test_fail_unless (prep->lid == fclid);
+ test_fail_unless (prep->wack
+ == (!params->bcast || params->partial_ack));
+ test_fail_unless (prep->unassociated == params->unassociated);
+ test_fail_unless (!prep->rts_cts);
+ test_fail_unless (prep->burst_mpdu_nb == params->mpdu_count + 1);
+ test_fail_unless (prep->mpdu_count == params->mpdu_count);
+ test_fail_unless (prep->current == &prep->mpdu[prep->mpdu_count]);
+ test_fail_unless (prep->tx_date == date);
+ }
+ if (sound_reason_code != TONEMAP_SRC_NULL)
+ {
+ test_fail_unless (prep->valid);
+ test_fail_unless (prep->main_mfs == mfs);
+ test_fail_unless (prep->fc_mode == PHY_FC_MODE_AV_1);
+ test_fail_unless (prep->current->tmi == tmi);
+ test_fail_unless (prep->phy_combo_params == PHY_COMBO_PARAMS (
+ mod, tm->fecrate, PHY_PB_SIZE_520));
+ test_fail_unless (prep->gil == tm->gil);
+ test_fail_unless (prep->tonemap == tm->tmdma_desc_head);
+ test_fail_unless (prep->current->interval == interval);
+ test_fail_unless (interval == TONEMAP_INTERVAL_NB
+ || (prep->current->intervals_version
+ == intervals_version));
+ test_fail_unless (prep->sound_reason_code == sound_reason_code);
+ test_fail_unless (prep->current->pb_nb_total == 0);
+ test_fail_unless (prep->current->main_seg_nb == 0);
+ test_fail_unless (prep->main_seg_nb_reserved == 0);
+ test_fail_unless (prep->ifs_tck == eff_rifs_tck);
+ test_fail_unless (prep->flp_tck == MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (params->symb_nb, dx)
+ + eff_rifs_tck);
+ test_fail_unless (prep->bypass_aes);
+ /* Check FC. */
+ pbproc_fc_sound_t fc = prep->fc_av.sound;
+ test_fail_unless (fc.dt_av = PBPROC_FC_DT_SOUND
+ && !fc.access
+ && fc.snid == tp->snid);
+ test_fail_unless (fc.dtei == fc.direction ? dtei : stei);
+ test_fail_unless (fc.lid == fclid);
+ test_fail_unless (!fc.pbsz);
+ test_fail_unless (!fc.saf);
+ test_fail_unless (!fc.scf);
+ test_fail_unless (fc.req_tm == TONEMAP_MAX);
+ test_fail_unless (fc.fl_av ==
+ MAC_TCK_TO_FL (MAC_PAYLOAD_TCK (params->symb_nb, dx)
+ + eff_rifs_tck));
+ test_fail_unless (fc.mpdu_cnt == params->mpdu_count);
+ test_fail_unless (fc.src == sound_reason_code);
+ test_fail_unless (prep->fc10 == 0x200000);
+ /* Acknowledge preparation. */
+ pbproc_prep_mpdu_sound_ack (tp->pbproc, params->scf);
+ test_fail_unless (!prep->valid);
+ test_fail_unless (!prep->main_mfs);
+ sta_t *sta = mac_store_sta_get (tp->store, dtei);
+ dbg_assert (sta);
+ tonemaps_t *tms = sta->tx_tonemaps;
+ if (!params->scf)
+ {
+ test_fail_unless (tms->default_tmi == params->tmi);
+ }
+ else
+ {
+ if (sound_reason_code == TONEMAP_SRC_INITIAL
+ || sound_reason_code == TONEMAP_SRC_ERROR)
+ {
+ test_fail_unless (tms->default_tmi
+ == TONEMAP_INDEX_INITIAL_SOUND_COMPLETE);
+ }
+ else
+ {
+ test_fail_unless (tms->default_tmi == params->tmi);
+ }
+ if (sound_reason_code == TONEMAP_SRC_INTERVAL_UNAVAILABLE
+ || sound_reason_code == TONEMAP_SRC_INTERVAL_UNUSABLE)
+ {
+ test_fail_unless (
+ tms->intervals->interval[params->interval].tmi
+ == TONEMAP_INDEX_INTERVAL_SOUND_COMPLETE);
+ }
+ }
+ blk_release (sta);
+ }
+ else if (params->main_seg_nb_total == 0)
+ {
+ test_fail_unless (!prep->valid);
+ test_fail_unless (prep->main_mfs == NULL);
+ test_fail_unless (prep->current->main_seg_nb == 0);
+ test_fail_unless (prep->main_seg_nb_reserved == 0);
+ test_fail_unless (prep->current->pb_nb_total == 0);
+ }
+ else
+ {
+ test_fail_unless (prep->valid);
+ test_fail_unless (prep->main_mfs == mfs);
+ test_fail_unless (prep->main_mfs_cmd
+ == (params->bcast ? MFS_FSM_CMD_NOP
+ : MFS_FSM_CMD_INIT));
+ test_fail_unless (prep->main_mfs_rsp == MFS_FSM_RSP_NB);
+ test_fail_unless (prep->fc_mode == PHY_FC_MODE_AV_1);
+ test_fail_unless (prep->current->tmi == tmi);
+ test_fail_unless (prep->phy_combo_params == PHY_COMBO_PARAMS (
+ mod, tm->fecrate, PHY_PB_SIZE_520));
+ test_fail_unless (prep->gil == tm->gil);
+ test_fail_unless (prep->tonemap == tm->tmdma_desc_head);
+ test_fail_unless (prep->current->interval == interval);
+ test_fail_unless (interval == TONEMAP_INTERVAL_NB
+ || (prep->current->intervals_version
+ == intervals_version));
+ test_fail_unless (prep->sound_reason_code == sound_reason_code);
+ test_fail_unless (prep->current->main_head == seg_first);
+ uint main_seg_nb = MIN (params->main_seg_nb_total, 16u);
+ uint main_seg_nb_reserved = params->main_seg_nb_total - main_seg_nb;
+ test_fail_unless (prep->current->main_seg_nb == main_seg_nb);
+ for (seg = seg_first, i = 1; i < main_seg_nb; seg = seg->next, i++)
+ test_fail_unless (seg->header.opsf == (i == 1));
+ test_fail_unless (seg->next == seg);
+ test_fail_unless (seg->header.opsf == (i == 1));
+ test_fail_unless (prep->current->main_tail == seg);
+ test_fail_unless (prep->main_seg_nb_reserved == main_seg_nb_reserved);
+ test_fail_unless (prep->current->pb_nb_total
+ == params->main_seg_nb_total + seg_nb_pending);
+ test_fail_unless (prep->ifs_tck == eff_rifs_tck);
+ test_fail_unless (prep->flp_tck == MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (params->symb_nb, dx)
+ + eff_rifs_tck);
+ if (params->encrypted)
+ {
+ test_fail_if (prep->bypass_aes);
+ test_fail_unless (prep->nek == tp->config.nek_mgr.use[0]->nek_enc);
+ }
+ else
+ test_fail_unless (prep->bypass_aes);
+ /* Check FC. */
+ if (prep->fc_av.generic.dt_av == PBPROC_FC_DT_SOF)
+ {
+ pbproc_fc_sof_t fc = prep->fc_av.sof;
+ test_fail_unless (fc.dt_av = PBPROC_FC_DT_SOF
+ && !fc.access
+ && fc.snid == tp->snid);
+ test_fail_unless (fc.dtei == ack_dtei);
+ test_fail_unless (fc.lid == (fclid & 0x0F));
+ test_fail_unless (fc.eks == (params->encrypted ? 0 : 0x3));
+ test_fail_unless (!fc.pbsz);
+ test_fail_unless (fc.num_sym == MIN (params->symb_nb, 3u));
+ test_fail_unless (fc.tmi_av == tmi);
+ test_fail_unless (fc.fl_av ==
+ MAC_TCK_TO_FL (MAC_PAYLOAD_TCK (params->symb_nb, dx)
+ + eff_rifs_tck));
+ test_fail_unless (fc.mpdu_cnt == params->mpdu_count);
+ test_fail_unless (fc.burst_cnt == 0);
+ test_fail_unless (fc.bbf == params->cfp);
+ if (params->cfp)
+ {
+ /* TODO: remove extra 100 ยตs. */
+ int access_left_fl = (access->duration_tck - prep->flp_tck -
+ MAC_US_TO_TCK (100) - MAC_TOLERANCE_TCK)
+ / MAC_TCK_PER_FL;
+ int access_max_fl = MAC_TCK_TO_FL (
+ 2 * (MAC_PREAMBLE_TCK + MAC_FC_AV_TCK)
+ + MAC_FL_TO_TCK (MAC_MAX_FL_MIN_FL));
+ test_fail_unless (fc.mrdur_fl ==
+ MIN (access_left_fl, access_max_fl));
+ }
+ else
+ test_fail_unless (fc.mrdur_fl == 0);
+ test_fail_unless (fc.mcf == params->bcast);
+ test_fail_unless (fc.mnbf == (params->bcast && params->unassociated));
+ test_fail_unless (prep->fc10 == 0x200000);
+ }
+ else if (prep->fc_av.generic.dt_av == PBPROC_FC_DT_RSOF)
+ {
+ pbproc_fc_rsof_t fc = prep->fc_av.rsof;
+ test_fail_unless (fc.dt_av = PBPROC_FC_DT_RSOF
+ && !fc.access
+ && fc.snid == tp->snid);
+ test_fail_unless (fc.dtei == stei);
+ test_fail_unless (fc.num_sym == MIN (params->symb_nb, 3u));
+ test_fail_unless (fc.lid == fclid);
+ test_fail_unless (fc.tmi_av == tmi);
+ test_fail_unless (fc.rsof_fl_av ==
+ MAC_TCK_TO_FL (MAC_PAYLOAD_TCK (params->symb_nb, dx)
+ + eff_rifs_tck));
+ test_fail_unless (fc.bdf);
+ test_fail_unless (!fc.pbsz);
+ test_fail_unless (fc.sppb == (params->sppb ? params->sppb : 0xf));
+ test_fail_unless (prep->fc10 == 0x200000);
+ }
+ /* Chain remaining segments. */
+ if (params->remove == 2 || params->no_access_conf)
+ seg_nb_pending += params->main_seg_nb_total - main_seg_nb;
+ else
+ main_seg_nb = params->main_seg_nb_total;
+ if (params->remove == 2)
+ mfs->ca_state = CA_MFS_STATE_REMOVED;
+ if (!params->no_access_conf)
+ pbproc_prep_mpdu_chain (tp->pbproc);
+ /* Check result. */
+ test_fail_unless (prep->valid);
+ test_fail_unless (prep->main_mfs == mfs);
+ test_fail_unless (prep->current->main_head == seg_first);
+ test_fail_unless (prep->current->main_seg_nb == main_seg_nb);
+ test_fail_unless (prep->main_seg_nb_reserved ==
+ (params->no_access_conf ? main_seg_nb_reserved : 0));
+ test_fail_unless (prep->current->pb_nb_total == main_seg_nb
+ + seg_nb_pending);
+ for (seg = seg_first, i = 1; i < main_seg_nb; seg = seg->next, i++)
+ test_fail_unless (seg->header.opsf == (i == 1));
+ test_fail_unless (seg->next == seg);
+ test_fail_unless (seg->header.opsf == (i == 1));
+ test_fail_unless (prep->current->main_tail == seg);
+ test_fail_unless (mfs->last_seg_offset ==
+ (main_seg_nb == (uint) params->mfs_seg_nb ? 0 : 1));
+ /* Cancel or acknowledge preparation. */
+ if (params->remove == 3)
+ mfs->ca_state = CA_MFS_STATE_REMOVED;
+ uint acked = params->main_seg_nb_total;
+ if (!params->remove)
+ acked -= nack_count;
+ uint mfs_seg_nb_after = params->mfs_seg_nb - acked;
+ /* Expired PBs */
+ if (!params->no_access_conf)
+ {
+ if (params->expiration_date
+ >= params->main_seg_nb_total * UTILS_MFS_EXPIRATION_NTB_STEP)
+ mfs_seg_nb_after -= (params->main_seg_nb_total - acked);
+ if ((uint) params->mfs_seg_nb > params->main_seg_nb_total)
+ {
+ uint expected_expired_nb = params->expiration_date
+ > params->main_seg_nb_total * UTILS_MFS_EXPIRATION_NTB_STEP
+ + PBPROC_EXPIRATION_HYSTERESIS_OFFSET
+ ? params->expiration_date / UTILS_MFS_EXPIRATION_NTB_STEP
+ - params->main_seg_nb_total : 0;
+ uint mfs_remaining_seg_nb = params->mfs_seg_nb
+ - params->main_seg_nb_total;
+ if (expected_expired_nb > mfs_remaining_seg_nb)
+ expected_expired_nb = mfs_remaining_seg_nb;
+ if (expected_expired_nb > PBPROC_CURRENT_TX_MFS_EXPIRE_BUDGET)
+ expected_expired_nb = PBPROC_CURRENT_TX_MFS_EXPIRE_BUDGET;
+ mfs_seg_nb_after -= expected_expired_nb;
+ }
+ }
+ else
+ {
+ if (params->expiration_date
+ >= main_seg_nb * UTILS_MFS_EXPIRATION_NTB_STEP)
+ mfs_seg_nb_after -= main_seg_nb;
+ }
+ if (!params->crc)
+ {
+ if (params->sacki)
+ {
+ if (params->tmi != PHY_MOD_ROBO || params->intervals)
+ {
+ sta_t *sta = mac_store_sta_get (tp->store, dtei);
+ dbg_assert (sta);
+ tonemaps_t *tms = sta->tx_tonemaps;
+ if (params->tmi_update)
+ tms->default_tmi = params->tmi_update;
+ pbproc_prep_mpdu_ack_uniform (
+ tp->pbproc, prep->mpdu_count, params->sacki);
+ test_fail_unless (
+ tms->default_tmi == params->tmi_sacki);
+ if (params->intervals)
+ test_fail_unless (
+ tms->intervals->interval[params->interval].tmi
+ == params->interval_tmi_sacki);
+ blk_release (sta);
+ }
+ else
+ pbproc_prep_mpdu_ack_uniform (
+ tp->pbproc, prep->mpdu_count, params->sacki);
+ }
+ else if (!params->all_ok)
+ pbproc_prep_mpdu_cancel (tp->pbproc, prep->mpdu_count);
+ else
+ pbproc_prep_mpdu_ack_all (tp->pbproc, prep->mpdu_count);
+ }
+ else
+ {
+ if (!params->encoded_sack)
+ {
+ pbproc_sacki_dec_t sacki_dec;
+ pbproc_sacki_dec_init (&sacki_dec, params->crc_error[0],
+ params->crc_error[1],
+ params->crc_error[2] & 0xff,
+ PREP_MPDU_TEST_CRC_BITMAP_SIZE);
+ pbproc_prep_mpdu_ack_bitmap (tp->pbproc, prep->mpdu_count,
+ &sacki_dec);
+ uint eaten = MIN (main_seg_nb + seg_nb_pending,
+ PREP_MPDU_TEST_CRC_BITMAP_SIZE);
+ test_fail_unless (sacki_dec.sil
+ == PREP_MPDU_TEST_CRC_BITMAP_SIZE - eaten);
+ }
+ else
+ {
+ pbproc_sacki_dec_t sacki_dec;
+ pbproc_sacki_dec_init (
+ &sacki_dec, params->encoded_sack & 0xffffffff,
+ (params->encoded_sack >> 32) & 0xffffffff, 0, 64);
+ pbproc_prep_mpdu_ack_encoded (tp->pbproc, prep->mpdu_count,
+ &sacki_dec);
+ test_fail_unless (sacki_dec.sil
+ == 64 - params->encoded_sack_length);
+ }
+ }
+ /* Set MFS_RSP and MFS_CMD to allow test of MFS fsm state in case of
+ * expiration. */
+ mfs->fsm_state = MFS_FSM_CMD_IN_SYNC;
+ tp->pbproc->prep_mpdu.main_mfs_cmd = MFS_FSM_CMD_IN_SYNC;
+ tp->pbproc->prep_mpdu.main_mfs_rsp = MFS_FSM_RSP_ACK;
+ pbproc_prep_mpdu_commit_burst (tp->pbproc);
+ u16 expected_holes_nb = 0;
+ if (mfs->ca_state != CA_MFS_STATE_REMOVED && mfs->seg_nb)
+ {
+ pb_t *mfs_seg;
+ for (mfs_seg = mfs->head; mfs_seg != mfs->tail; mfs_seg = mfs_seg->next)
+ expected_holes_nb += (mfs_seg->next->header.ssn - mfs_seg->header.ssn - 1);
+ expected_holes_nb += (mfs->next_ssn - mfs->tail->header.ssn - 1);
+ }
+ /* Test update of number of holes in the MFS. */
+ test_fail_unless (mfs->holes_seg_nb == expected_holes_nb);
+ /* Test update of MFS FSM state in case of expiration. */
+ if (params->mfs_fsm_state_test)
+ test_fail_unless (mfs->fsm_state == params->expected_mfs_fsm_state);
+ /* Call DSR if requested. */
+ if (tp->pbproc->fsm.schedule_deferred)
+ pbproc_fsm_handle_deferred (tp->pbproc);
+ /* Check result. */
+ test_fail_unless (mfs->seg_nb == (int) mfs_seg_nb_after);
+ if (!params->mfs_holes_bitmap && !params->expiration_date)
+ {
+ seg = mfs->head;
+ for (i = 0; i < (uint) params->mfs_seg_nb; i++)
+ {
+ bool bad_crc = !params->crc ? !params->all_ok
+ : (params->crc_error[i / 32] & (1u << (i % 32))) != 0;
+ if (i >= main_seg_nb || (!params->remove && bad_crc))
+ {
+ test_fail_unless (seg->header.ssn == i
+ && seg->header.mfbo == 0
+ && seg->header.vpbf == true
+ && seg->header.mmqf == params->mme
+ && seg->header.mfbf == false
+ && seg->header.opsf == (i == 0)
+ && seg->header.rsvd == 0);
+ seg = seg->next;
+ }
+ }
+ }
+ }
+ /* Information stored in frame control */
+ if (params->pg_sacki)
+ {
+ dbg_assert (params->crc_error[2] == 0);
+ uint sil;
+ u32 sackt0, sacki0, sacki1;
+ if (prep->fc_av.generic.dt_av == PBPROC_FC_DT_SOUND)
+ {
+ sil = PBPROC_FC_SACKI_EOC_SOUND_SIZE;
+ pbproc_fc_sound_t *fc = &prep->fc_av.sound;
+ sackt0 = fc->sackt0;
+ sacki0 = fc->sacki0 | fc->sacki1 << PBPROC_FC_SACKI_EOC_SOUND_LEFT;
+ sacki1 = fc->sacki1 >> (32 - PBPROC_FC_SACKI_EOC_SOUND_LEFT);
+ }
+ else if (prep->fc_av.generic.dt_av == PBPROC_FC_DT_SOF)
+ {
+ sil = PBPROC_FC_SACKI_EOC_SOF_SIZE;
+ pbproc_fc_sof_t *fc = &prep->fc_av.sof;
+ sackt0 = fc->sackt0;
+ sacki0 = fc->sacki0;
+ sacki1 = fc->sacki1;
+ }
+ else if (prep->fc_av.generic.dt_av == PBPROC_FC_DT_RSOF)
+ {
+ sil = PBPROC_FC_SACKI_EOC_RSOF_SIZE;
+ pbproc_fc_rsof_t *fc = &prep->fc_av.rsof;
+ sackt0 = fc->sackt0;
+ sacki0 = fc->sacki0;
+ sacki1 = fc->sacki1;
+ }
+ else
+ dbg_assert_default ();
+ test_fail_unless (sackt0 == PBPROC_FC_SACKT_MIXED);
+ test_fail_unless (sacki0 == params->crc_error[0]);
+ test_fail_unless ((sacki1 & BITS_ONES (sil - 32))
+ == (params->crc_error[1] & BITS_ONES (sil - 32)));
+ }
+ /* Cleanup. */
+ if (mfs_in_store)
+ mac_store_mfs_remove (tp->store, PARENT_OF (mfs_t, tx, mfs));
+ utils_mfs_tx_cleanup (mfs);
+ if (sta_created)
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+ pbproc_set_chandata_conf (tp->pbproc, NULL, 0, false);
+ tp->pbproc->detect.beacon_detected = false;
+ tp->pbproc->detect.hp10_detected = false;
+ tp->pbproc->detect.hp11_detected = false;
+ tp->config.authenticated = false;
+ tp->config.partial_ack_tei_default = false;
+}
+
+void
+prep_mpdu_basic_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic");
+ test_pbproc_init (&tp);
+ test_begin (t, "robo unicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1);
+ } test_end;
+ test_begin (t, "cfp limited reverse")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 28,
+ .symb_nb = 19, .main_seg_nb_total = 1, .cfp = true);
+ } test_end;
+ test_begin (t, "cfp max reverse")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 1, .duration_symb_nb = 1000,
+ .symb_nb = 19, .main_seg_nb_total = 1, .cfp = true);
+ } test_end;
+ test_begin (t, "rsof robo unicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1, .bbf = true);
+ } test_end;
+ test_begin (t, "robo unicast mme limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mme = true, .mfs_seg_nb = 30,
+ .duration_symb_nb = 25, .symb_nb = 19,
+ .main_seg_nb_total = 1);
+ } test_end;
+ test_begin (t, "robo unicast data limit dur max")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 38, .main_seg_nb_total = 2);
+ } test_end;
+ test_begin (t, "robo unicast data limit seg")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19, .main_seg_nb_total = 1);
+ } test_end;
+ test_begin (t, "robo unicast data limit no seg")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 0, .duration_symb_nb = 95,
+ .main_seg_nb_total = 0);
+ } test_end;
+ test_begin (t, "robo unicast data limit dur zero")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 16,
+ .symb_nb = 0, .main_seg_nb_total = 0);
+ } test_end;
+ test_begin (t, "robo multicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .bcast = true);
+ } test_end;
+ test_begin (t, "robo multicast data limit dur partial ack")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .bcast = true, .partial_ack = true);
+ } test_end;
+ test_begin (t, "robo multicast data limit dur max")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .bcast = true);
+ } test_end;
+ test_begin (t, "robo unassociated unicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .unassociated = true);
+ } test_end;
+ test_begin (t, "robo unassociated multicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .bcast = true, .unassociated = true);
+ } test_end;
+ test_begin (t, "hs-robo unicast data limit seg")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 95,
+ .symb_nb = 30, .main_seg_nb_total = 3,
+ .tmi = PHY_MOD_HS_ROBO);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 16,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "tm unicast data limit seg with null")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 13, .duration_symb_nb = 8,
+ .symb_nb = 8, .main_seg_nb_total = 12,
+ .seg_nb_pending = 0,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur bis")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 13, .duration_symb_nb = 8,
+ .symb_nb = 8, .main_seg_nb_total = 12,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ /* Bursting is not supported yet */
+ /*
+ test_begin (t, "tm unicast data limit dur tm")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 60, .duration_symb_nb = 91,
+ .symb_nb = 30, .main_seg_nb_total = 49,
+ .tmi = 5, .tm_mod = 10,
+ .tm_max_fl_tck = MAC_PAYLOAD_TCK (30, MAC_DX417_TCK)
+ + MAC_RIFS_SPC_ANY_TCK,
+ .mpdu_count = 1);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur max")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 100, .duration_symb_nb = 100,
+ .symb_nb = 50, .main_seg_nb_total = 83,
+ .tmi = 5, .tm_mod = 10,
+ .mpdu_count = 1);
+ } test_end;
+ */
+ test_begin (t, "tm unicast data limit dur zero")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 0,
+ .symb_nb = 0, .main_seg_nb_total = 0,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur one")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 1,
+ .symb_nb = 1, .main_seg_nb_total = 1,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur two")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 2,
+ .symb_nb = 2, .main_seg_nb_total = 2,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "robo unicast data limit dur encrypted")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .encrypted = true);
+ } test_end;
+ test_begin (t, "robo multicast data limit dur encrypted")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .bcast = true, .encrypted = true);
+ } test_end;
+ test_begin (t, "hs-robo unicast data limit dur remove 2")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .remove = 2, .tmi = PHY_MOD_HS_ROBO);
+ } test_end;
+ test_begin (t, "hs-robo unicast data limit dur remove 3")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .remove = 3, .tmi = PHY_MOD_HS_ROBO);
+ } test_end;
+ test_begin (t, "no sound for mme")
+ {
+ prep_mpdu_test (t, &tp, 0, .mme = true, .mfs_seg_nb = 30,
+ .duration_symb_nb = 25, .symb_nb = 19,
+ .main_seg_nb_total = 1,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ } test_end;
+ test_begin (t, "sound initial")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .tmi = TONEMAP_INDEX_INITIAL_START, .scf = true);
+ } test_end;
+ test_begin (t, "sound error")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .tmi = TONEMAP_INDEX_INITIAL_ERROR);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .tmi = TONEMAP_INDEX_INITIAL_ERROR, .scf = true);
+ } test_end;
+ test_begin (t, "sound complete")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .tmi = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE);
+ } test_end;
+ test_begin (t, "sound tmi")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 19, .tmi = 6, .sound_reason_code = 6);
+ } test_end;
+ test_begin (t, "beacon detection")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .beacon_detected = true);
+ } test_end;
+ test_begin (t, "hp detection")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .hp10_detected = true);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .hp11_detected = true);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .hp10_detected = true, .hp11_detected = true);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_ack_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "ack");
+ test_pbproc_init (&tp);
+ test_begin (t, "acked all")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .all_ok = true, .tmi = PHY_MOD_HS_ROBO);
+ } test_end;
+ test_begin (t, "acked bitmap")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc = true, .crc_error = { 0 },
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc = true, .crc_error = { 0x15 },
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 41, .duration_symb_nb = 30,
+ .symb_nb = 25, .main_seg_nb_total = 41,
+ .crc = true, .crc_error = { 0x0fa5c03a, 0x15 },
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked bitmap overflow")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 81, .duration_symb_nb = 55,
+ .symb_nb = 49, .main_seg_nb_total = 81,
+ .crc = true,
+ .crc_error = { 0xaa55aa55, 0x5a5a5a5a, 0x1ff5a },
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked bitmap with null")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 13, .duration_symb_nb = 9,
+ .symb_nb = 9, .main_seg_nb_total = 13,
+ .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x1a5a },
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc = true, .crc_error = { 0x15 },
+ .encoded_sack = 0x6f,
+ .encoded_sack_length = 9,
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 41, .duration_symb_nb = 30,
+ .symb_nb = 25, .main_seg_nb_total = 41,
+ .crc = true, .crc_error = { 0x0fa5c03a, 0x15 },
+ .encoded_sack = 0x066bffc9fd3f9ull,
+ .encoded_sack_length = 49,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap overflow")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 32, .duration_symb_nb = 30,
+ .symb_nb = 20, .main_seg_nb_total = 32,
+ .crc = true, .crc_error = { 0xf9ffffff },
+ .encoded_sack = 0xbfffffffffffffffull,
+ .encoded_sack_length = 64,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap with null extra symbol")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 3,
+ .symb_nb = 3, .main_seg_nb_total = 3,
+ .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x4 },
+ .encoded_sack = 0x5, .encoded_sack_length = 4,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap with null same symbol")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 3,
+ .symb_nb = 3, .main_seg_nb_total = 3,
+ .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x0 },
+ .encoded_sack = 0x0, .encoded_sack_length = 1,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap with null extra symbol bad")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 3,
+ .symb_nb = 3, .main_seg_nb_total = 3,
+ .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x4 },
+ .encoded_sack = 0x1d, .encoded_sack_length = 6,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap with null same symbol bad")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 3,
+ .symb_nb = 3, .main_seg_nb_total = 3,
+ .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x0 },
+ .encoded_sack = 0x7, .encoded_sack_length = 4,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked encoded bitmap with null overflow")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 29,
+ .symb_nb = 19, .main_seg_nb_total = 30,
+ .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x39ffffff },
+ .encoded_sack = 0xbfffffffffffffffull,
+ .encoded_sack_length = 64,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked uniform basic")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .all_ok = true,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_ALL_OK);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .all_ok = false,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_NOT_AVAILABLE);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .all_ok = false,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_NEK_ERROR);
+ } test_end;
+ test_begin (t, "acked uniform tmi error no sta")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .tmi = PHY_MOD_ROBO,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .tmi = PHY_MOD_ROBO,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_RESTART);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .tmi = PHY_MOD_ROBO,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_RESTART);
+ } test_end;
+ test_begin (t, "acked uniform tmi error robo")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 95,
+ .symb_nb = 30, .main_seg_nb_total = 3,
+ .tmi = PHY_MOD_HS_ROBO,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO,
+ .tmi_sacki = PHY_MOD_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 95,
+ .symb_nb = 30, .main_seg_nb_total = 3,
+ .tmi = PHY_MOD_HS_ROBO,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 95,
+ .symb_nb = 30, .main_seg_nb_total = 3,
+ .tmi = PHY_MOD_HS_ROBO,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_START);
+ } test_end;
+ test_begin (t, "acked uniform tmi error tm")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO,
+ .tmi_sacki = PHY_MOD_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_START);
+ } test_end;
+ test_begin (t, "acked uniform tmi error ce update")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6,
+ .tmi_update = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6,
+ .tmi_update = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6,
+ .tmi_update = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_SOUND_COMPLETE);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_intervals_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "intervals");
+ test_pbproc_init (&tp);
+ utils_interval_t intervals[] =
+ {
+ { 100000, TONEMAP_INDEX_INTERVAL_UNAVAILABLE, 0 },
+ { 200000, TONEMAP_INDEX_INTERVAL_UNUSABLE, 0 },
+ { 300000, 6, 0 },
+ { 400000, TONEMAP_INDEX_INTERVAL_SOUND_COMPLETE, 0 },
+ { 0, 0, 0 }
+ };
+ test_begin (t, "interval tmi")
+ {
+ prep_mpdu_test (t, &tp, 210000,
+ .mfs_seg_nb = 14, .duration_symb_nb = 9,
+ .symb_nb = 9, .main_seg_nb_total = 14,
+ .tmi = 6, .tm_mod = 10,
+ .intervals = intervals, .interval = 2);
+ } test_end;
+ test_begin (t, "no interval default tmi")
+ {
+ prep_mpdu_test (t, &tp, 910000,
+ .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .intervals = intervals,
+ .interval = TONEMAP_INTERVAL_NB);
+ } test_end;
+ test_begin (t, "unavailable interval")
+ {
+ prep_mpdu_test (t, &tp, 10000,
+ .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .intervals = intervals, .interval = 0,
+ .sound_reason_code = TONEMAP_SRC_INTERVAL_UNAVAILABLE);
+ prep_mpdu_test (t, &tp, 10000,
+ .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .intervals = intervals, .interval = 0,
+ .sound_reason_code = TONEMAP_SRC_INTERVAL_UNAVAILABLE,
+ .scf = true);
+ } test_end;
+ test_begin (t, "unusable interval")
+ {
+ prep_mpdu_test (t, &tp, 110000,
+ .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .intervals = intervals, .interval = 1,
+ .sound_reason_code = TONEMAP_SRC_INTERVAL_UNUSABLE);
+ prep_mpdu_test (t, &tp, 110000,
+ .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .intervals = intervals, .interval = 1,
+ .sound_reason_code = TONEMAP_SRC_INTERVAL_UNUSABLE,
+ .scf = true);
+ } test_end;
+ test_begin (t, "sound complete interval")
+ {
+ prep_mpdu_test (t, &tp, 310000,
+ .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .intervals = intervals, .interval = 3);
+ } test_end;
+ test_begin (t, "acked uniform tmi error")
+ {
+ prep_mpdu_test (t, &tp, 210000,
+ .mfs_seg_nb = 14, .duration_symb_nb = 9,
+ .symb_nb = 9, .main_seg_nb_total = 14,
+ .tmi = 6, .tm_mod = 10,
+ .intervals = intervals, .interval = 2,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO,
+ .tmi_sacki = PHY_MOD_ROBO, .interval_tmi_sacki =
+ TONEMAP_INDEX_INTERVAL_UNAVAILABLE);
+ prep_mpdu_test (t, &tp, 210000,
+ .mfs_seg_nb = 14, .duration_symb_nb = 9,
+ .symb_nb = 9, .main_seg_nb_total = 14,
+ .tmi = 6, .tm_mod = 10,
+ .intervals = intervals, .interval = 2,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_RESTART,
+ .tmi_sacki = PHY_MOD_ROBO, .interval_tmi_sacki =
+ TONEMAP_INDEX_INTERVAL_UNAVAILABLE);
+ } test_end;
+ test_begin (t, "acked uniform tmi error restart")
+ {
+ prep_mpdu_test (t, &tp, 210000,
+ .mfs_seg_nb = 14, .duration_symb_nb = 9,
+ .symb_nb = 9, .main_seg_nb_total = 14,
+ .tmi = 6, .tm_mod = 10,
+ .intervals = intervals, .interval = 2,
+ .sacki = PBPROC_FC_SACKI_UNIFORM_TMI_RESTART,
+ .tmi_sacki = TONEMAP_INDEX_INITIAL_START,
+ .interval_tmi_sacki = 6);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_expiration_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "expiration");
+ test_pbproc_init (&tp);
+ test_begin (t, "expiration on sack return")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .duration_symb_nb = 50,
+ .symb_nb = 25, .main_seg_nb_total = 40, .seg_nb_pending = 1,
+ .expiration_date = 20 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .duration_symb_nb = 50,
+ .symb_nb = 25, .main_seg_nb_total = 40, .seg_nb_pending = 1,
+ .expiration_date = 50 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .duration_symb_nb = 50,
+ .symb_nb = 25, .main_seg_nb_total = 40, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x0fa5c03a, 0x15 },
+ .expiration_date = 50 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "expiration on chaining")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 200, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 83, .seg_nb_pending = 0,
+ .expiration_date = 80 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 200, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 83, .seg_nb_pending = 0,
+ .expiration_date = 150 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 200, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 83, .seg_nb_pending = 0,
+ .expiration_date = 250 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 200, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 83, .seg_nb_pending = 0,
+ .crc = true, .crc_error = { 0x0fa5c03a, 0x15, 0x7ff00 },
+ .expiration_date = 150 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "expiration with cancel")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .duration_symb_nb = 50,
+ .symb_nb = 25, .main_seg_nb_total = 40, .seg_nb_pending = 1,
+ .expiration_date = 3 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .no_access_conf = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .duration_symb_nb = 50,
+ .symb_nb = 25, .main_seg_nb_total = 40, .seg_nb_pending = 1,
+ .expiration_date = 50 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .no_access_conf = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .duration_symb_nb = 50,
+ .symb_nb = 25, .main_seg_nb_total = 40, .seg_nb_pending = 1,
+ .expiration_date = 200 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .no_access_conf = true, .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_window_size_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "window size");
+ test_pbproc_init (&tp);
+ test_begin (t, "no holes no ack")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .mfs_holes_bitmap = 0,
+ .window_size = MFS_WINDOW_SIZE_32, .duration_symb_nb = 50,
+ .symb_nb = 20, .main_seg_nb_total = 32, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 20, .mfs_holes_bitmap = 0,
+ .window_size = MFS_WINDOW_SIZE_32, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "holes no ack")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x55,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 21, .seg_nb_pending = 0,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 16, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 10, .main_seg_nb_total = 16, .seg_nb_pending = 0,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "holes ack all")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .all_ok = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x000100AA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 12, .main_seg_nb_total = 19, .seg_nb_pending = 0,
+ .all_ok = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x100000AA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 12, .main_seg_nb_total = 19, .seg_nb_pending = 0,
+ .all_ok = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x200000AA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 12, .main_seg_nb_total = 19, .seg_nb_pending = 0,
+ .all_ok = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x300000AA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 12, .main_seg_nb_total = 18, .seg_nb_pending = 1,
+ .all_ok = true, .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "holes ack bitmap")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x00021084 },
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x100000AA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 12, .main_seg_nb_total = 19, .seg_nb_pending = 0,
+ .crc = true, .crc_error = { 0x00021084 },
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x000C4261 },
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x000C4000 },
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "expiration")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0x200000AA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 12, .main_seg_nb_total = 19, .seg_nb_pending = 0,
+ .expiration_date = 22 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .all_ok = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x00021084 },
+ .expiration_date = 15 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x00021084 },
+ .expiration_date = 22 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .tmi = 5, .tm_mod = 10);
+ /* No fsm state testing */
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x00021084 },
+ .expiration_date = 50 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .expected_mfs_fsm_state = MFS_FSM_CMD_RE_SYNC,
+ .mfs_fsm_state_test = false, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 200, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .crc = true, .crc_error = { 0x00021084 },
+ .expiration_date = 100 * UTILS_MFS_EXPIRATION_NTB_STEP,
+ .expected_mfs_fsm_state = MFS_FSM_CMD_RE_SYNC,
+ .mfs_fsm_state_test = false, .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "no access conf")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 40, .mfs_holes_bitmap = 0,
+ .window_size = MFS_WINDOW_SIZE_32, .duration_symb_nb = 50,
+ .symb_nb = 20, .main_seg_nb_total = 32, .seg_nb_pending = 0,
+ .no_access_conf = true, .tmi = 5, .tm_mod = 10);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .mfs_holes_bitmap = 0xAA,
+ .window_size = MFS_WINDOW_SIZE_24, .duration_symb_nb = 50,
+ .symb_nb = 13, .main_seg_nb_total = 20, .seg_nb_pending = 1,
+ .no_access_conf = true, .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_beacon_test (test_t t, test_pbproc_t *tp, u32 date, bool prepared,
+ uint duration_symb_nb, uint symb_nb)
+{
+ test_within (t);
+ dbg_assert (tp);
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ const u32 beacon_period_start_date = date / beacon_tck * beacon_tck;
+ /* Create a beacon MFS. */
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (true, false, MAC_LID_SPC_CENTRAL,
+ MAC_TEI_BCAST, 0);
+ mfs->cfp = true;
+ mfs->beacon = true;
+ pb_t *seg = NULL;
+ pbproc_tx_beacon_params_t params =
+ { { 0x0123, 0x4242, 0xabab, 0x5555 }, NULL };
+ if (prepared)
+ {
+ pb_beacon_t *pb = PARENT_OF (pb_beacon_t, blk, blk_alloc_desc ());
+ seg = (pb_t *) pb;
+ params.bpsto = pb->data + 123;
+ pbproc_mfs_beacon_prepare (tp->pbproc, mfs, pb, &params);
+ }
+ /* To be cleared by pbproc_prep_beacon. */
+ tp->pbproc->prep_mpdu.bbf = true;
+ /* Setup an access. */
+ test_pbproc_alloc (tp, false, beacon_period_start_date);
+ ca_access_param_t *access = &tp->pbproc->access;
+ access->access_date = date;
+ access->duration_tck = MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_PAYLOAD_TCK (duration_symb_nb, MAC_DX567_TCK)
+ + MAC_B2BIFS_TCK;
+ access->prp = false;
+ access->cfp = true;
+ /* Prepare beacon. */
+ pbproc_prep_beacon (tp->pbproc, mfs);
+ /* Check result. */
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ test_fail_unless (prep->stei == tp->config.tei);
+ test_fail_unless (prep->dtei == MAC_TEI_BCAST);
+ test_fail_unless (prep->lid == MAC_LID_NONE);
+ test_fail_unless (!prep->wack);
+ test_fail_unless (!prep->unassociated);
+ test_fail_unless (!prep->rts_cts);
+ test_fail_unless (prep->burst_mpdu_nb == 1);
+ test_fail_unless (prep->mpdu_count == 0);
+ test_fail_unless (prep->current == &prep->mpdu[0]);
+ if (symb_nb)
+ {
+ test_fail_unless (prep->valid);
+ test_fail_unless (prep->main_mfs == mfs);
+ test_fail_unless (prep->tx_date == date);
+ test_fail_unless (prep->fc_mode == PHY_FC_MODE_AV_1);
+ test_fail_unless (prep->sound_reason_code == TONEMAP_SRC_NULL);
+ test_fail_unless (prep->mpdu[0].tmi == PHY_MOD_MINI_ROBO);
+ test_fail_unless (prep->phy_combo_params == PHY_COMBO_PARAMS (
+ PHY_MOD_MINI_ROBO, PHY_FEC_RATE_1_2, PHY_PB_SIZE_136));
+ test_fail_unless (prep->gil == PHY_GIL_567);
+ test_fail_unless (prep->tonemap == NULL);
+ test_fail_unless (prep->ifs_tck == MAC_B2BIFS_TCK);
+ test_fail_unless (prep->flp_tck == MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX567_TCK)
+ + MAC_B2BIFS_TCK);
+ test_fail_unless (prep->mpdu[0].main_head == seg);
+ test_fail_unless (prep->mpdu[0].main_tail == seg);
+ test_fail_unless (prep->mpdu[0].main_seg_nb == 1);
+ test_fail_unless (prep->main_seg_nb_reserved == 0);
+ test_fail_unless (prep->main_mfs_cmd == MFS_FSM_CMD_NOP);
+ test_fail_unless (prep->main_mfs_rsp == MFS_FSM_RSP_NB);
+ test_fail_unless (prep->mpdu[0].pb_nb_total == 1);
+ test_fail_unless (prep->bypass_aes);
+ test_fail_unless (!prep->bbf);
+ /* Check FC. */
+ pbproc_fc_beacon_t *fc = &prep->fc_av.beacon;
+ test_fail_unless (fc->dt_av == PBPROC_FC_DT_BEACON);
+ test_fail_unless (fc->access == false
+ && fc->snid == tp->snid);
+ uint bts = fc->bts_msb8 << 24 | fc->bts_lsb24;
+ uint bto[4] = {
+ fc->bto0,
+ fc->bto1_msb8 << 8 | fc->bto1_lsb8,
+ fc->bto2,
+ fc->bto3_msb8 << 8 | fc->bto3_lsb8
+ };
+ test_fail_unless (bts == date + tp->config.ntb_offset_tck);
+ test_fail_unless (bto[0] == params.bto[0]);
+ test_fail_unless (bto[1] == params.bto[1]);
+ test_fail_unless (bto[2] == params.bto[2]);
+ test_fail_unless (bto[3] == params.bto[3]);
+ test_fail_unless (prep->fc10 == 0x2f00);
+ /* Check payload (BPSTO). */
+ uint bpsto = params.bpsto[0]
+ | params.bpsto[1] << 8
+ | params.bpsto[2] << 16;
+ test_fail_unless (bpsto == date - beacon_period_start_date);
+ /* Cancel preparation. */
+ pbproc_prep_mpdu_cancel_burst (tp->pbproc);
+ /* Check result. */
+ test_fail_unless (mfs->seg_nb == 1);
+ test_fail_unless (mfs->head == seg);
+ test_fail_unless (mfs->tail == seg);
+ test_fail_unless (!mfs->holes_seg_nb);
+ }
+ else
+ {
+ test_fail_unless (!prep->valid);
+ test_fail_unless (prep->main_mfs == NULL);
+ test_fail_unless (prep->mpdu[0].main_seg_nb == 0);
+ test_fail_unless (prep->main_seg_nb_reserved == 0);
+ test_fail_unless (prep->mpdu[0].pb_nb_total == 0);
+ /* Check MFS. */
+ if (prepared)
+ {
+ test_fail_unless (mfs->seg_nb == 1);
+ test_fail_unless (mfs->head == seg);
+ test_fail_unless (mfs->tail == seg);
+ }
+ else
+ {
+ test_fail_unless (mfs->seg_nb == 0);
+ test_fail_unless (mfs->head == NULL);
+ }
+ }
+ /* Cleanup. */
+ utils_mfs_tx_cleanup (mfs);
+}
+
+void
+prep_mpdu_beacon_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "beacon");
+ test_pbproc_init (&tp);
+ test_begin (t, "valid")
+ {
+ prep_beacon_test (t, &tp, 123456, true, 6, 6);
+ } test_end;
+ test_begin (t, "unvalid")
+ {
+ prep_beacon_test (t, &tp, 54321, true, 5, 0);
+ } test_end;
+ test_begin (t, "no seg")
+ {
+ prep_beacon_test (t, &tp, 54321, false, 6, 0);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_fsm_test (test_t t, test_pbproc_t *tp, mfs_fsm_cmd_t cmd,
+ mfs_fsm_rsp_t rsp, bool release, bool empty,
+ bool opsf, mfs_fsm_cmd_t expect_cmd, bool expect_hold)
+{
+ test_within (t);
+ /* Create an MFS. */
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, 2, 2, empty ? 0 : 1);
+ if (!empty && opsf)
+ mfs->head->header.opsf = true;
+ mfs->fsm_state = release ? MFS_FSM_CMD_RELEASE : cmd;
+ /* Prepare MPDU. */
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ prep->valid = true;
+ prep->main_mfs = mfs;
+ blk_addref (mfs);
+ pb_t *pb = PARENT_OF (pb_t, blk, blk_alloc_desc ());
+ prep->burst_mpdu_nb = 1;
+ prep->mpdu[0].main_head = prep->mpdu[0].main_tail = pb;
+ prep->mpdu[0].main_seg_nb = 1;
+ prep->main_seg_nb_reserved = 0;
+ prep->mpdu[0].pb_nb_total = 1;
+ prep->main_mfs_cmd = cmd;
+ /* Test. */
+ prep->main_mfs_rsp = rsp;
+ pbproc_prep_mpdu_ack_all_burst (tp->pbproc);
+ /* Call DSR if requested. */
+ if (tp->pbproc->fsm.schedule_deferred)
+ pbproc_fsm_handle_deferred (tp->pbproc);
+ /* Check result. */
+ test_fail_unless (mfs->fsm_state == expect_cmd);
+ test_fail_unless (
+ (expect_hold && mfs->ca_state == CA_MFS_STATE_HELD)
+ || (!expect_hold && mfs->ca_state == CA_MFS_STATE_UNKNOWN));
+ /* Cleanup. */
+ utils_mfs_tx_cleanup (mfs);
+ prep->main_mfs = NULL;
+ prep->valid = false;
+}
+
+void
+prep_mpdu_fsm_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "fsm");
+ test_pbproc_init (&tp);
+ test_begin (t, "unicast init ack")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_ACK,
+ false, true, false, MFS_FSM_CMD_IN_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_ACK,
+ false, false, false, MFS_FSM_CMD_IN_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_ACK,
+ false, false, true, MFS_FSM_CMD_IN_SYNC, false);
+ } test_end;
+ test_begin (t, "unicast init nack (invalid)")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_NACK,
+ false, true, false, MFS_FSM_CMD_INIT, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_NACK,
+ false, false, false, MFS_FSM_CMD_INIT, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_NACK,
+ false, false, true, MFS_FSM_CMD_INIT, false);
+ } test_end;
+ test_begin (t, "unicast in_sync ack")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_ACK,
+ false, true, false, MFS_FSM_CMD_IN_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_ACK,
+ false, false, false, MFS_FSM_CMD_IN_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_ACK,
+ false, false, true, MFS_FSM_CMD_IN_SYNC, false);
+ } test_end;
+ test_begin (t, "unicast in_sync nack")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_NACK,
+ false, true, false, MFS_FSM_CMD_RE_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_NACK,
+ false, false, false, MFS_FSM_CMD_RE_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_NACK,
+ false, false, true, MFS_FSM_CMD_RE_SYNC, false);
+ } test_end;
+ test_begin (t, "unicast re_sync ack")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_ACK,
+ false, true, false, MFS_FSM_CMD_IN_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_ACK,
+ false, false, false, MFS_FSM_CMD_IN_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_ACK,
+ false, false, true, MFS_FSM_CMD_RE_SYNC, false);
+ } test_end;
+ test_begin (t, "unicast re_sync nack")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_NACK,
+ false, true, false, MFS_FSM_CMD_RE_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_NACK,
+ false, false, false, MFS_FSM_CMD_RE_SYNC, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_NACK,
+ false, false, true, MFS_FSM_CMD_RE_SYNC, false);
+ } test_end;
+ test_begin (t, "multicast ack")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_ACK,
+ false, true, false, MFS_FSM_CMD_NOP, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_ACK,
+ false, false, false, MFS_FSM_CMD_NOP, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_ACK,
+ false, false, true, MFS_FSM_CMD_NOP, false);
+ } test_end;
+ test_begin (t, "multicast nack (invalid)")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_NACK,
+ false, true, false, MFS_FSM_CMD_NOP, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_NACK,
+ false, false, false, MFS_FSM_CMD_NOP, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_NACK,
+ false, false, true, MFS_FSM_CMD_NOP, false);
+ } test_end;
+ test_begin (t, "hold")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_HOLD,
+ false, true, false, MFS_FSM_CMD_INIT, true);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_HOLD,
+ false, true, false, MFS_FSM_CMD_IN_SYNC, true);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_HOLD,
+ false, true, false, MFS_FSM_CMD_RE_SYNC, true);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_HOLD,
+ false, true, false, MFS_FSM_CMD_NOP, false);
+ } test_end;
+ test_begin (t, "released")
+ {
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_ACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_ACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_ACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_ACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_INIT, MFS_FSM_RSP_NACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_IN_SYNC, MFS_FSM_RSP_NACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_RE_SYNC, MFS_FSM_RSP_NACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ prep_mpdu_fsm_test (t, &tp, MFS_FSM_CMD_NOP, MFS_FSM_RSP_NACK,
+ true, true, false, MFS_FSM_CMD_RELEASE, false);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_basic_rsof_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic rsof");
+ test_pbproc_init (&tp);
+ test_begin (t, "robo unicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1, .bbf = true);
+ } test_end;
+ test_begin (t, "robo unicast mme limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mme = true, .mfs_seg_nb = 30,
+ .duration_symb_nb = 25, .symb_nb = 19,
+ .main_seg_nb_total = 1, .bbf = true);
+ } test_end;
+ test_begin (t, "robo unicast data limit dur max")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 95,
+ .symb_nb = 38, .main_seg_nb_total = 2, .bbf = true);
+ } test_end;
+ test_begin (t, "robo unicast data limit seg")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 1, .duration_symb_nb = 95,
+ .symb_nb = 19, .main_seg_nb_total = 1, .bbf = true);
+ } test_end;
+ test_begin (t, "hs-robo unicast data limit seg")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 3, .duration_symb_nb = 95,
+ .symb_nb = 30, .main_seg_nb_total = 3,
+ .tmi = PHY_MOD_HS_ROBO, .bbf = true);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 10,
+ .tmi = 5, .tm_mod = 6, .bbf = true);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 10,
+ .symb_nb = 10, .main_seg_nb_total = 16,
+ .tmi = 5, .tm_mod = 10, .bbf = true);
+ } test_end;
+ test_begin (t, "tm unicast data limit seg with null")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 13, .duration_symb_nb = 8,
+ .symb_nb = 8, .main_seg_nb_total = 12,
+ .seg_nb_pending = 0,
+ .tmi = 5, .tm_mod = 10, .bbf = true);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur bis")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 13, .duration_symb_nb = 8,
+ .symb_nb = 8, .main_seg_nb_total = 12,
+ .tmi = 5, .tm_mod = 10, .bbf = true);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur one")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 1,
+ .symb_nb = 1, .main_seg_nb_total = 1,
+ .tmi = 5, .tm_mod = 10, .bbf = true);
+ } test_end;
+ test_begin (t, "tm unicast data limit dur two")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 2,
+ .symb_nb = 2, .main_seg_nb_total = 2,
+ .tmi = 5, .tm_mod = 10, .bbf = true);
+ } test_end;
+ test_begin (t, "robo unicast data limit dur encrypted")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .encrypted = true, .bbf = true);
+ } test_end;
+ test_begin (t, "hs-robo unicast data limit dur remove 2")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .remove = 2, .tmi = PHY_MOD_HS_ROBO, .bbf = true);
+ } test_end;
+ test_begin (t, "hs-robo unicast data limit dur remove 3")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .remove = 3, .tmi = PHY_MOD_HS_ROBO, .bbf = true);
+ } test_end;
+ test_begin (t, "sppb non zero cap 0")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1, .bbf = true,
+ .lid = MAC_LLID_MIN, .sppb = 0x1f);
+ } test_end;
+ test_begin (t, "sppb non zero cap 3")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1, .bbf = true,
+ .lid = MAC_LLID_MIN + 3, .sppb = 0x8f);
+ } test_end;
+ test_begin (t, "sppb zero cap 0")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 1, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1, .bbf = true,
+ .lid = MAC_LLID_MIN, .sppb = 0x0f);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_pg_ack_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "pg_ack");
+ test_pbproc_init (&tp);
+ test_begin (t, "acked bitmap")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc_error = { 0 },
+ .pg_sacki = true,
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc_error = { 0x15 },
+ .pg_sacki = true,
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 41, .duration_symb_nb = 30,
+ .symb_nb = 25, .main_seg_nb_total = 41,
+ .crc_error = { 0x0fa5c03a, 0x15 },
+ .pg_sacki = true,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked bitmap overflow")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 81, .duration_symb_nb = 55,
+ .symb_nb = 49, .main_seg_nb_total = 81,
+ .crc_error = { 0xaa55aa55, 0x5a5a5a5a },
+ .pg_sacki = true,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked bitmap rsof")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc_error = { 0 },
+ .pg_sacki = true, .bbf = true,
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 30, .duration_symb_nb = 50,
+ .symb_nb = 50, .main_seg_nb_total = 5,
+ .crc_error = { 0x15 },
+ .pg_sacki = true, .bbf = true,
+ .tmi = PHY_MOD_HS_ROBO);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 41, .duration_symb_nb = 30,
+ .symb_nb = 25, .main_seg_nb_total = 41,
+ .crc_error = { 0x0fa5c03a, 0x15 },
+ .pg_sacki = true, .bbf = true,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked bitmap overflow rsof")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 81, .duration_symb_nb = 55,
+ .symb_nb = 49, .main_seg_nb_total = 81,
+ .crc_error = { 0xaa55aa55, 0x5a5a5a5a },
+ .pg_sacki = true, .bbf = true,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "acked bitmap sound")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0 },
+ .pg_sacki = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0x15 },
+ .pg_sacki = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0x0fa5c03a, 0x15 },
+ .pg_sacki = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ } test_end;
+ test_begin (t, "acked bitmap sound bbf")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0 },
+ .pg_sacki = true, .bbf = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0x15 },
+ .pg_sacki = true, .bbf = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0x0fa5c03a, 0x15 },
+ .pg_sacki = true, .bbf = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ } test_end;
+ test_begin (t, "acked bitmap overflow sound")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0xaa55aa55, 0x5a5a5a5a },
+ .pg_sacki = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 5, .duration_symb_nb = 95,
+ .symb_nb = 19,
+ .crc_error = { 0xaa55aa55, 0x5a5a5a5a },
+ .pg_sacki = true, .bbf = true,
+ .tmi = TONEMAP_INDEX_INITIAL_START);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+prep_mpdu_test_suite (test_t t)
+{
+ test_suite_begin (t, "prepare mpdu");
+ prep_mpdu_basic_test_case (t);
+ prep_mpdu_basic_rsof_test_case (t);
+ prep_mpdu_ack_test_case (t);
+ prep_mpdu_pg_ack_test_case (t);
+ prep_mpdu_intervals_test_case (t);
+ prep_mpdu_expiration_test_case (t);
+ prep_mpdu_window_size_test_case (t);
+ prep_mpdu_beacon_test_case (t);
+/* prep_mpdu_fsm_test_case (t);*/
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/rx_data.c b/cesar/mac/pbproc/test/pbproc_eoc/src/rx_data.c
new file mode 100644
index 0000000000..2d9affd0a1
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/rx_data.c
@@ -0,0 +1,1932 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/rx_data.c
+ * \brief RX Data automaton test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "inc/utils.h"
+
+#include "inc/test_pbproc.h"
+
+#include "mac/common/timings.h"
+#include "hal/phy/inc/context.h"
+
+#include <stdarg.h>
+
+/** RX data burst test MPDU description. */
+struct rx_data_burst_mpdu_t
+{
+ /** Number of symbols. */
+ uint symb_nb;
+ /** Real number of symbols, or 0 if not different. */
+ uint real_symb_nb;
+ /** Number of PB. */
+ uint pb_nb;
+ /** PB Size: false for 520 octets, true for 136 octets. **/
+ bool pb_size_136;
+ /** Tonemap index. */
+ uint tmi;
+ /** Tonemap uniform modulation, or 0 to reuse previous one. */
+ uint tm_mod;
+ /** Payload is encrypted. */
+ bool encrypted;
+ /** NEK switch value (0-1) or STA own NEK (2). */
+ uint nek_switch;
+ /** Use an unknown NEK. */
+ bool bad_nek;
+ /** MPDU count (for bursts). */
+ uint mpdu_cnt;
+ /** Array of CRC error bits. */
+ u32 *crc_error;
+ /** Number of symbols for reverse transmission (RSOF). */
+ uint rev_symb_nb;
+ /** Number of PB for RSOF. */
+ uint rev_pb_nb;
+ /** bbf - prepare for RSOF */
+ bool bbf;
+ /** Time allocated for reverse transmission. */
+ uint mrdur_tck;
+};
+typedef struct rx_data_burst_mpdu_t rx_data_burst_mpdu_t;
+
+/** RX data burst test description. */
+struct rx_data_burst_desc_t
+{
+ /** Wether PRP was won before this reception. */
+ bool prp_won;
+ /** Transmission from an unassociated STA. */
+ bool unassociated;
+ /** Transmission from a STA known to be authenticated. */
+ bool authenticated;
+ /** Link ID. */
+ uint lid;
+ /** Acknowledgment expected. */
+ bool wack;
+ /** Multicast. */
+ bool bcast;
+ /** Multi-network broadcast. */
+ bool multi_net_bcast;
+ /** Window size. */
+ uint window_size_encoded;
+ /** Number of PB in the PB pool. */
+ uint pool_pb_nb;
+ /** Number of channel data. */
+ uint chandata_nb;
+ /** Reception of rsof */
+ bool rsof;
+ /** Table of individual MPDU. */
+ rx_data_burst_mpdu_t *mpdu;
+ /** Number of MPDU. */
+ uint mpdu_nb;
+ /** Test with RSOF out of allocation. */
+ bool rsof_out_of_alloc;
+ /** Test with SOF out of allocation. */
+ bool sof_out_of_alloc;
+ /** Test compatibility with old software. */
+ bool compat;
+};
+typedef struct rx_data_burst_desc_t rx_data_burst_desc_t;
+
+/** RX data burst test context. */
+struct rx_data_burst_t
+{
+ /** Source TEI. */
+ uint stei;
+ /** Whether the STA was added to MAC store. */
+ bool sta_added;
+ /** Link ID. */
+ uint lid;
+ /** Encoded window size. */
+ u8 window_size_encoded;
+ /** SACKT. */
+ uint sackt[4];
+ /** SACKI encoder. */
+ pbproc_sacki_enc_t sacki_enc;
+ /** Set to false after first MPDU. */
+ bool first;
+ /** Number of block left in pool. */
+ uint pool_size;
+};
+typedef struct rx_data_burst_t rx_data_burst_t;
+
+/** Build a call to rx_data_burst_test_f, see usage below. */
+#define rx_data_burst_test(t, tp, params...) \
+ rx_data_burst_test_f ((t), (tp), \
+ &(rx_data_burst_desc_t) { params })
+#define _one_MPDU_(mpdu...) { mpdu }
+#define _one_MPDU(mpdu) _one_MPDU_ mpdu
+#define MPDU(_mpdu...) \
+ .mpdu = (rx_data_burst_mpdu_t[]) { \
+ PREPROC_FOR_EACH_COMMA (_one_MPDU, _mpdu) }, \
+ .mpdu_nb = PREPROC_NARG (_mpdu)
+
+void
+rx_data_burst_test_mpdu (test_t t, test_pbproc_t *tp,
+ rx_data_burst_desc_t *burst, rx_data_burst_mpdu_t *m,
+ rx_data_burst_t *ctx)
+{
+ test_within (t);
+ dbg_assert (!burst->multi_net_bcast || burst->unassociated);
+ dbg_assert (!burst->multi_net_bcast || burst->bcast);
+ dbg_assert (!burst->authenticated || m->encrypted);
+ u32 date = 123456;
+ tp->config.tei = burst->rsof ? 1 : 5; /* TODO put in different place */
+ /* Prepare tone map. */
+ tonemap_t *tm = &tp->config.tonemask_info.tonemap_robo[PHY_MOD_ROBO];
+ uint dx = MAC_DX417_TCK;
+ if (m->tmi != PHY_MOD_ROBO || m->encrypted)
+ {
+ tm = utils_sta_prepare_default_tonemap (tp, false, ctx->stei, m->tmi,
+ m->tm_mod, 0, &dx);
+ ctx->sta_added = true;
+ }
+ uint rifs_tck = m->symb_nb == 0 || m->tmi < PHY_MOD_ROBO_NB
+ ? MAC_RIFS_DEFAULT_TCK : MAC_RIFS_SPC_ANY_TCK;
+ if (m->mpdu_cnt)
+ rifs_tck = MAC_BIFS_TCK;
+ /* Encrypted? */
+ utils_prepare_encryption (tp, m->encrypted, burst->authenticated,
+ ctx->stei, m->nek_switch);
+ /* Prepare FC. */
+ const uint fl_tck = MAC_PAYLOAD_TCK (m->symb_nb, dx)
+ + rifs_tck;
+ pbproc_fc_sof_t sof_fc = {
+ .dt_av = PBPROC_FC_DT_SOF,
+ .access = false,
+ .snid = tp->snid + (burst->multi_net_bcast ? 1 : 0),
+ .direction = 0,
+ .dtei = burst->wack ? tp->config.tei : 0xff,
+ .lid = burst->lid,
+ .eks = m->bad_nek ? 1 : (m->encrypted ? 0 : 0x3),
+ .pbsz = m->pb_size_136,
+ .num_sym = MIN (m->symb_nb, 3u),
+ .tmi_av = m->tmi,
+ .fl_av = MAC_TCK_TO_FL (fl_tck),
+ .mpdu_cnt = m->mpdu_cnt,
+ .burst_cnt = 0,
+ .bbf = m->bbf,
+ .mrdur_fl = m->mrdur_tck / MAC_TCK_PER_FL,
+ .mcf = burst->bcast,
+ .mnbf = burst->multi_net_bcast,
+ .fccs_av = 0,
+ };
+ pbproc_fc_rsof_t rsof_fc = {
+ .dt_av = PBPROC_FC_DT_RSOF,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = ctx->stei,
+ .pbsz = m->pb_size_136,
+ .bdf = true,
+ .num_sym = MIN (m->symb_nb, 3u),
+ .lid = burst->compat ? MAC_LID_NONE : burst->lid,
+ .tmi_av = m->tmi,
+ .rsof_fl_av = MAC_TCK_TO_FL (fl_tck),
+ .sppb = burst->compat ? 0x50 : 0x2f,
+ .fccs_av = 0,
+ };
+ const u8 pending_seg_info = !burst->rsof ? 0 : (burst->compat ? 1 : 2);
+ const uint rx_fl_tck = MAC_FL_TO_TCK (MAC_TCK_TO_FL (fl_tck));
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + rx_fl_tck;
+ /* Scenario. */
+ const phy_pb_size_t pb_size = m->pb_size_136 ? PHY_PB_SIZE_136 : PHY_PB_SIZE_520;
+ bool drop = m->symb_nb == 0
+ || (burst->bcast && burst->wack && m->bad_nek);
+ uint chandata_nb = burst->chandata_nb && !drop && !burst->unassociated
+ ? burst->chandata_nb : 0;
+ uint nb_pb_it = burst->wack
+ && m->pb_nb > PBPROC_SACKD_ANTICIP_PB_THRESHOLD
+ ? m->pb_nb - PBPROC_SACKD_ANTICIP_PB_NB : m->pb_nb;
+ bool pb_crc_error_first, pb_crc_error_last;
+ pb_crc_error_first = pb_crc_error_last = false;
+ mfs_tx_t *mfs = NULL;
+ if (m->crc_error)
+ {
+ /* Read CRC bitmap to compute CRC status returned by hardware. */
+ u32 *p = m->crc_error;
+ u32 b = 1;
+ uint i;
+ bool *pb_crc_error = &pb_crc_error_first;
+ /* If no intermediary interrupt, go direct to last one. */
+ if (nb_pb_it == m->pb_nb)
+ pb_crc_error = &pb_crc_error_last;
+ /* Read all bits. */
+ for (i = 0; i < m->pb_nb; i++)
+ {
+ /* Second part? */
+ if (i == nb_pb_it)
+ pb_crc_error = &pb_crc_error_last;
+ /* bad CRC? */
+ if (*p & b)
+ *pb_crc_error = true;
+ /* Next bit. */
+ b <<= 1;
+ if (!b)
+ {
+ p++;
+ b = 1;
+ }
+ }
+ }
+ bool send_sack = ((!m->bbf || burst->rsof_out_of_alloc) && !burst->rsof)
+ || burst->sof_out_of_alloc;
+ if (burst->rsof_out_of_alloc)
+ date = tp->pbproc->alloc.end_date
+ - (2 * pre_fc_fl_tck + m->mrdur_tck) / 2;
+ /* TODO: change this when MAC_CF_RSOF_SOF_IFS_TCK is removed. */
+ if (burst->sof_out_of_alloc)
+ date = tp->pbproc->alloc.end_date
+ - pre_fc_fl_tck - 2 * (MAC_PREAMBLE_TCK + MAC_FC_AV_TCK)
+ - MAC_RIFS_DEFAULT_TCK - MAC_US_TO_TCK (42);
+ /* Prepare reception. Only allow ordinary frames to be acked with RSOF. */
+ test_fail_unless (!burst->rsof || burst->wack);
+ bool valid = burst->rsof && burst->wack;
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ prep->valid = valid;
+ if (valid)
+ {
+ prep->bbf = burst->rsof;
+ prep->dtei = 25;
+ prep->lid = burst->lid;
+ prep->eks = 0;
+ prep->tx_date = date;
+ prep->flp_tck = 0;
+ /* prepare false mpdu */
+ prep->main_commit_return_head = 0;
+ prep->main_commit_return_seg_nb = 0;
+ prep->burst_head_ssn = prep->burst_seg_nb =
+ prep->expired_segments_nb = 0;
+ prep->mpdu_count = 1;
+ prep->mpdu[0].pb_nb_total = 0;
+ bool added;
+ prep->main_mfs = mfs = mac_store_mfs_add_tx (tp->store, false, false,
+ MAC_LLID_MIN, ctx->stei, &added);
+ dbg_assert (added);
+ blk_addref (mfs);
+ test_fail_unless (prep->main_mfs);
+ ctx->sta_added = true;
+ /* Set fsm to wait for SACKD. */
+ tp->pbproc->fsm.current_state = PBPROC_FSM_STATE_TX_WAIT_SACKD;
+ }
+ scenario_entry_t entries_long[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date,
+ .prp_won = burst->prp_won,
+ .slot_count = 2,
+ .fc_av = burst->rsof
+ ? PARENT_OF (pbproc_fc_t, rsof, &rsof_fc)->words
+ : PARENT_OF (pbproc_fc_t, sof, &sof_fc)->words),
+ SCENARIO_EVENT_COND (ctx->first && burst->prp_won && !burst->rsof,
+ ca_backoff_deferred, .slot_count = 0),
+ SCENARIO_EVENT_COND (ctx->first && !burst->prp_won && !burst->rsof,
+ ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT_COND (m->tmi >= PHY_MOD_ROBO_NB, phy_set_tonemap),
+ SCENARIO_EVENT_COND (m->pb_nb, phy_rx_prepare, .nb_pb = m->pb_nb,
+ .mod = m->tmi < PHY_MOD_ROBO_NB ? m->tmi : PHY_MOD_TM,
+ .fecrate = tm->fecrate, .pb_size = pb_size,
+ .gil = tm->gil, .symbol_nb = m->real_symb_nb
+ ? m->real_symb_nb : m->symb_nb,
+ .tcc_halfit = tm->tcc_halfit),
+ SCENARIO_EVENT_COND (!m->pb_nb, phy_rx_prepare_short),
+ SCENARIO_EVENT_COND (m->pb_nb, phy_pbdma_start,
+ .bypass_aes = !m->encrypted || drop,
+ .nb_total = m->pb_nb,
+ .nb_pb_it = m->pb_nb == nb_pb_it && chandata_nb ? 0
+ : nb_pb_it, .chandata = chandata_nb ? true : false,
+ .now = true),
+ SCENARIO_EVENT_COND (m->mpdu_cnt == 0 && (!m->bbf || send_sack),
+ ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck
+ + ((burst->rsof || !burst->wack)
+ && !burst->sof_out_of_alloc
+ ? MAC_US_TO_TCK (60)
+ : MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_CIFS_TCK)),
+ SCENARIO_EVENT_COND (m->mpdu_cnt == 0 && m->bbf && !send_sack,
+ ca_access_reprogram,
+ .date = date + pre_fc_fl_tck + MAC_US_TO_TCK (100),
+ .duration_tck = m->mrdur_tck, .tei = 1),
+ SCENARIO_EVENT_COND (m->mpdu_cnt != 0, ca_access_vcs_restart_eifs,
+ .start_date = date + pre_fc_fl_tck),
+ SCENARIO_EVENT_COND (m->mpdu_cnt != 0, phy_rx_activate,
+ .now = false, .date = date + pre_fc_fl_tck
+ + PHY_RX_ACTIVATE_DELAY_AFTER_BURST_TCK,
+ .pre_detection = true),
+ SCENARIO_EVENT_COND (valid && m->pb_nb, ca_access_done),
+ SCENARIO_ACTION_COND (m->pb_nb != nb_pb_it, phy_pbdma, .pb_it = true,
+ .pb_crc_error = pb_crc_error_first,
+ .crc_bitmap = m->crc_error,
+ .crc_bitmap_bits = nb_pb_it),
+ SCENARIO_EVENT_COND (m->pb_nb != nb_pb_it, phy_pbdma_update,
+ .nb_pb_it = chandata_nb ? 0 : m->pb_nb),
+ SCENARIO_ACTION_COND (m->pb_nb, phy_pbdma, .pb_it = true, .end_rx_pb = true,
+ .pb_crc_error = pb_crc_error_last,
+ .crc_bitmap = m->crc_error,
+ .crc_bitmap_bits = m->pb_nb),
+ SCENARIO_EVENT_COND (burst->wack && m->mpdu_cnt == 0 && send_sack,
+ phy_tx_param_short,
+ .fc_mode = PHY_FC_MODE_AV_1),
+ SCENARIO_EVENT_COND (burst->wack && m->mpdu_cnt == 0 && send_sack,
+ phy_tx_frame,
+ .date = date + pre_fc_fl_tck,
+ .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT_COND (valid && !m->pb_nb, ca_access_done),
+ SCENARIO_EVENT_COND (!drop, pbproc_rx_cb, .pb_nb = m->pb_nb,
+ .chandata_nb = chandata_nb,
+ .lid = burst->lid,
+ .fl_tck = rx_fl_tck,
+ .pending_seg_info = pending_seg_info,
+ .pb_size = pb_size,
+ .mpdu_cnt = m->mpdu_cnt,
+ .mfs_cmd_data = !burst->bcast ? MFS_FSM_CMD_INIT
+ : MFS_FSM_CMD_NOP,
+ .mfs_cmd_mme = MFS_FSM_CMD_NOP),
+ SCENARIO_END
+ };
+ /*
+ scenario_entry_t entries_short[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date,
+ .prp_won = burst->prp_won,
+ .slot_count = 2,
+ .fc_av = PARENT_OF (pbproc_fc_t, sof,
+ &sof_fc)->words),
+ SCENARIO_EVENT_COND (ctx->first && burst->prp_won,
+ ca_backoff_deferred, .slot_count = 0),
+ SCENARIO_EVENT_COND (ctx->first && !burst->prp_won,
+ ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT_COND (burst->wack && m->mpdu_cnt == 0,
+ phy_tx_param_short,
+ .fc_mode = PHY_FC_MODE_AV_1),
+ SCENARIO_EVENT_COND (burst->wack && m->mpdu_cnt == 0,
+ phy_tx_frame,
+ .date = date + pre_fc_fl_tck,
+ .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT_COND (m->mpdu_cnt == 0, ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_CIFS_TCK),
+ SCENARIO_EVENT_COND (m->mpdu_cnt != 0, ca_access_vcs_restart_eifs,
+ .start_date = date + pre_fc_fl_tck),
+ SCENARIO_EVENT_COND (m->mpdu_cnt != 0, phy_rx_activate,
+ .now = false, .date = date + pre_fc_fl_tck
+ + PHY_RX_ACTIVATE_DELAY_AFTER_BURST_TCK,
+ .pre_detection = true),
+ SCENARIO_END
+ };
+ */
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ /* Run scenario. */
+ scenario_run (t, entries_long, &globals);
+ /* Check pool. */
+ test_fail_unless (tp->pbproc->rx_pool_size == ctx->pool_size
+ - (!drop ? 1 + m->pb_nb + chandata_nb : 0));
+ ctx->pool_size = tp->pbproc->rx_pool_size;
+ /* Build SACK to check. */
+ if (burst->wack)
+ {
+ dbg_assert (m->mpdu_cnt < COUNT (ctx->sackt));
+ if (m->symb_nb == 0)
+ {
+ ctx->sackt[m->mpdu_cnt] = PBPROC_FC_SACKT_UNIFORM;
+ uint sacki_uniform = PBPROC_FC_SACKI_UNIFORM_ALL_OK; /* EoC */
+ pbproc_sacki_enc_copy (&ctx->sacki_enc, &sacki_uniform,
+ PBPROC_FC_SACKI_UNIFORM_SIZE);
+ }
+ else if (!pb_crc_error_first && !pb_crc_error_last)
+ {
+ ctx->sackt[m->mpdu_cnt] = PBPROC_FC_SACKT_UNIFORM;
+ uint sacki_uniform = PBPROC_FC_SACKI_UNIFORM_ALL_OK;
+ pbproc_sacki_enc_copy (&ctx->sacki_enc, &sacki_uniform,
+ PBPROC_FC_SACKI_UNIFORM_SIZE);
+ }
+ else
+ {
+ ctx->sackt[m->mpdu_cnt] = PBPROC_FC_SACKT_MIXED;
+ /* Do not check SACKI, it was checked in its own test. */
+ uint sacki = 0xdead;
+ pbproc_sacki_enc_copy (&ctx->sacki_enc, &sacki, 16);
+ }
+ }
+ /* Check SACK. */
+ if (burst->wack && m->mpdu_cnt == 0 && send_sack)
+ {
+ pbproc_fc_sack_t sack = PARENT_OF (pbproc_fc_t, words,
+ tp->pbproc->phy->tx_fc)->sack;
+ test_fail_unless (sack.dt_av == PBPROC_FC_DT_SACK);
+ test_fail_unless (sack.access == false);
+ test_fail_unless (sack.snid == tp->snid);
+ test_fail_unless (sack.dtei == ctx->stei);
+ test_fail_unless (sack.cfs == true);
+ test_fail_unless (sack.bdf == false);
+ test_fail_unless (sack.svn == 0);
+ test_fail_unless (sack.rrtf == 0);
+ test_fail_unless (sack.mfs_rsp_data == MFS_FSM_RSP_ACK);
+ test_fail_unless (sack.mfs_rsp_mgmt == MFS_FSM_RSP_ACK);
+ uint sackt[COUNT (ctx->sackt)] = {
+ sack.sackt0, sack.sackt1, sack.sackt2, sack.sackt3
+ };
+ bool mixed = false;
+ uint i;
+ for (i = 0; i < COUNT (ctx->sackt); i++)
+ {
+ if (ctx->sackt[i] == PBPROC_FC_SACKT_MIXED)
+ {
+ test_fail_unless (
+ sackt[i] == PBPROC_FC_SACKT_MIXED
+ || sackt[i] == PBPROC_FC_SACKT_MIXED_COMPRESSED);
+ mixed = true;
+ }
+ else
+ test_fail_unless (sackt[i] == ctx->sackt[i]);
+ }
+ if (!mixed)
+ {
+ test_fail_unless (sack.sacki[0] == ctx->sacki_enc.si[0]);
+ test_fail_unless (sack.sacki[1] == ctx->sacki_enc.si[1]);
+ if (MAC_LID_IS_PLID (burst->lid))
+ test_fail_unless ((sack.sacki_last & 0xf)
+ == ctx->sacki_enc.si[2]);
+ else
+ test_fail_unless (sack.sacki_last == ctx->sacki_enc.si[2]);
+ }
+ if (MAC_LID_IS_PLID (burst->lid))
+ test_fail_unless (sack.sacki_last >> 4
+ == ctx->window_size_encoded);
+ }
+ /* Check SACK. */
+ if (burst->wack && m->mpdu_cnt == 0 && (m->bbf && !send_sack))
+ {
+ pbproc_sackd_t *sackd = &tp->pbproc->recv_mpdu.sackd;
+ test_fail_if (MAC_LID_IS_PLID (sackd->lid));
+ test_fail_unless (sackd->tei == MAC_TEI_CCO_DEF);
+ test_fail_unless (sackd->sacki_enc.sil + sackd->sacki_enc.sis
+ == PBPROC_FC_SACK_SACKI_BITS);
+ test_fail_unless (tp->pbproc->recv_mpdu.rx_params.bbf);
+ test_fail_unless (tp->pbproc->recv_mpdu.rx_params.mrdur_tck
+ == m->mrdur_tck);
+ }
+ /* Prepared mpdu should be released.*/
+ if (burst->rsof)
+ {
+ test_fail_unless (prep->valid == false);
+ }
+ /* Release allocated mfs for false prepared mpdu */
+ if (mfs)
+ {
+ mac_store_mfs_remove (tp->store, PARENT_OF (mfs_t, tx, mfs));
+ blk_release (mfs);
+ }
+ ctx->first = false;
+}
+
+void
+rx_data_burst_test_f (test_t t, test_pbproc_t *tp,
+ rx_data_burst_desc_t *burst)
+{
+ test_within (t);
+ uint i, mpdu_i;
+ rx_data_burst_t ctx;
+ /* 1 default CCO, even in not assoc state stei = 1 */
+ ctx.stei = burst->rsof ? 25 : 1;
+ ctx.lid = 1;
+ ctx.sta_added = false;
+ ctx.sackt[0] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ctx.sackt[1] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ctx.sackt[2] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ctx.sackt[3] = PBPROC_FC_SACKT_NOT_RECEIVED;
+ ctx.first = true;
+ pbproc_sacki_enc_init (&ctx.sacki_enc, PBPROC_FC_SACK_SACKI_BITS - 4,
+ true);
+ /* Prepare channel data configuration. */
+ u32 chandata_conf[burst->chandata_nb];
+ if (burst->chandata_nb)
+ {
+ for (i = 0; i < burst->chandata_nb; i++)
+ chandata_conf[i] = i;
+ pbproc_set_chandata_conf (tp->pbproc,
+ (phy_chandata_conf_t *) chandata_conf,
+ burst->chandata_nb, true);
+ }
+ /* Allocate PB pool. */
+ blk_t *first, *last;
+ ctx.pool_size = burst->mpdu_nb + burst->pool_pb_nb;
+ first = blk_alloc_desc_range (ctx.pool_size, &last);
+ pbproc_rx_segment_refill (tp->pbproc, PARENT_OF (pb_t, blk, first),
+ PARENT_OF (pb_t, blk, last), ctx.pool_size);
+ /* Create an MFS if window_size is not default. */
+ mfs_rx_t *mfs = NULL;
+ if (burst->window_size_encoded)
+ {
+ bool added;
+ mfs = mac_store_mfs_add_rx (tp->store, burst->bcast, false,
+ burst->lid, ctx.stei, &added);
+ dbg_assert (added);
+ mfs->window_size_encoded = burst->window_size_encoded;
+ mfs->window_size = mfs_window_size[burst->window_size_encoded];
+ ctx.window_size_encoded = mfs->window_size_encoded;
+ }
+ else
+ ctx.window_size_encoded = MFS_RX_WINDOW_SIZE_DATA_DEFAULT_ENCODED;
+ /* Reset stats. */
+ test_pbproc_check_stats_reset (tp);
+ uint bad_symb_nb = 0, null_symb_nb = 0, empty_nb = 0;
+ /* Receive every MPDU. */
+ test_pbproc_alloc (tp, false, 0);
+ for (mpdu_i = 0; mpdu_i < burst->mpdu_nb; mpdu_i++)
+ {
+ rx_data_burst_mpdu_t *m = &burst->mpdu[mpdu_i];
+ /* Run scenario. */
+ rx_data_burst_test_mpdu (t, tp, burst, m, &ctx);
+ if (m->real_symb_nb)
+ bad_symb_nb++;
+ if (m->symb_nb > 0 && m->pb_nb == 0)
+ null_symb_nb++;
+ if (m->symb_nb == 0 && m->pb_nb == 0)
+ empty_nb++;
+ }
+ /* Check stats. */
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = burst->rsof ? 0 : burst->prp_won ? 0 : 1,
+ .cw_lost = burst->rsof ? 0 : burst->prp_won ? 1 : 0,
+ .rx_handle_fc = burst->mpdu_nb,
+ .rx_data = burst->mpdu_nb,
+ .rx_data_wack = burst->wack ? burst->mpdu_nb - null_symb_nb : 0,
+ .rx_data_woack = !burst->wack ? burst->mpdu_nb - null_symb_nb : 0,
+ .rx_data_error = null_symb_nb,
+ .rx_data_empty = empty_nb,
+ .rx_data_bad_symb_nb = bad_symb_nb,
+ .rx_rsof_out_of_alloc = burst->rsof_out_of_alloc ? 1 : 0,
+ .tx_data_wack_ack = burst->rsof ? 1 : 0);
+ /* Check return to IDLE state. */
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ /* Cleanup. */
+ if (tp->pbproc->rx_pool_size)
+ {
+ blk_release_desc_range (&tp->pbproc->rx_pool_head->blk,
+ &tp->pbproc->rx_pool_tail->blk);
+ slist_init (tp->pbproc->rx_pool_, paste_size);
+ }
+ if (mfs)
+ {
+ mac_store_mfs_remove (tp->store, PARENT_OF (mfs_t, rx, mfs));
+ blk_release (mfs);
+ }
+ if (ctx.sta_added)
+ dbg_check (mac_store_sta_remove (tp->store, ctx.stei));
+ tp->config.authenticated = false;
+ if (burst->chandata_nb)
+ pbproc_set_chandata_conf (tp->pbproc, NULL, 0, false);
+}
+
+void
+rx_beacon_test (test_t t, test_pbproc_t *tp, u32 date, uint symb_nb)
+{
+ test_within (t);
+ pbproc_fc_beacon_t beacon_fc = {
+ .dt_av = PBPROC_FC_DT_BEACON,
+ .access = false,
+ .snid = tp->snid,
+ .bts_lsb24 = 0x345678,
+ .bts_msb8 = 0x12,
+ .bto0 = 0x0123,
+ .bto1_lsb8 = 0x34,
+ .bto1_msb8 = 0x12,
+ .bto2 = 0x2345,
+ .bto3_lsb8 = 0x56,
+ .bto3_msb8 = 0x34,
+ .fccs_av = 0,
+ };
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK
+ + MAC_FC_AV_TCK + MAC_PAYLOAD_TCK (symb_nb, MAC_DX567_TCK)
+ + MAC_B2BIFS_TCK;
+ test_pbproc_check_stats_reset (tp);
+ test_pbproc_alloc (tp, true, 0);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .rx_sysdate = date / 2,
+ .prp_won = false,
+ .fc_av = PARENT_OF (pbproc_fc_t, beacon,
+ &beacon_fc)->words),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare, .nb_pb = 1,
+ .mod = PHY_MOD_MINI_ROBO,
+ .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_136, .gil = PHY_GIL_567,
+ .symbol_nb = symb_nb, .tcc_halfit = 1),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true,
+ .nb_total = 1, .nb_pb_it = 1, .chandata = false,
+ .now = true),
+ SCENARIO_ACTION (phy_pbdma, .pb_it = true, .end_rx_pb = true),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck),
+ SCENARIO_EVENT (pbproc_rx_beacon_cb, .duration_tck = 0),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ blk_t *pb;
+ pb = blk_alloc_desc ();
+ uint old_pool_size = tp->pbproc->rx_pool_size;
+ pbproc_rx_segment_refill (tp->pbproc, PB_FROM_BLK (pb), PB_FROM_BLK (pb),
+ 1);
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (t, tp,
+ .prp_lost = 1,
+ .rx_handle_fc = 1,
+ .rx_beacon = 1);
+ test_fail_unless (tp->pbproc->rx_pool_size == old_pool_size);
+ test_fail_unless (old_pool_size != 0 || tp->pbproc->rx_pool_head == NULL);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+rx_data_basic_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic");
+ test_pbproc_init (&tp);
+ test_begin (t, "robo unicast reverse")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .lid = 4,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .bbf = true,
+ .mrdur_tck = MAC_FL_TO_TCK (MAC_TCK_TO_FL (50000)))));
+ } test_end;
+ test_begin (t, "robo unicast encrypted rsof")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .rsof = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ } test_end;
+ test_begin (t, "robo unicast reverse, RSOF out of alloc")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .lid = 4, .rsof_out_of_alloc = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .bbf = true,
+ .mrdur_tck = MAC_FL_TO_TCK (MAC_TCK_TO_FL (50000)))));
+ } test_end;
+ test_begin (t, "robo unicast encrypted rsof, SOF out of alloc")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .rsof = true, .sof_out_of_alloc = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ } test_end;
+ test_begin (t, "robo unicast encrypted rsof compat")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .rsof = true, .compat = true, .lid = MAC_LLID_MIN,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ } test_end;
+ test_begin (t, "robo unicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = true, .pool_pb_nb = 7, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo unicast no seg")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 0, .pb_nb = 0, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo window size")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .lid = 1,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .lid = 5,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .lid = 1, .window_size_encoded = MFS_WINDOW_SIZE_160,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ .lid = 5, .window_size_encoded = MFS_WINDOW_SIZE_160,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo unicast chandata")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 16, .wack = true,
+ .chandata_nb = 11,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = true, .pool_pb_nb = 18, .wack = true,
+ .chandata_nb = 11,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo multicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .bcast = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo multicast partial ack")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true, .bcast = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo unicast unassociated")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true, .unassociated = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ /* No chandata in unassoc state in EoC
+ test_begin (t, "robo unicast unassociated chandata")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 16, .wack = true, .unassociated = true,
+ .chandata_nb = 11,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ */
+ test_begin (t, "robo multicast unassociated")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .bcast = true, .unassociated = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo multi network multicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .bcast = true, .unassociated = true,
+ .multi_net_bcast = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "hs-robo unicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 50, .pb_nb = 5, .tmi = PHY_MOD_HS_ROBO)));
+ } test_end;
+ test_begin (t, "mini robo unicast PB136")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 1, .wack = true,
+ MPDU ((.symb_nb = 6, .pb_nb = 1, .pb_size_136 = true,
+ .tmi = PHY_MOD_MINI_ROBO)));
+ } test_end;
+ test_begin (t, "tm unicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 6, .wack = true,
+ MPDU ((.symb_nb = 4, .pb_nb = 6, .tmi = 5, .tm_mod = 10)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 1, .wack = true,
+ MPDU ((.symb_nb = 1, .pb_nb = 1, .tmi = 5, .tm_mod = 10)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 2, .wack = true,
+ MPDU ((.symb_nb = 2, .pb_nb = 2, .tmi = 5, .tm_mod = 10)));
+ } test_end;
+ test_begin (t, "tm unicast no seg")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 6, .wack = true,
+ MPDU ((.symb_nb = 0, .pb_nb = 0, .tmi = 5, .tm_mod = 10)));
+ } test_end;
+ test_begin (t, "tm unicast PB136")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 1, .wack = true,
+ MPDU ((.symb_nb = 2, .pb_nb = 1, .pb_size_136 = true,
+ .tmi = 5, .tm_mod = 1)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 1, .wack = true,
+ MPDU ((.symb_nb = 1, .pb_nb = 1, .pb_size_136 = true,
+ .tmi = 5, .tm_mod = 10)));
+ } test_end;
+ test_begin (t, "tm unicast large")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 41, .wack = true,
+ MPDU ((.symb_nb = 25, .pb_nb = 41, .tmi = 5, .tm_mod = 10)));
+ } test_end;
+ test_begin (t, "tm unicast large chandata")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 46, .wack = true, .chandata_nb = 5,
+ MPDU ((.symb_nb = 25, .pb_nb = 41, .tmi = 5, .tm_mod = 10)));
+ } test_end;
+ test_begin (t, "robo unicast encrypted sta unknown")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ } test_end;
+ test_begin (t, "robo unicast encrypted sta known")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true, .authenticated = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true, .authenticated = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ } test_end;
+ test_begin (t, "robo unicast encrypted subavln")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true, .authenticated = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .encrypted = true, .nek_switch = 0)));
+ } test_end;
+ test_begin (t, "robo unicast crc error none")
+ {
+ u32 crc_error[8] = { 0x00, };
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .crc_error = crc_error)));
+ } test_end;
+ test_begin (t, "robo unicast crc error one")
+ {
+ u32 crc_error[8] = { 0x01, };
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .crc_error = crc_error)));
+ } test_end;
+ test_begin (t, "robo unicast crc error many")
+ {
+ u32 crc_error[8] = { 0x1d, };
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .crc_error = crc_error)));
+ } test_end;
+ test_begin (t, "tm unicast large crc error few")
+ {
+ u32 crc_error[8] = { 0x10000001, 0x010 };
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 41, .wack = true,
+ MPDU ((.symb_nb = 25, .pb_nb = 41, .tmi = 5, .tm_mod = 10,
+ .crc_error = crc_error)));
+ } test_end;
+ test_begin (t, "tm unicast large crc error many")
+ {
+ u32 crc_error[8] = { 0xffefdff7, 0x1fb };
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 41, .wack = true,
+ MPDU ((.symb_nb = 25, .pb_nb = 41, .tmi = 5, .tm_mod = 10,
+ .crc_error = crc_error)));
+ } test_end;
+ test_begin (t, "robo multicast partial ack unauthenticated encrypted")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true, .bcast = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .bad_nek = true)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 16, .wack = true, .bcast = true,
+ .chandata_nb = 11,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .bad_nek = true)));
+ } test_end;
+ test_begin (t, "beacon")
+ {
+ rx_beacon_test (t, &tp, 123654, 6);
+ blk_t *pb;
+ pb = blk_alloc_desc ();
+ pbproc_rx_segment_refill (tp.pbproc, PB_FROM_BLK (pb),
+ PB_FROM_BLK (pb), 1);
+ rx_beacon_test (t, &tp, 123654, 6);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+rx_data_burst_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "burst");
+ test_pbproc_init (&tp);
+ test_begin (t, "robo unicast burst 2")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 10, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "robo unicast burst 3")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 15, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 2),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "robo unicast burst 4")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 20, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 3),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 2),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "robo unicast chandata")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 4 * 16, .wack = true, .chandata_nb = 11,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 3),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 2),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "robo multicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 4 * 5, .bcast = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 3),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 2),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "tm unicast")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 50, .wack = true,
+ MPDU ((.symb_nb = 4, .pb_nb = 6, .tmi = 5, .tm_mod = 10,
+ .mpdu_cnt = 3),
+ (.symb_nb = 1, .pb_nb = 1, .tmi = 5,
+ .mpdu_cnt = 2),
+ (.symb_nb = 2, .pb_nb = 2, .tmi = 5,
+ .mpdu_cnt = 1),
+ (.symb_nb = 25, .pb_nb = 41, .tmi = 5,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "robo/tm unicast crc error")
+ {
+ u32 crc_error[][8] = {
+ { 0x00, },
+ { 0x01, },
+ { 0x1d, },
+ { 0x10000001, 0x010 },
+ };
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 56, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 3),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 2, .crc_error = crc_error[1]),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1, .crc_error = crc_error[2]),
+ (.symb_nb = 25, .pb_nb = 41, .tmi = 5, .tm_mod = 10,
+ .mpdu_cnt = 0, .crc_error = crc_error[3])));
+ } test_end;
+ test_begin (t, "robo unicast hole")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 20, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 3),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "robo multicast partial ack unauthenticated encrypted"
+ " hole")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 15, .wack = true, .bcast = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 2),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1, .bad_nek = true),
+ (.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 0)));
+ } test_end;
+ test_begin (t, "burst interruption")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 10, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO,
+ .mpdu_cnt = 1),
+ (.symb_nb = 0, .pb_nb = 0, .mpdu_cnt = 0)));
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+enum rx_data_nfu_t
+{
+ NFU_SACK,
+ NFU_SOF_ACCESS,
+ NFU_SOF_SNID,
+ NFU_SOF_TEI,
+ NFU_SOF_UNASSOC_SNID,
+ NFU_OUT_OF_ALLOC,
+ NFU_POOL_SHORTAGE,
+ NFU_RSOF_WRONG_STATION,
+};
+typedef enum rx_data_nfu_t rx_data_nfu_t;
+
+void
+rx_data_nfu_test (test_t t, test_pbproc_t *tp, u32 date, rx_data_nfu_t nfu)
+{
+ test_within (t);
+ u32 restart_date;
+ uint length_tck;
+ mfs_tx_t *mfs = NULL;
+ const uint lid = MAC_LLID_MIN;
+ pbproc_fc_t fc;
+ const uint sof_fl_tck = MAC_PAYLOAD_TCK (45, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK;
+ pbproc_fc_sof_t sof_fc = {
+ .dt_av = PBPROC_FC_DT_SOF,
+ .access = nfu == NFU_SOF_ACCESS,
+ .snid = nfu != NFU_SOF_SNID ? tp->snid : tp->snid + 1,
+ .direction = 0,
+ .dtei = nfu != NFU_SOF_TEI ? tp->config.tei : tp->config.tei + 8,
+ .lid = 1,
+ .eks = 0x2,
+ .pbsz = false,
+ .num_sym = MIN (45u, 3u),
+ .tmi_av = PHY_MOD_ROBO,
+ .fl_av = MAC_TCK_TO_FL (sof_fl_tck),
+ .mpdu_cnt = 0,
+ .burst_cnt = 0,
+ .bbf = false,
+ .mrdur_fl = 0,
+ .mcf = false,
+ .mnbf = false,
+ .fccs_av = 0,
+ };
+ pbproc_fc_sack_t sack_fc = {
+ .dt_av = PBPROC_FC_DT_SACK,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = 1/*tp->config.tei*/,
+ .cfs = false,
+ .bdf = true,
+ .svn = 0,
+ .rrtf = false,
+ .mfs_rsp_data = MFS_FSM_RSP_ACK,
+ .mfs_rsp_mgmt = MFS_FSM_RSP_ACK,
+ .sackt3 = 0,
+ .sackt2 = 0,
+ .sackt1 = 0,
+ .sackt0 = 0,
+ .sacki = { 0, 0 },
+ .sacki_last = 0,
+ .fccs_av = 0,
+ };
+ pbproc_fc_rsof_t rsof_fc = {
+ .dt_av = PBPROC_FC_DT_RSOF,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = 24,
+ .pbsz = 0,
+ .bdf = true,
+ .num_sym = 3u,
+ .tmi_av = PHY_MOD_ROBO,
+ .rsof_fl_av = MAC_TCK_TO_FL (sof_fl_tck),
+ .fccs_av = 0,
+ };
+ fc.sof = sof_fc;
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ bool valid = (nfu == NFU_RSOF_WRONG_STATION);
+ prep->valid = valid;
+ if (valid)
+ {
+ fc.rsof = rsof_fc;
+ prep->valid = true;
+ prep->bbf = true;
+ prep->dtei = 25;
+ prep->lid = MAC_LLID_MIN;
+ prep->eks = 0;
+ prep->tx_date = date;
+ prep->flp_tck = 0;
+ /* prepare false mpdu */
+ prep->main_commit_return_head = 0;
+ prep->main_commit_return_seg_nb = 0;
+ prep->burst_head_ssn = prep->burst_seg_nb = 0;
+ prep->expired_segments_nb = 0;
+ prep->mpdu_count = 1;
+ prep->mpdu[0].pb_nb_total = 0;
+ bool added;
+ prep->main_mfs = mfs = mac_store_mfs_add_tx (tp->store, false, false,
+ lid, 25, &added);
+ dbg_assert (added);
+ test_fail_unless (mfs);
+ blk_addref (mfs);
+ tp->pbproc->fsm.current_state = PBPROC_FSM_STATE_TX_WAIT_SACKD;
+ }
+ if (nfu == NFU_SACK)
+ {
+ fc.sack = sack_fc;
+ length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK;
+ }
+ else if (nfu == NFU_RSOF_WRONG_STATION)
+ {
+ length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_FL_TO_TCK (MAC_TCK_TO_FL (sof_fl_tck));
+ }
+ else
+ {
+ length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_FL_TO_TCK (MAC_TCK_TO_FL (sof_fl_tck))
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK;
+ }
+ if (nfu == NFU_OUT_OF_ALLOC)
+ {
+ date = TEST_PBPROC_ALLOC_END_DATE + MAC_TOLERANCE_TCK
+ - length_tck + MAC_CIFS_TCK + 1;
+ restart_date = date + length_tck - MAC_PREAMBLE_TCK - MAC_FC_AV_TCK -
+ MAC_CIFS_TCK;
+ length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK;
+ }
+ else
+ {
+ restart_date = date;
+ }
+ uint our_tei_saved = tp->config.tei;
+ if (nfu == NFU_SOF_UNASSOC_SNID)
+ tp->config.tei = 0;
+ test_pbproc_check_stats_reset (tp);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .slot_count = 2, .fc_av = fc.words),
+ SCENARIO_EVENT_COND (!valid, ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = restart_date + length_tck),
+ SCENARIO_EVENT_COND (valid, ca_access_done),
+ SCENARIO_END
+ };
+ scenario_entry_t rsof_entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .slot_count = 2, .fc_av = fc.words),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs,
+ .start_date = restart_date + length_tck),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = restart_date + length_tck,
+ .pre_detection = true),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ scenario_run (t, nfu == NFU_RSOF_WRONG_STATION ? rsof_entries : entries,
+ &globals);
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = valid ? 0 : 1,
+ .tx_data_wack_noack = valid ? 1 : 0,
+ .rx_handle_fc = 1,
+ .rx_nfu = nfu == NFU_OUT_OF_ALLOC ? 0 : 1,
+ .rx_data = nfu == NFU_OUT_OF_ALLOC ? 1 : 0,
+ .rx_data_error = nfu == NFU_OUT_OF_ALLOC ? 1 : 0,
+ .rx_out_of_alloc = nfu == NFU_OUT_OF_ALLOC ? 1 : 0);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ tp->config.tei = our_tei_saved;
+ if (valid)
+ {
+ mac_store_mfs_remove (tp->store, PARENT_OF (mfs_t, tx, mfs));
+ blk_release (mfs);
+ dbg_check (mac_store_sta_remove (tp->store, 25));
+ }
+}
+
+/**
+ * Test beacon to be ignored.
+ * \param t test context
+ * \param tp test_pbproc context
+ * \param nfu NFU kind
+ */
+static void
+rx_beacon_nfu_test (test_t t, test_pbproc_t *tp, rx_data_nfu_t nfu)
+{
+ test_within (t);
+ /* Prepare FC. */
+ pbproc_fc_beacon_t beacon_fc = {
+ .dt_av = PBPROC_FC_DT_BEACON,
+ .access = false,
+ .snid = tp->snid,
+ .bts_lsb24 = 0x345678,
+ .bts_msb8 = 0x12,
+ .bto0 = 0x0123,
+ .bto1_lsb8 = 0x34,
+ .bto1_msb8 = 0x12,
+ .bto2 = 0x2345,
+ .bto3_lsb8 = 0x56,
+ .bto3_msb8 = 0x34,
+ .fccs_av = 0,
+ };
+ u32 date = 12345;
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK
+ + MAC_FC_AV_TCK + MAC_PAYLOAD_TCK (6, MAC_DX567_TCK)
+ + MAC_B2BIFS_TCK;
+ if (nfu == NFU_OUT_OF_ALLOC)
+ /* Date to overshoot allocation. */
+ date = TEST_PBPROC_ALLOC_END_DATE + MAC_TOLERANCE_TCK
+ - pre_fc_fl_tck + MAC_B2BIFS_TCK + 1;
+ if (nfu != NFU_POOL_SHORTAGE)
+ tp->pbproc->rx_pool_size = 1;
+ /* Use another state to test return to IDLE. */
+ tp->pbproc->fsm.current_state = PBPROC_FSM_STATE_RX_BURST;
+ /* Reset stats. */
+ test_pbproc_check_stats_reset (tp);
+ /* Scenario. */
+ test_pbproc_alloc (tp, true, 0);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .fc_av = PARENT_OF (pbproc_fc_t, beacon,
+ &beacon_fc)->words),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ scenario_run (t, entries, &globals);
+ /* Check stats. */
+ test_pbproc_check_stats (
+ t, tp,
+ .rx_handle_fc = 1,
+ .rx_beacon = 1,
+ .rx_out_of_alloc = nfu == NFU_OUT_OF_ALLOC ? 1 : 0,
+ .rx_pool_shortage = nfu == NFU_POOL_SHORTAGE ? 1 : 0);
+ /* Check PBProc state. */
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ test_fail_unless (tp->pbproc->rx_pool_size == (nfu != NFU_POOL_SHORTAGE
+ ? 1 : 0));
+ tp->pbproc->rx_pool_size = 0;
+}
+
+enum rx_data_sack_error_t
+{
+ SACK_ERROR_TM_TMI_UNAVAILABLE,
+ SACK_ERROR_TM_STA_UNAVAILABLE,
+ SACK_ERROR_TM_UNASSOCIATED,
+ SACK_ERROR_TM_BCAST,
+ SACK_ERROR_ENC_STA_NO_NEK,
+ SACK_ERROR_ENC_NO_EKS,
+ SACK_ERROR_ENC_UNASSOCIATED,
+ SACK_ERROR_POOL_SHORTAGE,
+ SACK_ERROR_EMPTY,
+ WOACK_ERROR_TM,
+ WOACK_ERROR_ENC,
+};
+typedef enum rx_data_sack_error_t rx_data_sack_error_t;
+
+void
+rx_data_sack_error_test (test_t t, test_pbproc_t *tp,
+ rx_data_sack_error_t sack_error, ...)
+{
+ uint date = 123456;
+ test_within (t);
+ uint sack_uniform[] = {
+ PBPROC_FC_SACKI_UNIFORM_TMI_RESTART,
+ PBPROC_FC_SACKI_UNIFORM_TMI_RESTART,
+ PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO,
+ PBPROC_FC_SACKI_UNIFORM_TMI_DEFAULT_ROBO,
+ PBPROC_FC_SACKI_UNIFORM_NEK_ERROR,
+ PBPROC_FC_SACKI_UNIFORM_NEK_ERROR,
+ PBPROC_FC_SACKI_UNIFORM_NEK_ERROR,
+ PBPROC_FC_SACKI_UNIFORM_ALL_ERROR,
+ PBPROC_FC_SACKI_UNIFORM_ALL_ERROR,
+ };
+ uint symb_nb;
+ if (sack_error == SACK_ERROR_EMPTY)
+ {
+ va_list ap;
+ va_start (ap, sack_error);
+ symb_nb = va_arg (ap, uint);
+ va_end (ap);
+ }
+ else
+ symb_nb = 38;
+ const uint fl_tck = MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK;
+ bool sta = false;
+ if (sack_error == SACK_ERROR_TM_TMI_UNAVAILABLE
+ || sack_error == SACK_ERROR_ENC_STA_NO_NEK)
+ {
+ mac_store_sta_add (tp->store, 5);
+ sta = true;
+ }
+ uint tmi, eks;
+ if (sack_error == SACK_ERROR_TM_TMI_UNAVAILABLE
+ || sack_error == SACK_ERROR_TM_STA_UNAVAILABLE
+ || sack_error == SACK_ERROR_TM_UNASSOCIATED
+ || sack_error == SACK_ERROR_TM_BCAST
+ || sack_error == WOACK_ERROR_TM)
+ {
+ tmi = 5;
+ eks = 0xf;
+ }
+ else if (sack_error == SACK_ERROR_POOL_SHORTAGE)
+ {
+ tmi = PHY_MOD_ROBO;
+ eks = 0xf;
+ }
+ else
+ {
+ tmi = PHY_MOD_ROBO;
+ eks = 2;
+ }
+ bool wack = !(sack_error == WOACK_ERROR_TM
+ || sack_error == WOACK_ERROR_ENC);
+ bool unassociated = sack_error == SACK_ERROR_TM_UNASSOCIATED
+ || sack_error == SACK_ERROR_ENC_UNASSOCIATED;
+ tp->config.tei = (wack)?1:5;
+ pbproc_fc_sof_t fc = {
+ .dt_av = PBPROC_FC_DT_SOF,
+ .access = false,
+ .snid = tp->snid,
+ .direction = wack,
+ .dtei = wack ? (unassociated ? 0 : 5) : 0xff,
+ .lid = 1,
+ .eks = eks,
+ .pbsz = false,
+ .num_sym = MIN (symb_nb, 3u),
+ .tmi_av = tmi,
+ .fl_av = MAC_TCK_TO_FL (fl_tck),
+ .mpdu_cnt = 0,
+ .burst_cnt = 0,
+ .bbf = false,
+ .mrdur_fl = 0,
+ .mcf = !wack || sack_error == SACK_ERROR_TM_BCAST,
+ .mnbf = false,
+ .fccs_av = 0,
+ };
+ uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_FL_TO_TCK (MAC_TCK_TO_FL (fl_tck));
+ test_pbproc_check_stats_reset (tp);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .slot_count = 2,
+ .fc_av = PARENT_OF (pbproc_fc_t, sof, &fc)->words),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT_COND (wack, phy_tx_param_short,
+ .fc_mode = PHY_FC_MODE_AV_1),
+ SCENARIO_EVENT_COND (wack, phy_tx_frame, .date = date + pre_fc_fl_tck,
+ .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CIFS_TCK),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ scenario_run (t, entries, &globals);
+ /* Check stats. */
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = 1,
+ .rx_handle_fc = 1,
+ .rx_data = 1,
+ .rx_data_error = 1,
+ .rx_data_empty = sack_error == SACK_ERROR_EMPTY ? 1 : 0,
+ .rx_pool_shortage = sack_error == SACK_ERROR_POOL_SHORTAGE ? 1 : 0);
+ /* Check SACK. */
+ if (wack)
+ {
+ pbproc_fc_sack_t sack = PARENT_OF (pbproc_fc_t, words,
+ tp->pbproc->phy->tx_fc)->sack;
+ test_fail_unless (sack.dt_av == PBPROC_FC_DT_SACK);
+ test_fail_unless (sack.access == false);
+ test_fail_unless (sack.snid == tp->snid);
+ test_fail_unless (sack.dtei == (unassociated ? 0 : 5));
+ test_fail_unless (sack.cfs == tp->pbproc->access.cfp);
+ test_fail_unless (sack.bdf == false);
+ test_fail_unless (sack.svn == 0);
+ test_fail_unless (sack.rrtf == 0);
+ test_fail_unless (sack.mfs_rsp_data == MFS_FSM_RSP_ACK);
+ test_fail_unless (sack.mfs_rsp_mgmt == MFS_FSM_RSP_ACK);
+ test_fail_unless (sack.sackt3 == PBPROC_FC_SACKT_NOT_RECEIVED);
+ test_fail_unless (sack.sackt2 == PBPROC_FC_SACKT_NOT_RECEIVED);
+ test_fail_unless (sack.sackt1 == PBPROC_FC_SACKT_NOT_RECEIVED);
+ test_fail_unless (sack.sackt0 == PBPROC_FC_SACKT_UNIFORM);
+ test_fail_unless (sack.sacki[0] == sack_uniform[sack_error]);
+ test_fail_unless (sack.sacki[1] == 0);
+ test_fail_unless (sack.sacki_last
+ == MFS_RX_WINDOW_SIZE_DATA_DEFAULT_ENCODED << 4);
+ }
+ /* Cleanup. */
+ if (sta)
+ dbg_check (mac_store_sta_remove (tp->store, 5));
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+rx_data_fc10 (test_t t, test_pbproc_t *tp, u32 fc10, bool crc_error,
+ uint length, bool hp10_detected, bool hp11_detected)
+{
+ test_within (t);
+ uint date = 12345678;
+ test_pbproc_check_stats_reset (tp);
+ bool hp10_was_detected = tp->pbproc->detect.hp10_detected;
+ bool hp11_was_detected = tp->pbproc->detect.hp11_detected;
+ tp->pbproc->detect.hp10_detect_date = 0x12345678;
+ tp->pbproc->detect.hp11_detect_date = 0x01234567;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .fc_av = NULL, .fc10 = fc10),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT_COND (length, ca_access_vcs_restart,
+ .end_date = date + length
+ + MAC_HP10_PREAMBLE_DELTA_TCK),
+ SCENARIO_EVENT_COND (!length, ca_access_vcs_restart_eifs,
+ .start_date = date),
+ SCENARIO_EVENT_COND (!length, phy_rx_activate, .now = false,
+ .date = date + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + PHY_RX_ACTIVATE_DELAY_AFTER_SHORT_TCK,
+ .pre_detection = true),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = 1,
+ .rx_handle_fc = 1,
+ .rx_nfu = crc_error ? 0 : 1,
+ .rx_crc_error = crc_error ? 1 : 0,
+ );
+ test_fail_unless (!hp10_detected
+ || tp->pbproc->detect.hp10_detect_date == date);
+ test_fail_unless (tp->pbproc->detect.hp10_detected == (hp10_detected ||
+ hp10_was_detected));
+ test_fail_unless (!hp11_detected
+ || tp->pbproc->detect.hp11_detect_date == date);
+ test_fail_unless (tp->pbproc->detect.hp11_detected == (hp11_detected ||
+ hp11_was_detected));
+ tp->pbproc->detect.hp10_detected = false;
+ tp->pbproc->detect.hp11_detected = false;
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+rx_data_errors_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "errors");
+ test_pbproc_init (&tp);
+ tp.config.tei = 1; /* Test STA->CCO direction */
+ test_begin (t, "crc error")
+ {
+ uint date = 12345678;
+ test_pbproc_check_stats_reset (&tp);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date,
+ .rx_sysdate = date * 21 / 20,
+ .prp_won = false, .fc_av = NULL),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart, .
+ end_date = date + MAC_FL_TO_TCK (MAC_MAX_FL_MIN_FL)),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + PHY_RX_ACTIVATE_DELAY_AFTER_SHORT_TCK,
+ .pre_detection = true),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = &tp,
+ };
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (
+ t, &tp,
+ .prp_lost = 1,
+ .rx_handle_fc = 1,
+ .rx_crc_error = 1,
+ );
+ test_fail_unless (tp.pbproc->fsm.current_state
+ == PBPROC_FSM_STATE_IDLE);
+ } test_end;
+ /* SOF with response: wait for EOF.
+ * SOF without response: wait for EOF unless hp1x is detected yet, in this
+ * case use frame length to resynchronise. */
+ /*
+ test_begin (t, "fc10 sof")
+ {
+ rx_data_fc10 (t, &tp, 0x0000a0ab, true, 0, false, false);
+ rx_data_fc10 (t, &tp, 0x0020a0ab, true, 0, false, false);
+ } test_end;
+ test_begin (t, "fc10 sof, hp1x detected")
+ {
+ tp.pbproc->detect.hp10_detected = true;
+ rx_data_fc10 (t, &tp, 0x0000a0ab, false, MAC_HP10_DELIMITER_TCK
+ + (20 + 5 * 20) * MAC_HP10_SYMBOL_TCK + MAC_HP10_EFG_TCK
+ + MAC_HP10_DELIMITER_TCK + MAC_HP10_CIFS_TCK, false,
+ false);
+ tp.pbproc->detect.hp10_detected = true;
+ rx_data_fc10 (t, &tp, 0x0020a0ab, true, 0, false, false);
+ tp.pbproc->detect.hp11_detected = true;
+ rx_data_fc10 (t, &tp, 0x0000a0ab, false, MAC_HP10_DELIMITER_TCK
+ + (20 + 5 * 20) * MAC_HP10_SYMBOL_TCK + MAC_HP10_EFG_TCK
+ + MAC_HP10_DELIMITER_TCK + MAC_HP10_CIFS_TCK, false,
+ false);
+ tp.pbproc->detect.hp11_detected = true;
+ rx_data_fc10 (t, &tp, 0x0020a0ab, true, 0, false, false);
+ } test_end;
+ */
+ /* EOF with response, detect and synchronise. */
+ /*
+ test_begin (t, "fc10 hp10 eof with response")
+ {
+ rx_data_fc10 (t, &tp, 0x006000ab, false, MAC_HP10_DELIMITER_TCK
+ + MAC_HP10_RIFS_TCK + MAC_HP10_DELIMITER_TCK
+ + MAC_HP10_CIFS_TCK, true, false);
+ } test_end;
+ test_begin (t, "fc10 hp11 eof with response")
+ {
+ rx_data_fc10 (t, &tp, 0x006001ab, false, MAC_HP10_DELIMITER_TCK
+ + MAC_HP10_RIFS_TCK + MAC_HP10_DELIMITER_TCK
+ + MAC_HP10_CIFS_TCK, false, true);
+ rx_data_fc10 (t, &tp, 0x006011ab, false, MAC_HP10_DELIMITER_TCK
+ + MAC_HP10_RIFS_TCK + MAC_HP10_DELIMITER_TCK
+ + MAC_HP10_CIFS_TCK, false, true);
+ } test_end;
+ */
+ /* EOF without response, detect and EIFS (too late to synchronise). */
+ /*
+ test_begin (t, "fc10 hp10 eof without response")
+ {
+ rx_data_fc10 (t, &tp, 0x004800ab, false, 0, true, false);
+ } test_end;
+ test_begin (t, "fc10 hp11 eof without response")
+ {
+ rx_data_fc10 (t, &tp, 0x005811ab, false, 0, false, true);
+ } test_end;
+ */
+ /* Other FC10. */
+ /*
+ test_begin (t, "fc10 none")
+ {
+ rx_data_fc10 (t, &tp, 0x004400ab, true, 0, false, false);
+ rx_data_fc10 (t, &tp, 0x004401ab, true, 0, false, false);
+ rx_data_fc10 (t, &tp, 0x002000ab, true, 0, false, false);
+ rx_data_fc10 (t, &tp, 0, true, 0, false, false);
+ } test_end;
+ */
+ test_begin (t, "unknown fc")
+ {
+ uint date = 654879;
+ pbproc_fc_generic_t fc = {
+ .dt_av = 0x7,
+ .access = false,
+ .snid = tp.snid,
+ };
+ test_pbproc_check_stats_reset (&tp);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date,
+ .rx_sysdate = date * 21 / 20,
+ .prp_won = false,
+ .fc_av = PARENT_OF (pbproc_fc_t, generic,
+ &fc)->words),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart, .
+ end_date = date + MAC_FL_TO_TCK (MAC_MAX_FL_MIN_FL)),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + PHY_RX_ACTIVATE_DELAY_AFTER_SHORT_TCK,
+ .pre_detection = true),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = &tp,
+ };
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (
+ t, &tp,
+ .prp_lost = 1,
+ .rx_handle_fc = 1,
+ .rx_fc_unknown = 1,
+ );
+ test_fail_unless (tp.pbproc->fsm.current_state
+ == PBPROC_FSM_STATE_IDLE);
+ } test_end;
+ test_begin (t, "nfu sack")
+ {
+ rx_data_nfu_test (t, &tp, 123546, NFU_SACK);
+ } test_end;
+ test_begin (t, "nfu sof")
+ {
+ rx_data_nfu_test (t, &tp, 12354, NFU_SOF_ACCESS);
+ rx_data_nfu_test (t, &tp, 1235, NFU_SOF_SNID);
+ rx_data_nfu_test (t, &tp, 123, NFU_SOF_TEI);
+ } test_end;
+ test_begin (t, "nfu sof unassoc")
+ {
+ rx_data_nfu_test (t, &tp, 123, NFU_SOF_UNASSOC_SNID);
+ } test_end;
+ test_begin (t, "nfu out of alloc")
+ {
+ rx_data_nfu_test (t, &tp, 12354, NFU_OUT_OF_ALLOC);
+ } test_end;
+ test_begin (t, "nfu rsof wrong station")
+ {
+ rx_data_nfu_test (t, &tp, 12354, NFU_RSOF_WRONG_STATION);
+ } test_end;
+ test_begin (t, "sack error invalid tm")
+ {
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_TM_TMI_UNAVAILABLE);
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_TM_STA_UNAVAILABLE);
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_TM_UNASSOCIATED);
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_TM_BCAST);
+ } test_end;
+ test_begin (t, "sack error encryption")
+ {
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_ENC_STA_NO_NEK);
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_ENC_NO_EKS);
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_ENC_UNASSOCIATED);
+ } test_end;
+ test_begin (t, "pool shortage")
+ {
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_POOL_SHORTAGE);
+ } test_end;
+ test_begin (t, "woack error invalid tm")
+ {
+ rx_data_sack_error_test (t, &tp, WOACK_ERROR_TM);
+ } test_end;
+ test_begin (t, "woack error encryption")
+ {
+ rx_data_sack_error_test (t, &tp, WOACK_ERROR_ENC);
+ } test_end;
+ test_begin (t, "beacon nfu pool shortage")
+ {
+ rx_beacon_nfu_test (t, &tp, NFU_POOL_SHORTAGE);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+rx_data_fl_av_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "fl_av");
+ test_pbproc_init (&tp);
+ test_begin (t, "robo classic")
+ {
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 19, .pb_nb = 1, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 38, .pb_nb = 2, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 57, .pb_nb = 3, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 76, .pb_nb = 4, .tmi = PHY_MOD_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 95, .pb_nb = 5, .tmi = PHY_MOD_ROBO)));
+ } test_end;
+ test_begin (t, "robo weird")
+ {
+ uint symb_nb;
+ for (symb_nb = 20; symb_nb < 110; symb_nb++)
+ {
+ if (symb_nb % 19 == 0)
+ continue;
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = symb_nb, .real_symb_nb = symb_nb / 19 * 19,
+ .pb_nb = symb_nb / 19, .tmi = PHY_MOD_ROBO)));
+ }
+ } test_end;
+ test_begin (t, "robo weird no seg")
+ {
+ uint symb_nb;
+ for (symb_nb = 1; symb_nb < 19; symb_nb++)
+ rx_data_sack_error_test (t, &tp, SACK_ERROR_EMPTY, symb_nb);
+ } test_end;
+ test_begin (t, "hs-robo classic")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 10, .pb_nb = 1, .tmi = PHY_MOD_HS_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 20, .pb_nb = 2, .tmi = PHY_MOD_HS_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 30, .pb_nb = 3, .tmi = PHY_MOD_HS_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 40, .pb_nb = 4, .tmi = PHY_MOD_HS_ROBO)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 50, .pb_nb = 5, .tmi = PHY_MOD_HS_ROBO)));
+ } test_end;
+ test_begin (t, "hs-robo weird")
+ {
+ uint symb_nb;
+ for (symb_nb = 11; symb_nb < 59; symb_nb++)
+ {
+ if (symb_nb % 10 == 0)
+ continue;
+ rx_data_burst_test (
+ t, &tp, .prp_won = false, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = symb_nb, .real_symb_nb = symb_nb / 10 * 10,
+ .pb_nb = symb_nb / 10, .tmi = PHY_MOD_HS_ROBO)));
+ }
+ } test_end;
+ test_begin (t, "tm classic")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 2, .pb_nb = 1, .tmi = 5, .tm_mod = 4)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 3, .pb_nb = 2, .tmi = 5, .tm_mod = 4)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 5, .pb_nb = 3, .tmi = 5, .tm_mod = 4)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 6, .pb_nb = 4, .tmi = 5, .tm_mod = 4)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 8, .pb_nb = 5, .tmi = 5, .tm_mod = 4)));
+ } test_end;
+ test_begin (t, "tm weird")
+ {
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 4, .real_symb_nb = 3, .pb_nb = 2,
+ .tmi = 5, .tm_mod = 4)));
+ rx_data_burst_test (
+ t, &tp, .pool_pb_nb = 5, .wack = true,
+ MPDU ((.symb_nb = 7, .real_symb_nb = 6, .pb_nb = 4,
+ .tmi = 5, .tm_mod = 4)));
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+rx_data_budget_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "budget");
+ test_pbproc_init (&tp);
+ test_begin (t, "overflow")
+ {
+ int i;
+ /* Fill RX queue. */
+ for (i = 0; i < 3; i++)
+ {
+ pb_beacon_t *pbb = PARENT_OF (pb_beacon_t, blk,
+ blk_alloc_desc ());
+ slist_push_back (tp.pbproc->commit.rx_beacon_, pbb);
+ }
+ for (i = 0; i < 3; i++)
+ {
+ pbproc_rx_desc_t *rx = PARENT_OF (pbproc_rx_desc_t, blk,
+ blk_alloc_desc ());
+ rx->rx->pb_nb = 0;
+ rx->rx->pb_first = rx->rx->pb_last = NULL;
+ rx->rx->chandata_nb = 0;
+ rx->rx->chandata_first = NULL;
+ rx->rx->params.lid = 0;
+ rx->rx->params.fl_tck = 0;
+ rx->rx->params.pending_seg_info = 0;
+ rx->rx->params.pb_size = 0;
+ rx->rx->params.mpdu_cnt = 0;
+ rx->rx->params.mfs_cmd_data = 0;
+ rx->rx->params.mfs_cmd_mme = 0;
+ slist_push_back (tp.pbproc->commit.rx_, rx);
+ }
+ /* Trigger a deferred callback. */
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_deferred),
+ SCENARIO_EVENT (pbproc_rx_beacon_cb,
+ .duration_tck = MAC_MS_TO_TCK (2)),
+ SCENARIO_EVENT (pbproc_rx_beacon_cb,
+ .duration_tck = MAC_MS_TO_TCK (2)),
+ SCENARIO_EVENT (pbproc_rx_cb, .pb_nb = 0, .chandata_nb = 0,
+ .lid = 0, .fl_tck = 0, .pending_seg_info = 0,
+ .pb_size = 0, .mpdu_cnt = 0,
+ .mfs_cmd_data = 0, .mfs_cmd_mme = 0,
+ .duration_tck = MAC_MS_TO_TCK (7)),
+ SCENARIO_EVENT (pbproc_rx_cb, .pb_nb = 0, .chandata_nb = 0,
+ .lid = 0, .fl_tck = 0, .pending_seg_info = 0,
+ .pb_size = 0, .mpdu_cnt = 0,
+ .mfs_cmd_data = 0, .mfs_cmd_mme = 0,
+ .duration_tck = MAC_MS_TO_TCK (7)),
+ SCENARIO_EVENT (phy_deferred_schedule),
+ SCENARIO_EVENT (pbproc_rx_beacon_cb,
+ .duration_tck = MAC_MS_TO_TCK (2)),
+ SCENARIO_EVENT (pbproc_rx_cb, .pb_nb = 0, .chandata_nb = 0,
+ .lid = 0, .fl_tck = 0, .pending_seg_info = 0,
+ .pb_size = 0, .mpdu_cnt = 0,
+ .mfs_cmd_data = 0, .mfs_cmd_mme = 0,
+ .duration_tck = MAC_MS_TO_TCK (7)),
+ SCENARIO_END
+ };
+
+ scenario_globals_t globals = {
+ .tp = &tp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (tp.pbproc->fsm.current_state
+ == PBPROC_FSM_STATE_IDLE);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+rx_data_test_suite (test_t t)
+{
+ test_suite_begin (t, "rx data");
+ rx_data_basic_test_case (t);
+ /* rx_data_burst_test_case (t); */
+ rx_data_errors_test_case (t);
+ rx_data_fl_av_test_case (t);
+ rx_data_budget_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/rx_sound.c b/cesar/mac/pbproc/test/pbproc_eoc/src/rx_sound.c
new file mode 100644
index 0000000000..d61c8b35c0
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/rx_sound.c
@@ -0,0 +1,353 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/rx_sound.c
+ * \brief RX SOUND automaton test
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "inc/utils.h"
+
+#include "inc/test_pbproc.h"
+
+#include "mac/common/timings.h"
+#include "hal/phy/inc/context.h"
+
+void
+rx_sound_test (test_t t, test_pbproc_t *tp, u32 date, uint chandata_nb,
+ uint pool_pb_nb, uint tmi, uint burst, bool scf)
+{
+ uint i;
+ test_within (t);
+ const uint lid = 1;
+ /* Prepare ctx reception status. */
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ prep->valid = true;
+ prep->bbf = true;
+ prep->dtei = 25;
+ /* Prepare tone map. */
+ dbg_assert (tmi == PHY_MOD_ROBO || tmi == PHY_MOD_MINI_ROBO);
+ tonemap_t *tm = &tp->config.tonemask_info.tonemap_robo[tmi];
+ dbg_assert (tm->gil == PHY_GIL_417 || tm->gil == PHY_GIL_567);
+ uint dx = tm->gil == PHY_GIL_417 ? MAC_DX417_TCK : MAC_DX567_TCK;
+ uint rifs_tck = burst ? MAC_BIFS_TCK : MAC_RIFS_DEFAULT_TCK;
+ phy_pb_size_t pb_size = tmi == PHY_MOD_ROBO ? PHY_PB_SIZE_520
+ : PHY_PB_SIZE_136;
+ /* Prepare channel data configuration. */
+ u32 chandata_conf[chandata_nb];
+ bool chandata = false;
+ if (chandata_nb)
+ {
+ for (i = 0; i < chandata_nb; i++)
+ chandata_conf[i] = i;
+ pbproc_set_chandata_conf (tp->pbproc,
+ (phy_chandata_conf_t *) chandata_conf,
+ chandata_nb, false);
+ if (pool_pb_nb >= chandata_nb)
+ chandata = true;
+ }
+ /* Compute frame size. */
+ uint symb_nb = (1 * tm->bits_per_pb[pb_size] + tm->bits_per_symbol - 1)
+ / tm->bits_per_symbol;
+ /* Prepare FC. */
+ const uint fl_tck = MAC_PAYLOAD_TCK (symb_nb, dx)
+ + rifs_tck;
+ pbproc_fc_sound_t sound_fc = {
+ .dt_av = PBPROC_FC_DT_SOUND,
+ .access = false,
+ .snid = tp->snid,
+ .direction = 1,
+ .dtei = 25,
+ .lid = lid,
+ .pbsz = pb_size == PHY_PB_SIZE_136,
+ .saf = false,
+ .scf = false,
+ .req_tm = 7,
+ .fl_av = MAC_TCK_TO_FL (fl_tck),
+ .mpdu_cnt = burst,
+ .src = TONEMAP_SRC_INITIAL,
+ .fccs_av = 0,
+ };
+ const uint rx_fl_tck = MAC_FL_TO_TCK (MAC_TCK_TO_FL (fl_tck));
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + rx_fl_tck;
+ /* Reset stats. */
+ test_pbproc_check_stats_reset (tp);
+ /* Scenario. */
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .slot_count = 2,
+ .fc_av = PARENT_OF (pbproc_fc_t, sound,
+ &sound_fc)->words),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT_COND (chandata, phy_rx_prepare_sound, .nb_pb = 1,
+ .mod = tmi, .fecrate = tm->fecrate,
+ .pb_size = pb_size, .gil = tm->gil,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT_COND (chandata, phy_pbdma_start_chandata),
+ SCENARIO_EVENT_COND (!chandata, phy_rx_prepare_short),
+ SCENARIO_EVENT_COND (!burst, ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_CIFS_TCK),
+ SCENARIO_EVENT_COND (burst, ca_access_vcs_restart_eifs,
+ .start_date = date + pre_fc_fl_tck),
+ SCENARIO_EVENT_COND (burst, phy_rx_activate, .now = false,
+ .date = date + pre_fc_fl_tck
+ + PHY_RX_ACTIVATE_DELAY_AFTER_BURST_TCK,
+ .pre_detection = true),
+ SCENARIO_ACTION_COND (chandata, phy_pbdma, .end_chandata = true),
+ SCENARIO_EVENT_COND (!burst, phy_tx_param_short,
+ .fc_mode = PHY_FC_MODE_AV_1),
+ SCENARIO_EVENT_COND (!burst, phy_tx_frame,
+ .date = date + pre_fc_fl_tck, .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT_COND (chandata, pbproc_rx_cb, .pb_nb = 0,
+ .chandata_nb = chandata ? chandata_nb : 0,
+ .lid = lid,
+ .fl_tck = rx_fl_tck,
+ .pending_seg_info = 0,
+ .pb_size = pb_size,
+ .mpdu_cnt = burst,
+ .mfs_cmd_data = MFS_FSM_CMD_NOP,
+ .mfs_cmd_mme = MFS_FSM_CMD_NOP),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ /* Allocate PB pool. */
+ blk_t *first, *last;
+ first = blk_alloc_desc_range (1 + pool_pb_nb, &last);
+ pbproc_rx_segment_refill (tp->pbproc, PARENT_OF (pb_t, blk, first),
+ PARENT_OF (pb_t, blk, last), 1 + pool_pb_nb);
+ /* Run scenario. */
+ scenario_run (t, entries, &globals);
+ /* Check pool. */
+ test_fail_unless (tp->pbproc->rx_pool_size == 1 + pool_pb_nb
+ - (chandata ? 1 + chandata_nb : 0));
+ /* Check SOUND ACK. */
+ if (!burst)
+ {
+ pbproc_fc_sound_t ack = PARENT_OF (pbproc_fc_t, words,
+ tp->pbproc->phy->tx_fc)->sound;
+ test_fail_unless (ack.dt_av == PBPROC_FC_DT_SOUND);
+ test_fail_unless (ack.access == false);
+ test_fail_unless (ack.snid == tp->snid);
+ test_fail_unless (ack.dtei == sound_fc.dtei);
+ test_fail_unless (ack.direction == 0);
+ test_fail_unless (ack.lid == lid);
+ test_fail_unless (ack.pbsz == false);
+ test_fail_unless (ack.saf == true);
+ test_fail_unless (ack.scf == scf);
+ test_fail_unless (ack.req_tm == 0);
+ test_fail_unless (ack.fl_av == 0);
+ test_fail_unless (ack.mpdu_cnt == 0);
+ test_fail_unless (ack.src == 0);
+ }
+ /* Check stats. */
+ test_pbproc_check_stats (t, tp,
+ .prp_lost = 1,
+ .rx_handle_fc = 1,
+ .rx_sound = 1,
+ .rx_sound_complete = scf && chandata ? 1 : 0,
+ .rx_sound_drop = chandata ? 0 : 1);
+ /* Check return to IDLE state. */
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ /* Cleanup. */
+ if (tp->pbproc->rx_pool_size)
+ {
+ blk_release_desc_range (&tp->pbproc->rx_pool_head->blk,
+ &tp->pbproc->rx_pool_tail->blk);
+ slist_init (tp->pbproc->rx_pool_, paste_size);
+ }
+ if (chandata_nb)
+ pbproc_set_chandata_conf (tp->pbproc, NULL, 0, false);
+}
+
+void
+rx_sound_basic_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic");
+ test_pbproc_init (&tp);
+ test_begin (t, "robo")
+ {
+ rx_sound_test (t, &tp, 123456, 11, 11, PHY_MOD_ROBO, 0, true);
+ rx_sound_test (t, &tp, 123456, 11, 12, PHY_MOD_ROBO, 0, true);
+ } test_end;
+ test_begin (t, "mini-robo")
+ {
+ rx_sound_test (t, &tp, 1234567, 6, 6, PHY_MOD_MINI_ROBO, 0, true);
+ rx_sound_test (t, &tp, 1234567, 6, 7, PHY_MOD_MINI_ROBO, 0, true);
+ } test_end;
+ test_begin (t, "sound complete")
+ {
+ uint i;
+ utils_sta_prepare_default_tonemap (&tp, false, 25, PHY_MOD_ROBO, 0, 0,
+ NULL);
+ for (i = 0; i < TONEMAP_SOUND_FRAME_COUNTER - 1; i++)
+ rx_sound_test (t, &tp, 123456, 11, 11, PHY_MOD_ROBO, 0, false);
+ rx_sound_test (t, &tp, 123456, 11, 11, PHY_MOD_ROBO, 0, true);
+ rx_sound_test (t, &tp, 123456, 11, 11, PHY_MOD_ROBO, 0, true);
+ dbg_check (mac_store_sta_remove (tp.store, 25));
+ } test_end;
+ /*
+ test_begin (t, "burst")
+ {
+ rx_sound_test (t, &tp, 123456, 11, 11, PHY_MOD_ROBO, 1, true);
+ rx_sound_test (t, &tp, 123456, 11, 11, PHY_MOD_MINI_ROBO, 1, true);
+ } test_end;
+ */
+ test_begin (t, "no chandata")
+ {
+ rx_sound_test (t, &tp, 123456, 0, 1, PHY_MOD_ROBO, 0, true);
+ rx_sound_test (t, &tp, 123456, 0, 1, PHY_MOD_MINI_ROBO, 0, true);
+ } test_end;
+ test_begin (t, "woack no chandata")
+ {
+ rx_sound_test (t, &tp, 123456, 0, 1, PHY_MOD_ROBO, 1, true);
+ rx_sound_test (t, &tp, 123456, 0, 1, PHY_MOD_MINI_ROBO, 1, true);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+enum rx_sound_nfu_t
+{
+ NFU_OUT_OF_ALLOC,
+ NFU_POOL_SHORTAGE,
+ NFU_WRONG_STATION,
+};
+typedef enum rx_sound_nfu_t rx_sound_nfu_t;
+
+void
+rx_sound_nfu_test (test_t t, test_pbproc_t *tp, u32 date, rx_sound_nfu_t nfu)
+{
+ test_within (t);
+ u32 restart_date;
+ uint length_tck;
+ /* Prepare context. */
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ prep->valid = true;
+ prep->bbf = true;
+ prep->dtei = nfu == NFU_WRONG_STATION ? 100 : 25;
+ /* Use another state to test return to IDLE. */
+ tp->pbproc->fsm.current_state = PBPROC_FSM_STATE_RX_BURST;
+ /* Prepare channel data configuration. */
+ const uint chandata_nb = 3;
+ u32 chandata_conf[chandata_nb];
+ uint i;
+ for (i = 0; i < chandata_nb; i++)
+ chandata_conf[i] = i;
+ pbproc_set_chandata_conf (tp->pbproc,
+ (phy_chandata_conf_t *) chandata_conf,
+ chandata_nb, false);
+ /* Compute frame size. */
+ tonemap_t *tm = &tp->config.tonemask_info.tonemap_robo[PHY_MOD_ROBO];
+ uint symb_nb = (1 * tm->bits_per_pb[PHY_PB_SIZE_520]
+ + tm->bits_per_symbol - 1) / tm->bits_per_symbol;
+ const uint fl_tck = MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK;
+ /* Prepare FC. Direction is STA->CCO. */
+ pbproc_fc_sound_t sound_fc = {
+ .dt_av = PBPROC_FC_DT_SOUND,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = 25,
+ .direction = 1,
+ .lid = 1,
+ .pbsz = false,
+ .saf = false,
+ .scf = false,
+ .req_tm = 7,
+ .fl_av = MAC_TCK_TO_FL (fl_tck),
+ .mpdu_cnt = 0,
+ .src = TONEMAP_SRC_INITIAL,
+ .fccs_av = 0,
+ };
+ /* Late set of date. */
+ prep->tx_date = date;
+ length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_FL_TO_TCK (MAC_TCK_TO_FL (fl_tck))
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK;
+ if (nfu == NFU_OUT_OF_ALLOC)
+ date = TEST_PBPROC_ALLOC_END_DATE + MAC_TOLERANCE_TCK
+ - length_tck + MAC_CIFS_TCK + 1;
+ restart_date = date + length_tck - MAC_PREAMBLE_TCK - MAC_FC_AV_TCK
+ - MAC_CIFS_TCK;
+ length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK;
+ tp->pbproc->rx_pool_size = nfu != NFU_POOL_SHORTAGE ? 4 : 3;
+ test_pbproc_check_stats_reset (tp);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date, .prp_won = false,
+ .slot_count = 2,
+ .fc_av = PARENT_OF (pbproc_fc_t, sound,
+ &sound_fc)->words),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = restart_date + length_tck),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = 0,
+ .rx_handle_fc = 1,
+ .rx_sound = nfu == NFU_WRONG_STATION ? 0 : 1,
+ .rx_nfu = nfu == NFU_WRONG_STATION ? 1 : 0,
+ .rx_out_of_alloc = nfu == NFU_OUT_OF_ALLOC ? 1 : 0,
+ .rx_pool_shortage = nfu == NFU_POOL_SHORTAGE ? 1 : 0);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ test_fail_unless (tp->pbproc->rx_pool_size == (nfu != NFU_POOL_SHORTAGE
+ ? 4 : 3));
+ tp->pbproc->rx_pool_size = 0;
+ pbproc_set_chandata_conf (tp->pbproc, NULL, 0, false);
+}
+
+void
+rx_sound_error_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "error");
+ test_pbproc_init (&tp);
+ test_begin (t, "nfu out of alloc")
+ {
+ rx_sound_nfu_test (t, &tp, 123456, NFU_OUT_OF_ALLOC);
+ } test_end;
+ test_begin (t, "nfu pool shortage")
+ {
+ rx_sound_nfu_test (t, &tp, 123456, NFU_POOL_SHORTAGE);
+ } test_end;
+ test_begin (t, "nfu wrong station")
+ {
+ rx_sound_nfu_test (t, &tp, 123456, NFU_WRONG_STATION);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+rx_sound_test_suite (test_t t)
+{
+ test_suite_begin (t, "rx sound");
+ rx_sound_basic_test_case (t);
+ rx_sound_error_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/scenario_defs.c b/cesar/mac/pbproc/test/pbproc_eoc/src/scenario_defs.c
new file mode 100644
index 0000000000..a024f336ed
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/scenario_defs.c
@@ -0,0 +1,166 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/scenario_defs.c
+ * \brief Scenario actions.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+#include "hal/phy/inc/context.h"
+#include "mac/ca/inc/context.h"
+
+void
+scenario_action_phy_rx_fc_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ scenario_action_phy_rx_fc_t *p = &params->action_phy_rx_fc;
+ ca_t *ca = globals->tp->ca;
+ phy_t *phy = globals->tp->pbproc->phy;
+ phy->rx_sysdate = p->rx_sysdate;
+ phy->prp_won = p->prp_won;
+ if (!p->prp_won)
+ ca->access_param.prp = true;
+ phy->slot_count = p->slot_count;
+ phy->fc10 = p->fc10 ? p->fc10 : (u32) -1;
+ /* Call callbacks. */
+ if (phy->rx_fc_cb (phy->user_data, p->rx_date, p->fc_av))
+ phy->deferred_cb (phy->user_data);
+ while (phy->dsr_scheduled)
+ {
+ phy->dsr_scheduled = false;
+ phy->deferred_cb (phy->user_data);
+ }
+}
+
+void
+scenario_action_phy_access_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ scenario_action_phy_access_t *p = &params->action_phy_access;
+ ca_t *ca = globals->tp->ca;
+ phy_t *phy = globals->tp->pbproc->phy;
+ /* Prepare parameters. */
+ ca->mfs = p->mfs;
+ if (p->access_param)
+ {
+ ca->access_param = *p->access_param;
+ phy->current_date = ca->access_param.access_date - PBPROC_ANTICIP_TCK
+ + p->delay_tck;
+ }
+ phy->prp_won = p->prp_won;
+ phy->slot_count = p->slot_count;
+ /* Call callbacks. */
+ if (phy->access_cb (phy->user_data))
+ phy->deferred_cb (phy->user_data);
+ while (phy->dsr_scheduled)
+ {
+ phy->dsr_scheduled = false;
+ phy->deferred_cb (phy->user_data);
+ }
+}
+
+void
+scenario_action_phy_access_conf_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ phy_t *phy = globals->tp->pbproc->phy;
+ /* Call callbacks. */
+ if (phy->access_conf_cb (phy->user_data))
+ phy->deferred_cb (phy->user_data);
+ while (phy->dsr_scheduled)
+ {
+ phy->dsr_scheduled = false;
+ phy->deferred_cb (phy->user_data);
+ }
+}
+
+void
+scenario_action_phy_pbdma_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ scenario_action_phy_pbdma_t *p = &params->action_phy_pbdma;
+ phy_t *phy = globals->tp->pbproc->phy;
+ /* Prepare parameters. */
+ phy_pbdma_status_t status;
+ *(u32 *) &status = 0;
+ status.pb_null = p->pb_null;
+ status.pb_crc_error = p->pb_crc_error;
+ status.pb_it = p->pb_it;
+ status.end_rx_pb = p->end_rx_pb;
+ status.end_tx_pb = p->end_tx_pb;
+ status.end_chandata = p->end_chandata;
+ status.null_pb_index = p->null_pb_index;
+ uint i;
+ if (p->crc_bitmap)
+ {
+ dbg_assert (p->crc_bitmap_bits < 256);
+ for (i = 0; i < p->crc_bitmap_bits / 32; i++)
+ phy->crc_bitmap[i] = p->crc_bitmap[i];
+ if (p->crc_bitmap_bits % 32 != 0)
+ {
+ phy->crc_bitmap[i] =
+ p->crc_bitmap[i] & BITS_ONES (p->crc_bitmap_bits % 32);
+ i++;
+ }
+ for (; i < COUNT (phy->crc_bitmap); i++)
+ phy->crc_bitmap[i] = 0;
+ }
+ else
+ for (i = 0; i < COUNT (phy->crc_bitmap); i++)
+ phy->crc_bitmap[i] = 0;
+ /* Call callbacks. */
+ if (phy->pbdma_cb (phy->user_data, *(u32 *) &status))
+ phy->deferred_cb (phy->user_data);
+ while (phy->dsr_scheduled)
+ {
+ phy->dsr_scheduled = false;
+ phy->deferred_cb (phy->user_data);
+ }
+}
+
+void
+scenario_action_phy_deferred_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ phy_t *phy = globals->tp->pbproc->phy;
+ /* Call callbacks. */
+ phy->deferred_cb (phy->user_data);
+ while (phy->dsr_scheduled)
+ {
+ phy->dsr_scheduled = false;
+ phy->deferred_cb (phy->user_data);
+ }
+}
+
+void
+scenario_action_phy_extra_timer_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ phy_t *phy = globals->tp->pbproc->phy;
+ /* Call callbacks. */
+ if (phy->extra_timer_cb (phy->user_data))
+ phy->deferred_cb (phy->user_data);
+ while (phy->dsr_scheduled)
+ {
+ phy->dsr_scheduled = false;
+ phy->deferred_cb (phy->user_data);
+ }
+}
+
+void
+scenario_action_pbproc_activate_cb (scenario_globals_t *globals,
+ scenario_params_t *params)
+{
+ scenario_action_pbproc_activate_t *p = &params->action_pbproc_activate;
+ pbproc_t *pbproc = globals->tp->pbproc;
+ /* Call function. */
+ pbproc_activate (pbproc, p->flag);
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/test_pbproc.c b/cesar/mac/pbproc/test/pbproc_eoc/src/test_pbproc.c
new file mode 100644
index 0000000000..eb9054f1f1
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/test_pbproc.c
@@ -0,0 +1,502 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_pbproc.c
+ * \brief PBProc test.
+ * \ingroup test
+ */
+#include "common/std.h"
+#include "config/av.h"
+
+#include "lib/trace.h"
+
+#include "inc/test_pbproc.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "hal/phy/inc/context.h"
+
+#include <string.h>
+
+void
+prep_mpdu_test_suite (test_t t);
+
+void
+tx_data_test_suite (test_t t);
+
+void
+tx_sound_test_suite (test_t t);
+
+void
+rx_data_test_suite (test_t t);
+
+void
+rx_sound_test_suite (test_t t);
+
+void
+rx_rts_cts_test_suite (test_t t);
+
+void
+test_pbproc_rx_cb (void *user, pbproc_rx_desc_t *rx_desc)
+{
+ dbg_assert_ptr (user);
+ dbg_assert_ptr (rx_desc);
+ pbproc_rx_t *rx = rx_desc->rx;
+ if (rx->pb_nb)
+ {
+ dbg_assert_ptr (rx->pb_first);
+ dbg_assert_ptr (rx->pb_last);
+ }
+ else
+ dbg_assert (rx->pb_first == NULL && rx->pb_last == NULL);
+ if (rx->chandata_nb)
+ dbg_assert_ptr (rx->chandata_first);
+ else
+ dbg_assert (rx->chandata_first == NULL);
+ scenario_event (pbproc_rx_cb, params, globals);
+ test_fail_unless (rx->pb_nb == params->pb_nb);
+ if (rx->pb_nb)
+ blk_release_desc_range (&rx->pb_first->blk, &rx->pb_last->blk);
+ test_fail_unless (rx->chandata_nb == params->chandata_nb);
+ if (rx->chandata_nb)
+ blk_release_desc_range_nb (&rx->chandata_first->blk, rx->chandata_nb);
+ /* TODO: more verifications. */
+ test_fail_unless (rx->params.lid == params->lid);
+ test_fail_unless (rx->params.fl_tck == params->fl_tck);
+ test_fail_unless (rx->params.pending_seg_info
+ == params->pending_seg_info);
+ test_fail_unless (rx->params.pb_size == params->pb_size);
+ test_fail_unless (rx->params.mpdu_cnt == params->mpdu_cnt);
+ /*test_fail_unless (rx->params.mfs_cmd_data == params->mfs_cmd_data);*/
+ test_fail_unless (rx->params.mfs_cmd_mme == params->mfs_cmd_mme);
+ /* This took time. */
+ globals->tp->pbproc->phy->current_date += params->duration_tck;
+ /* Done. */
+ blk_release_desc (&rx_desc->blk);
+}
+
+void
+test_pbproc_rx_beacon_cb (void *user, pb_beacon_t *pb,
+ pbproc_rx_beacon_params_t *params)
+{
+ dbg_assert_ptr (user);
+ dbg_assert_ptr (pb);
+ dbg_assert (params == (void *) (pb->data + MAC_PB136_BYTES));
+ scenario_event (pbproc_rx_beacon_cb, event_params, globals);
+ /* TODO: more verifications. */
+ /* This took time. */
+ globals->tp->pbproc->phy->current_date += event_params->duration_tck;
+ /* Done. */
+ blk_release_desc (&pb->blk);
+}
+
+void
+test_pbproc_init (test_pbproc_t *ctx)
+{
+ dbg_assert (ctx);
+ lib_rnd_init (ctx->rnd, 1234);
+ mac_config_init (&ctx->config);
+ mac_ntb_init (&ctx->config);
+ ctx->config.ntb_offset_tck = TEST_PBPROC_NTB_OFFSET_TCK;
+ ctx->config.tei = 1;
+ ctx->snid = 1;
+ ctx->config.seed = 42;
+ ctx->store = mac_store_init ();
+ ctx->pbproc = pbproc_init (&ctx->config, ctx->store);
+ pbproc_init_cb (ctx->pbproc, ctx, test_pbproc_rx_cb,
+ test_pbproc_rx_beacon_cb);
+ pbproc_get_phy (ctx->pbproc);
+ ctx->ca = pbproc_get_ca (ctx->pbproc);
+ ctx->pbproc->activated = true;
+ test_pbproc_alloc (ctx, false, 0);
+ test_pbproc_check_stats_reset (ctx);
+}
+
+void
+test_pbproc_alloc (test_pbproc_t *ctx, bool hybrid,
+ u32 beacon_period_start_date)
+{
+ dbg_assert (ctx);
+ ctx->pbproc->alloc.coexistence_mode = hybrid
+ ? MAC_COEXISTENCE_FULL_HYBRID_MODE : MAC_COEXISTENCE_AV_ONLY_MODE;
+ ctx->pbproc->alloc.hybrid = hybrid;
+ ctx->pbproc->alloc.merge = false;
+ ctx->pbproc->times = ctx->pbproc->times_array[PBPROC_TIMES_ARRAY_INDEX (
+ hybrid, ctx->pbproc->alloc.coexistence_mode)];
+ ctx->pbproc->alloc.end_date = TEST_PBPROC_ALLOC_END_DATE;
+ ctx->pbproc->alloc.aifs_date = TEST_PBPROC_ALLOC_END_DATE;
+ ctx->pbproc->alloc.beacon_period_start_date = beacon_period_start_date;
+}
+
+void
+test_pbproc_check_stats_ (test_t t, test_pbproc_t *ctx,
+ const pbproc_stat_t *stats)
+{
+ test_within (t);
+ dbg_assert (ctx);
+ dbg_assert (stats);
+#define TEST_PBPROC_CHECK_STAT(stat) \
+ test_fail_unless (ctx->pbproc->stats.stat == ctx->recorded_stats.stat \
+ + stats->stat, #stat ": %d", \
+ ctx->pbproc->stats.stat - ctx->recorded_stats.stat)
+ TEST_PBPROC_CHECK_STAT(rts_fail);
+ TEST_PBPROC_CHECK_STAT(prp_lost);
+ TEST_PBPROC_CHECK_STAT(cw_lost);
+ TEST_PBPROC_CHECK_STAT(aifs);
+ TEST_PBPROC_CHECK_STAT(rx_out_of_alloc);
+ TEST_PBPROC_CHECK_STAT(rx_rsof_out_of_alloc);
+ TEST_PBPROC_CHECK_STAT(rx_pool_shortage);
+ TEST_PBPROC_CHECK_STAT(rx_handle_fc);
+ TEST_PBPROC_CHECK_STAT(rx_beacon);
+ TEST_PBPROC_CHECK_STAT(rx_data);
+ TEST_PBPROC_CHECK_STAT(rx_data_wack);
+ TEST_PBPROC_CHECK_STAT(rx_data_woack);
+ TEST_PBPROC_CHECK_STAT(rx_data_burst_stop);
+ TEST_PBPROC_CHECK_STAT(rx_data_error);
+ TEST_PBPROC_CHECK_STAT(rx_data_empty);
+ TEST_PBPROC_CHECK_STAT(rx_data_bad_symb_nb);
+ TEST_PBPROC_CHECK_STAT(rx_sound);
+ TEST_PBPROC_CHECK_STAT(rx_sound_complete);
+ TEST_PBPROC_CHECK_STAT(rx_sound_drop);
+ TEST_PBPROC_CHECK_STAT(rx_nfu);
+ TEST_PBPROC_CHECK_STAT(rx_fc_unknown);
+ TEST_PBPROC_CHECK_STAT(rx_crc_error);
+ TEST_PBPROC_CHECK_STAT(tx_invalid);
+ TEST_PBPROC_CHECK_STAT(tx_late);
+ TEST_PBPROC_CHECK_STAT(tx_data);
+ TEST_PBPROC_CHECK_STAT(tx_data_cancel);
+ TEST_PBPROC_CHECK_STAT(tx_data_burst);
+ TEST_PBPROC_CHECK_STAT(tx_data_burst_interrupted);
+ TEST_PBPROC_CHECK_STAT(tx_data_wack);
+ TEST_PBPROC_CHECK_STAT(tx_data_woack);
+ TEST_PBPROC_CHECK_STAT(tx_data_beacon);
+ TEST_PBPROC_CHECK_STAT(tx_data_wack_ack);
+ TEST_PBPROC_CHECK_STAT(tx_data_wack_noack);
+ TEST_PBPROC_CHECK_STAT(tx_sound);
+ TEST_PBPROC_CHECK_STAT(tx_sound_ack);
+ TEST_PBPROC_CHECK_STAT(tx_sound_noack);
+}
+
+void
+test_pbproc_check_stats_reset (test_pbproc_t *ctx)
+{
+ dbg_assert (ctx);
+ ctx->recorded_stats = ctx->pbproc->stats;
+}
+
+void
+test_pbproc_uninit (test_pbproc_t *ctx)
+{
+ dbg_assert (ctx);
+ ctx->ca = NULL;
+ pbproc_uninit (ctx->pbproc);
+ ctx->pbproc = NULL;
+ mac_store_uninit (ctx->store);
+ ctx->store = NULL;
+}
+
+static void
+test_pbproc_aifs (test_t t, bool from_merge, bool to_merge)
+{
+ test_within (t);
+ test_pbproc_t ctx;
+ test_pbproc_init (&ctx);
+ ctx.pbproc->alloc.merge = from_merge;
+ ca_access_param_t access_param = {
+ .access_date = 0, .cw_start_date = 0, .aifs = true,
+ };
+ ctx.pbproc->detect.hp10_detected = true;
+ ctx.pbproc->detect.hp10_detect_date =
+ phy_date () - MAC_MS_TO_TCK (1900);
+ ctx.pbproc->detect.hp11_detected = true;
+ ctx.pbproc->detect.hp11_detect_date =
+ phy_date () - MAC_MS_TO_TCK (2900);
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = NULL,
+ .access_param = &access_param,
+ .prp_won = true, .slot_count = 64),
+ SCENARIO_EVENT_COND (!from_merge, phy_rx_activate, .now = true,
+ .pre_detection = false),
+ SCENARIO_EVENT_COND (!from_merge, ca_backoff_cancel),
+ SCENARIO_EVENT (ca_access_aifs,
+ .coexistence_mode =
+ MAC_COEXISTENCE_FULL_HYBRID_MODE,
+ .snid = ctx.snid, .hybrid = true, .merge = to_merge,
+ .nek_switch = 0),
+ SCENARIO_EVENT_COND (!to_merge, phy_rx_param,
+ .fc_mode = PHY_FC_MODE (true, 1)),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = &ctx,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (ctx.pbproc->fsm.current_state
+ == PBPROC_FSM_STATE_IDLE);
+ if (!to_merge)
+ test_fail_unless (memcmp (&ctx.pbproc->times,
+ &ctx.pbproc->times_array[true],
+ sizeof (pbproc_times_t)) == 0);
+#if !CONFIG_AV_ONLY_MODE
+ test_fail_unless (ctx.pbproc->detect.hp10_detected == true);
+ test_fail_unless (ctx.pbproc->detect.hp11_detected == false);
+#endif
+ ctx.pbproc->detect.hp10_detected = false;
+ ctx.pbproc->detect.hp11_detected = false;
+ test_pbproc_check_stats (t, &ctx, .aifs = 1);
+ test_pbproc_uninit (&ctx);
+}
+
+void
+test_pbproc_init_suite (test_t t)
+{
+ test_suite_begin (t, "init");
+ test_case_begin (t, "basic");
+ test_pbproc_t ctx;
+ test_begin (t, "init uninit")
+ {
+ test_pbproc_init (&ctx);
+ test_pbproc_uninit (&ctx);
+ test_pbproc_init (&ctx);
+ test_pbproc_uninit (&ctx);
+ } test_end;
+ test_begin (t, "rx segment refill")
+ {
+ test_pbproc_init (&ctx);
+ blk_t *first, *last;
+ first = blk_alloc_desc_range (10, &last);
+ pbproc_rx_segment_refill (ctx.pbproc, PB_FROM_BLK (first),
+ PB_FROM_BLK (last), 10);
+ first = blk_alloc_desc_range (10, &last);
+ pbproc_rx_segment_refill (ctx.pbproc, PB_FROM_BLK (first),
+ PB_FROM_BLK (last), 10);
+ test_pbproc_uninit (&ctx);
+ } test_end;
+ test_begin (t, "activate deactivate")
+ {
+ test_pbproc_init (&ctx);
+ ctx.pbproc->activated = false;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (pbproc_activate, .flag = true),
+ SCENARIO_EVENT (ca_access_activate, .date = 0,
+ .coexistence_mode = MAC_COEXISTENCE_AV_ONLY_MODE,
+ .snid = ctx.snid, .hybrid = false, .merge = false,
+ .nek_switch = 0),
+ SCENARIO_EVENT (phy_rx_param, .fc_mode = PHY_FC_MODE (false, 1)),
+ SCENARIO_EVENT (phy_rx_activate, .now = true,
+ .pre_detection = true),
+ SCENARIO_ACTION (pbproc_activate, .flag = false),
+ SCENARIO_EVENT (phy_rx_activate, .now = true,
+ .pre_detection = false),
+ SCENARIO_EVENT (ca_access_deactivate),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = &ctx,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (memcmp (&ctx.pbproc->times,
+ &ctx.pbproc->times_array[false],
+ sizeof (pbproc_times_t)) == 0);
+ test_pbproc_uninit (&ctx);
+ } test_end;
+ test_begin (t, "activate hybrid")
+ {
+ test_pbproc_init (&ctx);
+ ctx.pbproc->activated = false;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (pbproc_activate, .flag = true),
+ SCENARIO_EVENT (ca_access_activate, .date = 0,
+ .coexistence_mode =
+ MAC_COEXISTENCE_FULL_HYBRID_MODE,
+ .snid = ctx.snid, .hybrid = true, .merge = false,
+ .nek_switch = 0),
+ SCENARIO_EVENT (phy_rx_param, .fc_mode = PHY_FC_MODE (true, 1)),
+ SCENARIO_EVENT (phy_rx_activate, .now = true,
+ .pre_detection = true),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = &ctx,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (memcmp (&ctx.pbproc->times,
+ &ctx.pbproc->times_array[true],
+ sizeof (pbproc_times_t)) == 0);
+ test_pbproc_uninit (&ctx);
+ } test_end;
+ test_begin (t, "aifs")
+ {
+ test_pbproc_aifs (t, false, false);
+ } test_end;
+ test_begin (t, "aifs merged")
+ {
+ test_pbproc_aifs (t, true, true);
+ } test_end;
+ test_begin (t, "aifs to merged")
+ {
+ test_pbproc_aifs (t, false, true);
+ } test_end;
+ test_begin (t, "aifs from merged")
+ {
+ test_pbproc_aifs (t, true, false);
+ } test_end;
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
+struct test_pbproc_trace_dump_t
+{
+ char text[2048];
+ uint size;
+};
+typedef struct test_pbproc_trace_dump_t test_pbproc_trace_dump_t;
+
+static int
+test_pbproc_trace_dump_callback (void *user, const char *text,
+ uint text_size)
+{
+ test_pbproc_trace_dump_t *ctx = user;
+ dbg_assert (ctx);
+ if (text_size + ctx->size >= COUNT (ctx->text))
+ return 0;
+ memcpy (ctx->text, text, text_size);
+ ctx->size += text_size;
+ ctx->text[ctx->size] = '\0';
+ return text_size;
+}
+
+void
+test_pbproc_trace_suite (test_t t)
+{
+ test_suite_begin (t, "trace");
+ test_case_begin (t, "fc");
+ test_pbproc_t tp;
+ test_pbproc_init (&tp);
+ pbproc_t *ctx = tp.pbproc;
+ test_begin (t, "rx fc")
+ {
+ char ref[2048], *refp = ref;
+ const char *s;
+ s = "---trace-begin[pbproc]---\n"
+ "[.] init\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ s = "[0x00000000] fsm RX FC pre_date=0x00000000"
+ " BEACON snid=A1 bts=0x12345678 bto=42330,42331,42332,42333\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 0, 0,
+ 0x34567818, 0x5ba55a12, 0x5da55ca5, 0xdeaddea5);
+ s = "[0x00000001] fsm RX FC pre_date=0x00000001"
+ " SOF snid=2 dir=CCO->STA dtei=0x12 lid=0x04 mnbf eks=3"
+ " num_sym=2 tmi=21 fl_av=2213 mpdu_cnt=3 burst_cnt=1"
+ " bbf mrdur_fl=0xbab sackt0=0x2 sacki0=0x21472d05, sacki1=0x54\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 1, 1,
+ 0x56341221, 0xbbab78a5, 0x21472d05, 0xdeadde54);
+ s = "[0x00000002] fsm RX FC pre_date=0x00000002"
+ " SOF snid=A13 dir=STA->CCO dtei=0xed lid=0x0b mcf eks=0"
+ " pb136 num_sym=1 tmi=10 fl_av=1882 burst_cnt=2"
+ " sackt0=0x1 sacki0=0x72b882fa, sacki1=0xab\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 2, 2,
+ 0xa9cbedd9, 0x4454875a, 0x72b882fa, 0xdeaddeab);
+ s = "[0x00000003] fsm RX FC pre_date=0x00000003"
+ " SACK snid=3 dtei=0x12 cfs svn=1 mfs=ACK,mNACK sackt=m,mc,nr,u"
+ " sacki=0x01234567,0x89abcdef,0x01\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 3, 3,
+ 0xe4451232, 0x01234567, 0x89abcdef, 0xdeadde01);
+ s = "[0x00000004] fsm RX FC pre_date=0x00000004"
+ " SACK snid=A12 dtei=0xed bdf rrtf mfs=HOLD,mFAIL sackt=u,nr,mc,m"
+ " sacki=0xfedcba98,0x76543210,0xfe\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 4, 4,
+ 0x1bbaedca, 0xfedcba98, 0x76543210, 0xdeaddefe);
+ s = "[0x00000005] fsm RX FC pre_date=0x00000005"
+ " CTS snid=4 stei=0x23 dtei=0x45 lid=0x67 mcf cfs hp10df igf"
+ " dur=11111\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 5, 5,
+ 0x67452343, 0x002b67a5, 0x00000000, 0xdeadde00);
+ s = "[0x00000006] fsm RX FC pre_date=0x00000006"
+ " RTS snid=A11 stei=0xdc dtei=0xba lid=0x98 mnbf bdf hp11df"
+ " dur=5272\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 6, 6,
+ 0x98badcbb, 0x0014985a, 0x00000000, 0xdeadde00);
+ s = "[0x00000007] fsm RX FC pre_date=0x00000007"
+ " SOUND snid=5 dir=STA->CCO dtei=0x34 lid=0x07 saf scf req_tm=6"
+ " fl_av=2134 mpdu_cnt=2 src=0x00 sackt0=0x1"
+ " sacki0=0x1341a0, sacki1=0xbc\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 7, 7,
+ 0x78563454, 0x9a0d05b5, 0x000000bc, 0xdeadde00);
+ s = "[0x00000008] fsm RX FC pre_date=0x00000008"
+ " SOUND snid=A10 dir=CCO->STA dtei=0xcb lid=0x08 pb136 req_tm=1"
+ " fl_av=1961 mpdu_cnt=1 src=0x00 sackt0=0x2"
+ " sacki0=0xca65f, sacki1=0x43\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 8, 8,
+ 0x87a9cbac, 0x6532fa4a, 0x00000043, 0xdeadde00);
+ s = "[0x00000009] fsm RX FC pre_date=0x00000009"
+ " RSOF snid=6 dtei=0x12 lid=0x0c bdf pb136 sppb=0x20 fl_av=2321"
+ " tmi=13 num_sym=3 sackt0=0x1 sacki0=0x1234567 sacki1=0x89ab\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 9, 9,
+ 0xe4451265, 0x01234567, 0xdb8089ab, 0xdeadde20);
+ s = "[0x0000000a] fsm RX FC pre_date=0x0000000a"
+ " RSOF snid=A9 dtei=0xed lid=0x03 sppb=0x73 fl_av=1774 tmi=18"
+ " num_sym=0 sackt0=0x2 sacki0=0xfedcba98 sacki1=0x1f7654\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ PBPROC_TRACE (FSM_RX_FC, 10, 10,
+ 0x1bbaed9d, 0xfedcba98, 0x247f7654, 0xdeadde73);
+ s = "---trace-end---\n";
+ dbg_assert (refp + strlen (s) < ref + sizeof (ref));
+ strcpy (refp, s); refp += strlen (s);
+ test_pbproc_trace_dump_t dump;
+ dump.size = 0;
+ trace_buffer_dump (&ctx->trace, test_pbproc_trace_dump_callback,
+ &dump);
+ test_fail_unless (strcmp (dump.text, ref) == 0);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ trace_init ();
+ test_init (t, argc, argv);
+ test_pbproc_init_suite (t);
+ prep_mpdu_test_suite (t);
+ tx_data_test_suite (t);
+ tx_sound_test_suite (t);
+ rx_data_test_suite (t);
+ rx_sound_test_suite (t);
+ test_pbproc_trace_suite (t);
+ trace_uninit ();
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/tx_data.c b/cesar/mac/pbproc/test/pbproc_eoc/src/tx_data.c
new file mode 100644
index 0000000000..556d043862
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/tx_data.c
@@ -0,0 +1,923 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/tx_data.c
+ * \brief TX Data automaton test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_pbproc.h"
+#include "inc/utils.h"
+
+#include "mac/common/timings.h"
+
+/** TX common test parameters. */
+struct tx_data_test_common_param_t
+{
+ /** Duration of the access, measured as a number of symbol, default to
+ * symb_nb if 0. */
+ uint duration_symb_nb;
+ /** Number of symbols. */
+ uint symb_nb;
+ /** Expected total number of segments. */
+ uint seg_nb_total;
+ /** Tonemap index. */
+ uint tmi;
+ /** Tonemap uniform modulation, or 0 to reuse previous one. */
+ uint tm_mod;
+ /** Whether spoc_update_step is valid. */
+ bool spoc;
+ /** SPOC update step. */
+ phy_prepare_type_t spoc_update_step;
+ /** MFS FSM response in SACK, default to ACK. */
+ mfs_fsm_rsp_t sack_mfs_fsm_rsp;
+ /** MFS window size in SACK. */
+ mfs_window_size_idx_t sack_window_size;
+ /** TX while in RE_SYNC, seen on stats. */
+ bool re_sync;
+ /** No acknowledgment, access event. */
+ bool noack_access;
+ /** No acknowledgment, unexpected FC received. */
+ bool noack_fc;
+ /** EoC RSOF. */
+ bool eoc_rsof;
+};
+typedef struct tx_data_test_common_param_t tx_data_test_common_param_t;
+
+#define tx_data_test_common(t, tp, date, mfs, params...) \
+ tx_data_test_common_f ((t), (tp), (date), (mfs), \
+ &(struct tx_data_test_common_param_t) { params })
+
+void
+tx_data_test_common_f (test_t t, test_pbproc_t *tp, u32 date, mfs_tx_t *mfs,
+ const tx_data_test_common_param_t *p)
+{
+ test_within (t);
+ dbg_assert (mfs);
+ const uint stei = mfs->common.unassociated ? 0 : tp->config.tei;
+ const uint dtei = mfs->common.tei;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ tonemap_t *tm = &tp->config.tonemask_info.tonemap_robo[PHY_MOD_ROBO];
+ uint dx = MAC_DX417_TCK;
+ uint tmi = p->tmi;
+ if (tmi != PHY_MOD_ROBO)
+ tm = utils_sta_prepare_default_tonemap (tp, true, dtei, tmi,
+ p->tm_mod, 0, &dx);
+ uint rifs_tck = tmi < PHY_MOD_ROBO_NB ? MAC_RIFS_DEFAULT_TCK
+ : MAC_RIFS_SPC_ANY_TCK;
+ uint duration_symb_nb = p->duration_symb_nb
+ ? p->duration_symb_nb : p->symb_nb;
+ uint duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (duration_symb_nb, dx) + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ bool spoc_preamble = p->spoc
+ && p->spoc_update_step == PHY_PREPARE_TYPE_PREAMBLE;
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = true,
+ .cfp = p->eoc_rsof,
+ };
+ ca_access_param_t noack_access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = false,
+ .cfp = p->eoc_rsof,
+ };
+ dbg_assert (MFS_FSM_RSP_ACK == 0); /* Check default is fine. */
+ pbproc_fc_sack_t sack_fc = {
+ .dt_av = PBPROC_FC_DT_SACK,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = !p->noack_fc ? stei : stei + 1,
+ .cfs = false,
+ .bdf = true,
+ .svn = 0,
+ .rrtf = false,
+ .mfs_rsp_data = p->sack_mfs_fsm_rsp,
+ .mfs_rsp_mgmt = MFS_FSM_RSP_ACK,
+ .sackt3 = 0,
+ .sackt2 = 0,
+ .sackt1 = 0,
+ .sackt0 = 0,
+ .sacki = { 0, 0 },
+ .sacki_last = p->sack_window_size << 4,
+ .fccs_av = 0,
+ };
+ tp->pbproc->recv_mpdu.rx_params.bbf = p->eoc_rsof;
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (p->symb_nb, dx) + rifs_tck;
+ scenario_entry_t ack_entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date + pre_fc_fl_tck,
+ .fc_av = (u32 *) &sack_fc),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT_COND (!access.cfp, ca_backoff_success),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CIFS_TCK),
+ SCENARIO_END
+ };
+ scenario_entry_t noack_access_entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = NULL,
+ .access_param = &noack_access),
+ SCENARIO_EVENT (ca_access_done),
+ /* TODO: remove this EoC speciality. */
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = noack_access.access_date
+ - PBPROC_ANTICIP_TCK + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CIFS_TCK),
+ SCENARIO_END
+ };
+ scenario_entry_t noack_fc_entries[] = {
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date + pre_fc_fl_tck,
+ .fc_av = (u32 *) &sack_fc),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CIFS_TCK),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_END
+ };
+ scenario_entry_t *ack_noack_entries = ack_entries;
+ if (p->noack_access)
+ ack_noack_entries = noack_access_entries;
+ else if (p->noack_fc)
+ ack_noack_entries = noack_fc_entries;
+ bool long_ppdu = p->seg_nb_total != 0;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 2),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT_COND (!long_ppdu, phy_tx_param_short,
+ .fc_mode = PHY_FC_MODE_AV_1),
+ SCENARIO_EVENT_COND (long_ppdu, phy_pbdma_start, .bypass_aes = true,
+ .nb_total = p->seg_nb_total,
+ .nb_pb_it = 0, .chandata = false, .now = false),
+ SCENARIO_EVENT_COND (long_ppdu && tmi >= PHY_MOD_ROBO_NB,
+ phy_set_tonemap),
+ SCENARIO_EVENT_COND (long_ppdu, phy_tx_param,
+ .fc_mode = PHY_FC_MODE_AV_1,
+ .mod = tmi < PHY_MOD_ROBO_NB ? tmi : PHY_MOD_TM,
+ .fecrate = tm->fecrate, .pb_size = PHY_PB_SIZE_520,
+ .gil = PHY_GIL_417, .symbol_nb = p->symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = true,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_ACTION (phy_access_conf),
+ SCENARIO_EVENT_COND (long_ppdu, phy_tx_prepare),
+ SCENARIO_EVENT (ca_backoff_deferred, .slot_count = 0),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs,
+ .start_date = date + pre_fc_fl_tck),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date + pre_fc_fl_tck,
+ .pre_detection = true),
+ SCENARIO_EVENT_COND (p->spoc, phy_extra_timer_program,
+ .date = date + pre_fc_fl_tck - rifs_tck),
+ SCENARIO_ACTION_COND (p->spoc, phy_extra_timer),
+ SCENARIO_EVENT_COND (spoc_preamble, phy_spoc_tx_set),
+ SCENARIO_EVENT_COND (p->spoc, phy_prepare,
+ .type = p->spoc_update_step, .wait = false),
+ SCENARIO_EVENT_COND (spoc_preamble, phy_spoc_rx_set),
+ SCENARIO_EVENT_COND (spoc_preamble, phy_freq_error_set, .sync = true,
+ .rho_q30 = 42),
+ SCENARIO_SUB (ack_noack_entries),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ mfs->no_reply_count = 2;
+ scenario_run (t, entries, &globals);
+ bool ack = !(p->noack_access || p->noack_fc);
+ test_pbproc_check_stats (t, tp, .tx_data = 1, .tx_data_wack = 1,
+ .tx_data_wack_ack = ack ? 1 : 0,
+ .tx_data_wack_noack = ack ? 0 : 1,
+ .tx_data_re_sync = p->re_sync ? 1 : 0,
+ .rx_handle_fc = p->noack_fc ? 1 : 0,
+ .rx_nfu = p->noack_fc ? 1 : 0);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ /* TODO: this is too permissive: */
+ test_fail_unless (!ack || mfs->no_reply_count == 0);
+}
+
+void
+tx_data_test (test_t t, test_pbproc_t *tp, u32 date, uint mfs_seg_nb,
+ uint duration_symb_nb, uint symb_nb, uint seg_nb_total,
+ bool unassociated, uint tmi)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 2;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei,
+ mfs_seg_nb);
+ mfs->common.unassociated = unassociated;
+ tx_data_test_common (t, tp, date, mfs,
+ .duration_symb_nb = duration_symb_nb,
+ .symb_nb = symb_nb, .seg_nb_total = seg_nb_total,
+ .tmi = tmi);
+ test_fail_unless (mfs->stats.num_mpdus == 1);
+ test_fail_unless (mfs->stats.num_bursts == 1);
+ test_fail_unless (mfs->stats.num_pbs == seg_nb_total);
+ test_fail_unless (mfs->stats.num_segs_suc == seg_nb_total);
+ utils_mfs_tx_cleanup (mfs);
+ if (tmi != PHY_MOD_ROBO)
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+}
+
+void
+tx_data_test_eoc_rsof (test_t t, test_pbproc_t *tp, u32 date, uint mfs_seg_nb,
+ uint duration_symb_nb, uint symb_nb, uint seg_nb_total,
+ uint tmi)
+{
+ test_within (t);
+ const uint lid = 4;
+ const uint dtei = 1;
+ tp->config.tei = 6;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei,
+ mfs_seg_nb);
+ tx_data_test_common (t, tp, date, mfs,
+ .duration_symb_nb = duration_symb_nb,
+ .symb_nb = symb_nb, .seg_nb_total = seg_nb_total,
+ .tmi = tmi, .eoc_rsof = true);
+ test_fail_unless (mfs->stats.num_mpdus == 1);
+ test_fail_unless (mfs->stats.num_bursts == 1);
+ test_fail_unless (mfs->stats.num_pbs == seg_nb_total);
+ test_fail_unless (mfs->stats.num_segs_suc == seg_nb_total);
+ utils_mfs_tx_cleanup (mfs);
+ if (tmi != PHY_MOD_ROBO)
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+ tp->config.tei = 1;
+}
+
+void
+tx_data_noack_test (test_t t, test_pbproc_t *tp, u32 date, bool access)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 2;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei, 1);
+ tx_data_test_common (t, tp, date, mfs, .duration_symb_nb = 50,
+ .symb_nb = 19, .seg_nb_total = 1,
+ .noack_access = access, .noack_fc = !access);
+ test_fail_unless (mfs->stats.num_mpdus == 1);
+ test_fail_unless (mfs->stats.num_bursts == 1);
+ test_fail_unless (mfs->stats.num_pbs == 1);
+ test_fail_unless (mfs->stats.num_segs_suc == 0);
+ utils_mfs_tx_cleanup (mfs);
+}
+
+void
+tx_data_woack_test (test_t t, test_pbproc_t *tp, u32 date, uint mfs_seg_nb,
+ uint duration_symb_nb, uint symb_nb,
+ uint data_seg_nb_total)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 0xff;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ uint duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (duration_symb_nb, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (true, false, lid, dtei, mfs_seg_nb);
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = true,
+ .cfp = false,
+ };
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 2),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true,
+ .nb_total = data_seg_nb_total,
+ .nb_pb_it = data_seg_nb_total,
+ .chandata = false, .now = false),
+ SCENARIO_EVENT (phy_tx_param, .fc_mode = PHY_FC_MODE_AV_1,
+ .mod = PHY_MOD_ROBO, .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = true,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_ACTION (phy_access_conf),
+ SCENARIO_EVENT (phy_tx_prepare),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_ACTION (phy_pbdma, .pb_it = true, .end_tx_pb = true),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_backoff_success),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CIFS_TCK),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (t, tp, .tx_data = 1, .tx_data_woack = 1);
+ test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_NOP);
+ test_fail_unless (mfs->stats.num_mpdus == 1);
+ test_fail_unless (mfs->stats.num_bursts == 1);
+ test_fail_unless (mfs->stats.num_pbs == data_seg_nb_total);
+ test_fail_unless (mfs->stats.num_segs_suc == data_seg_nb_total);
+ utils_mfs_tx_cleanup (mfs);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+tx_data_noseg_test (test_t t, test_pbproc_t *tp, u32 date,
+ uint duration_symb_nb, bool prp_won, bool got_mfs,
+ bool late)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 2;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ uint duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (duration_symb_nb, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ mfs_tx_t *mfs = got_mfs
+ ? utils_mfs_tx_prepare (false, false, lid, dtei, late ? 1 : 0)
+ : NULL;
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = true,
+ .cfp = false,
+ };
+ scenario_entry_t *entries;
+ scenario_entry_t entries_prp_won[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 0,
+ .delay_tck = late ? PBPROC_ANTICIP_TCK : 0),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT_COND (late, ca_access_done),
+ /* TODO: why this? */
+ SCENARIO_EVENT (ca_backoff_deferred,
+ .slot_count = access.duration_tck / MAC_SLOT_TCK),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_access_defer, .date = date),
+ SCENARIO_END
+ };
+ scenario_entry_t entries_prp_lost[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = false, .slot_count = 0),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_backoff_cancel),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs,
+ .start_date = phy_date ()),
+ SCENARIO_END
+ };
+ entries = prp_won ? entries_prp_won : entries_prp_lost;
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (t, tp,
+ .prp_lost = prp_won ? 0 : 1,
+ .tx_invalid = (late || prp_won) ? 1 : 0,
+ .tx_late = late ? 1 : 0);
+ if (mfs)
+ {
+ test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_INIT);
+ test_fail_unless (mfs->stats.num_mpdus == 0);
+ test_fail_unless (mfs->stats.num_bursts == 0);
+ test_fail_unless (mfs->stats.num_pbs == 0);
+ test_fail_unless (mfs->stats.num_segs_suc == 0);
+ utils_mfs_tx_cleanup (mfs);
+ }
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+tx_data_beacon_test (test_t t, test_pbproc_t *tp, u32 date,
+ uint duration_symb_nb, uint symb_nb)
+{
+ test_within (t);
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ bool hybrid = false;
+ uint pre_fc_tck = hybrid
+ ? MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK + MAC_FC_AV_TCK
+ : MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ uint duration_tck = pre_fc_tck + MAC_PAYLOAD_TCK (6, MAC_DX567_TCK)
+ + MAC_B2BIFS_TCK;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (true, false, MAC_LID_SPC_CENTRAL,
+ MAC_TEI_BCAST, 0);
+ mfs->cfp = true;
+ mfs->beacon = true;
+ pb_beacon_t *pb = PARENT_OF (pb_beacon_t, blk, blk_alloc_desc ());
+ pbproc_tx_beacon_params_t params = {
+ { 0x0123, 0x4242, 0xabab, 0x5555 }, pb->data + 123
+ };
+ pbproc_mfs_beacon_prepare (tp->pbproc, mfs, pb, &params);
+ test_pbproc_alloc (tp, hybrid, date / beacon_tck * beacon_tck);
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = false,
+ .cfp = true,
+ };
+ const uint pre_fc_fl_tck = pre_fc_tck
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX567_TCK) + MAC_B2BIFS_TCK;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 0),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT_COND (hybrid, phy_tx_fc10, .date = date, .fc10 = 0x2f00),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true, .nb_total = 1,
+ .nb_pb_it = 1, .chandata = false, .now = false),
+ SCENARIO_EVENT (phy_tx_param, .fc_mode = hybrid ? PHY_FC_MODE_HYBRID_1
+ : PHY_FC_MODE_AV_1,
+ .mod = PHY_MOD_MINI_ROBO, .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_136, .gil = PHY_GIL_567,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = true,
+ .stop_tx_on_prp_lost = false),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_ACTION (phy_access_conf),
+ SCENARIO_EVENT (phy_tx_prepare),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_ACTION (phy_pbdma, .pb_it = true, .end_tx_pb = true),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_backoff_success),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (t, tp, .tx_data = 1, .tx_data_beacon = 1);
+ test_fail_unless (mfs->stats.num_mpdus == 1);
+ test_fail_unless (mfs->stats.num_bursts == 1);
+ test_fail_unless (mfs->stats.num_pbs == 1);
+ test_fail_unless (mfs->stats.num_segs_suc == 1);
+ utils_mfs_tx_cleanup (mfs);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+tx_data_spoc_test (test_t t, test_pbproc_t *tp,
+ phy_prepare_type_t spoc_update_step)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 2;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei, 5);
+ tx_data_test_common (t, tp, 5462132, mfs, .symb_nb = 50,
+ .duration_symb_nb = 50,
+ .seg_nb_total = 5,
+ .tmi = PHY_MOD_HS_ROBO,
+ .spoc = spoc_update_step != PHY_PREPARE_TYPE_NB,
+ .spoc_update_step = spoc_update_step);
+ test_fail_unless (mfs->stats.num_mpdus == 1);
+ test_fail_unless (mfs->stats.num_bursts == 1);
+ test_fail_unless (mfs->stats.num_pbs == 5);
+ test_fail_unless (mfs->stats.num_segs_suc == 5);
+ utils_mfs_tx_cleanup (mfs);
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+}
+
+void
+tx_data_basic_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic");
+ test_pbproc_init (&tp);
+ test_begin (t, "unicast")
+ {
+ tx_data_test (t, &tp, 5462132, 30, 50, 50, 5, false, PHY_MOD_HS_ROBO);
+ tx_data_test (t, &tp, 5462132, 30, 50, 38, 2, true, PHY_MOD_ROBO);
+ } test_end;
+ test_begin (t, "unicast rsof")
+ {
+ tx_data_test_eoc_rsof (t, &tp, 5462132, 30, 50, 50, 5, PHY_MOD_HS_ROBO);
+ } test_end;
+ test_begin (t, "unicast rsof empty")
+ {
+ tx_data_test_eoc_rsof (t, &tp, 5462132, 0, 30, 0, 0, PHY_MOD_ROBO);
+ } test_end;
+ test_begin (t, "no seg prp won")
+ {
+ tx_data_noseg_test (t, &tp, 5462132, 95, true, true, false);
+ } test_end;
+ test_begin (t, "no seg prp lost")
+ {
+ tx_data_noseg_test (t, &tp, 5462132, 95, false, true, false);
+ } test_end;
+ test_begin (t, "no mfs prp won")
+ {
+ tx_data_noseg_test (t, &tp, 5462132, 95, true, false, false);
+ } test_end;
+ test_begin (t, "no mfs prp lost")
+ {
+ tx_data_noseg_test (t, &tp, 5462132, 95, false, false, false);
+ } test_end;
+ test_begin (t, "multicast")
+ {
+ tx_data_woack_test (t, &tp, 5462132, 30, 95, 38, 2);
+ } test_end;
+ test_begin (t, "beacon")
+ {
+ tx_data_beacon_test (t, &tp, 123, 6, 6);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+tx_data_spoc_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "spoc");
+ test_pbproc_init (&tp);
+ s32 rho_q30 = 42;
+ pbproc_spoc_update (tp.pbproc, true, rho_q30);
+ test_begin (t, "preamble")
+ {
+ tx_data_spoc_test (t, &tp, PHY_PREPARE_TYPE_PREAMBLE);
+ test_fail_unless (tp.pbproc->spoc_update.step
+ == PHY_PREPARE_TYPE_PRS);
+ test_fail_unless (tp.pbproc->spoc_update.coeff == NULL);
+ } test_end;
+ test_begin (t, "prs")
+ {
+ tx_data_spoc_test (t, &tp, PHY_PREPARE_TYPE_PRS);
+ test_fail_unless (tp.pbproc->spoc_update.step
+ == PHY_PREPARE_TYPE_NB);
+ } test_end;
+ test_begin (t, "done")
+ {
+ tx_data_spoc_test (t, &tp, PHY_PREPARE_TYPE_NB);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+tx_data_cancel_test (test_t t, test_pbproc_t *tp, bool prp_won, bool rx_fc)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 2;
+ const uint date = 123456;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei, 1);
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (19, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK +
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ .prp = true,
+ .cfp = false,
+ };
+ const uint date2 = 123456 + MAC_EIFS_AV_TCK;
+ ca_access_param_t access2 = {
+ .access_date = date2,
+ .duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (19, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK +
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ .prp = false,
+ .cfp = false,
+ };
+ const uint date3 = date2 + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK
+ - PBPROC_ANTICIP_TCK;
+ ca_access_param_t access3 = {
+ .access_date = date3,
+ .duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (19, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK +
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ .prp = false,
+ .cfp = false,
+ };
+ pbproc_fc_sack_t sack_fc = {
+ .dt_av = PBPROC_FC_DT_SACK,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = tp->config.tei + 8,
+ .cfs = false,
+ .bdf = true,
+ .svn = 0,
+ .rrtf = false,
+ .mfs_rsp_data = MFS_FSM_RSP_ACK,
+ .mfs_rsp_mgmt = MFS_FSM_RSP_ACK,
+ .sackt3 = 0,
+ .sackt2 = 0,
+ .sackt1 = 0,
+ .sackt0 = 0,
+ .sacki = { 0, 0 },
+ .sacki_last = 0,
+ .fccs_av = 0,
+ };
+ uint sack_length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK;
+ scenario_entry_t sack_entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 6),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true, .nb_total = 1,
+ .nb_pb_it = 0, .chandata = false, .now = false),
+ SCENARIO_EVENT (phy_tx_param, .fc_mode = PHY_FC_MODE_AV_1,
+ .mod = PHY_MOD_ROBO, .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = 19),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = true,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date - MAC_SLOT_TCK,
+ .prp_won = prp_won, .slot_count = 5,
+ .fc_av = PARENT_OF (pbproc_fc_t, sack,
+ &sack_fc)->words),
+ SCENARIO_EVENT_COND (prp_won, ca_backoff_deferred, .slot_count = 3),
+ SCENARIO_EVENT_COND (!prp_won, ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date - MAC_SLOT_TCK + sack_length_tck),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_END
+ };
+ scenario_entry_t access_entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 6),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true, .nb_total = 1,
+ .nb_pb_it = 0, .chandata = false, .now = false),
+ SCENARIO_EVENT (phy_tx_param, .fc_mode = PHY_FC_MODE_AV_1,
+ .mod = PHY_MOD_ROBO, .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = 19),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = true,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access2,
+ .prp_won = prp_won, .slot_count = 600),
+ SCENARIO_EVENT (ca_access_done),
+ /* TODO: remove this EoC speciality. */
+ SCENARIO_EVENT (ca_access_vcs_restart, .end_date = date3),
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access3,
+ .prp_won = prp_won, .slot_count = 600),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true, .nb_total = 1,
+ .nb_pb_it = 0, .chandata = false, .now = false),
+ SCENARIO_EVENT (phy_tx_param, .fc_mode = PHY_FC_MODE_AV_1,
+ .mod = PHY_MOD_ROBO, .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = 19),
+ SCENARIO_EVENT (phy_tx_frame, .date = date3, .want_conf = true,
+ .stop_tx_on_prp_lost = false),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date3),
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date3 - MAC_SLOT_TCK,
+ .prp_won = prp_won, .slot_count = 5,
+ .fc_av = PARENT_OF (pbproc_fc_t, sack,
+ &sack_fc)->words),
+ SCENARIO_EVENT (ca_backoff_deferred, .slot_count = 3),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date3 - MAC_SLOT_TCK + sack_length_tck),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_END
+ };
+ scenario_entry_t *entries = rx_fc ? sack_entries : access_entries;
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = prp_won ? 0 : 1,
+ .cw_lost = prp_won || !rx_fc ? 1 : 0,
+ .rx_handle_fc = 1,
+ .rx_nfu = 1,
+ .tx_data = rx_fc ? 1 : 2,
+ .tx_data_cancel = rx_fc ? 1 : 2,
+ );
+ test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_INIT);
+ test_fail_unless (mfs->stats.num_mpdus == 0);
+ test_fail_unless (mfs->stats.num_bursts == 0);
+ test_fail_unless (mfs->stats.num_pbs == 0);
+ test_fail_unless (mfs->stats.num_segs_suc == 0);
+ utils_mfs_tx_cleanup (mfs);
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+tx_data_error_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "error");
+ test_pbproc_init (&tp);
+ test_begin (t, "cw lost")
+ {
+ tx_data_cancel_test (t, &tp, true, true);
+ } test_end;
+ test_begin (t, "prp lost after access")
+ {
+ tx_data_cancel_test (t, &tp, false, true);
+ } test_end;
+ test_begin (t, "prp lost after access and no frame")
+ {
+ tx_data_cancel_test (t, &tp, false, false);
+ } test_end;
+ test_begin (t, "tx late")
+ {
+ tx_data_noseg_test (t, &tp, 5462132, 95, true, true, true);
+ } test_end;
+ test_begin (t, "nack access")
+ {
+ tx_data_noack_test (t, &tp, 5462132, true);
+ } test_end;
+ test_begin (t, "nack fc nfu")
+ {
+ tx_data_noack_test (t, &tp, 5462132, false);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+enum frame_direction_t
+{
+ FRAME_STA_TO_CCO_DIR = 1,
+ FRAME_CCO_TO_STA_DIR = 0,
+};
+typedef enum frame_direction_t frame_direction_t;
+
+bool
+pbproc_ftda_parse_sackd (pbproc_t *ctx, const pbproc_fc_t *fc_av,
+ pbproc_fc_ack_data_t *ack_data);
+
+void
+tx_data_pg_ack_test (test_t t, test_pbproc_t *tp, uint cfg_tei, uint prep_tei,
+ uint frame_tei, frame_direction_t direction,
+ uint frame_type, bool cancel)
+{
+ test_within (t);
+ tp->config.tei = cfg_tei;
+ dbg_assert (cfg_tei != frame_tei);
+ pbproc_fc_sof_t sof = {
+ .dt_av = PBPROC_FC_DT_SOF,
+ .access = false,
+ .snid = tp->snid,
+ .direction = direction,
+ .dtei = frame_tei,
+ .fccs_av = 0,
+ };
+ pbproc_fc_rsof_t rsof = {
+ .dt_av = PBPROC_FC_DT_RSOF,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = frame_tei,
+ .fccs_av = 0,
+ };
+ pbproc_fc_sound_t sound = {
+ .dt_av = PBPROC_FC_DT_SOUND,
+ .access = false,
+ .snid = tp->snid,
+ .direction = direction,
+ .dtei = frame_tei,
+ .fccs_av = 0,
+ };
+ pbproc_fc_t fc;
+ if (frame_type == PBPROC_FC_DT_SOF)
+ fc.sof = sof;
+ else if (frame_type == PBPROC_FC_DT_RSOF)
+ fc.rsof = rsof;
+ else if (frame_type == PBPROC_FC_DT_SOUND)
+ fc.sound = sound;
+ else
+ dbg_assert_default ();
+ pbproc_prep_mpdu_t *prep = &tp->pbproc->prep_mpdu;
+ prep->valid = true;
+ prep->dtei = prep_tei;
+ /* Run test. */
+ pbproc_fc_ack_data_t ack_data;
+ bool ok = pbproc_ftda_parse_sackd (tp->pbproc, &fc, &ack_data);
+ test_fail_unless (ok == !cancel);
+ /* Cleanup. */
+ prep->valid = true;
+}
+
+void
+tx_data_pg_ack_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "pg_ack");
+ test_pbproc_init (&tp);
+ tp.pbproc->alloc.snid = tp.snid;
+ /* SOF combination. */
+ test_begin (t, "cco sof")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 25, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_SOF, false);
+ } test_end;
+ test_begin (t, "cco sof wrong direction")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 25, 25, FRAME_CCO_TO_STA_DIR,
+ PBPROC_FC_DT_SOF, true);
+ } test_end;
+ test_begin (t, "cco sof wrong station")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 24, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_SOF, true);
+ } test_end;
+ test_begin (t, "sta sof")
+ {
+ tx_data_pg_ack_test (t, &tp, 23, 1, 45, FRAME_CCO_TO_STA_DIR,
+ PBPROC_FC_DT_SOF, false);
+ } test_end;
+ test_begin (t, "sta sof wrong direction")
+ {
+ tx_data_pg_ack_test (t, &tp, 23, 1, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_SOF, true);
+ } test_end;
+ /* RSOF combination. */
+ test_begin (t, "cco rsof")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 25, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_RSOF, false);
+ } test_end;
+ /* RSOF combination. */
+ test_begin (t, "cco rsof wrong station")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 24, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_RSOF, true);
+ } test_end;
+ test_begin (t, "sta rsof")
+ {
+ tx_data_pg_ack_test (t, &tp, 23, 1, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_RSOF, true);
+ } test_end;
+ /* SOUND combination. */
+ test_begin (t, "cco sound")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 25, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_SOUND, false);
+ } test_end;
+ test_begin (t, "cco sound wrong station")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 24, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_SOUND, true);
+ } test_end;
+ test_begin (t, "cco sound wrong direction")
+ {
+ tx_data_pg_ack_test (t, &tp, 1, 25, 25, FRAME_CCO_TO_STA_DIR,
+ PBPROC_FC_DT_SOUND, true);
+ } test_end;
+ test_begin (t, "sta valid sound")
+ {
+ tx_data_pg_ack_test (t, &tp, 23, 24, 25, FRAME_CCO_TO_STA_DIR,
+ PBPROC_FC_DT_SOUND, false);
+ } test_end;
+ test_begin (t, "sta sound wrong direction")
+ {
+ tx_data_pg_ack_test (t, &tp, 23, 24, 25, FRAME_STA_TO_CCO_DIR,
+ PBPROC_FC_DT_SOUND, true);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+tx_data_test_suite (test_t t)
+{
+ test_suite_begin (t, "tx data");
+ tx_data_basic_test_case (t);
+ tx_data_spoc_test_case (t);
+ tx_data_error_test_case (t);
+ tx_data_pg_ack_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/tx_sound.c b/cesar/mac/pbproc/test/pbproc_eoc/src/tx_sound.c
new file mode 100644
index 0000000000..27913ae5d2
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/tx_sound.c
@@ -0,0 +1,377 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/tx_sound.c
+ * \brief TX SOUND automaton test
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/scenario/scenario.h"
+
+#include "inc/test_pbproc.h"
+#include "inc/utils.h"
+
+#include "mac/common/timings.h"
+
+void
+tx_sound_test (test_t t, test_pbproc_t *tp)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 5;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ const u32 date = 12345;
+ const uint symb_nb = 19;
+ const uint duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ u32 chandata_conf[1] = { 0 };
+ pbproc_set_chandata_conf (
+ tp->pbproc, (phy_chandata_conf_t *) chandata_conf, 1, false);
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei, 1);
+ test_fail_unless (mfs);
+ mfs->no_reply_count = 2;
+ utils_sta_prepare_default_tonemap (tp, true, dtei,
+ TONEMAP_INDEX_INITIAL_START, 0, 0,
+ NULL);
+ /* need authenticated sta to send sound frames */
+ sta_t * sta = mac_store_sta_get(tp->store, dtei);
+ if (sta)
+ {
+ sta->authenticated = true;
+ tp->pbproc->config->authenticated = true;
+ blk_release (sta);
+ }
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = true,
+ .cfp = true,
+ };
+ pbproc_fc_sound_t sound_ack_fc = {
+ .dt_av = PBPROC_FC_DT_SOUND,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = dtei,
+ .direction = 1,
+ .lid = lid,
+ .pbsz = false,
+ .saf = true,
+ .scf = true,
+ .req_tm = 0,
+ .fl_av = 0,
+ .mpdu_cnt = 0,
+ .src = 0,
+ .fccs_av = 0,
+ };
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 2),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_tx_param_sound, .fc_mode = PHY_FC_MODE_AV_1,
+ .nb_pb = 1, .mod = PHY_MOD_ROBO,
+ .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date + pre_fc_fl_tck,
+ .pre_detection = true),
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date + pre_fc_fl_tck,
+ .fc_av = (u32 *) &sound_ack_fc),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT_COND (!access.cfp, ca_backoff_success),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date + pre_fc_fl_tck + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CIFS_TCK),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, entries, &globals);
+ test_pbproc_check_stats (t, tp, .tx_sound = 1, .tx_sound_ack = 1);
+ test_fail_unless (mfs->stats.num_mpdus == 0);
+ test_fail_unless (mfs->stats.num_bursts == 0);
+ test_fail_unless (mfs->stats.num_pbs == 0);
+ test_fail_unless (mfs->stats.num_segs_suc == 0);
+ test_fail_unless (mfs->no_reply_count == 0);
+ utils_mfs_tx_cleanup (mfs);
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ pbproc_set_chandata_conf (tp->pbproc, NULL, 0, false);
+}
+
+void
+tx_sound_basic_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic");
+ test_pbproc_init (&tp);
+ test_begin (t, "basic")
+ {
+ tx_sound_test (t, &tp);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+tx_sound_cancel_test (test_t t, test_pbproc_t *tp, bool prp_won, bool rx_fc,
+ bool late)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint dtei = 2;
+ const uint date = 123456;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ const uint symb_nb = 19;
+ u32 chandata_conf[1] = { 0 };
+ pbproc_set_chandata_conf (
+ tp->pbproc, (phy_chandata_conf_t *) chandata_conf, 1, false);
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (false, false, lid, dtei, 1);
+ /* if frame is not received and no late, check reply count */
+ if (!rx_fc && !late)
+ mfs->no_reply_count = 1;
+ utils_sta_prepare_default_tonemap (tp, true, dtei,
+ TONEMAP_INDEX_INITIAL_START, 0, 0,
+ NULL);
+ test_pbproc_alloc (tp, false, date / beacon_tck * beacon_tck);
+ /* need authenticated sta to send sound frames */
+ sta_t * sta = mac_store_sta_get(tp->store, dtei);
+ if (sta)
+ {
+ sta->authenticated = true;
+ tp->pbproc->config->authenticated = true;
+ blk_release (sta);
+ }
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ .prp = true,
+ .cfp = true,
+ };
+ const uint date2 = 123456 + MAC_EIFS_AV_TCK;
+ const uint date3 = date2 + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CIFS_TCK
+ - PBPROC_ANTICIP_TCK;
+ ca_access_param_t access2 = {
+ .access_date = date2,
+ .duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ .prp = false,
+ .cfp = true,
+ };
+ ca_access_param_t access3 = {
+ .access_date = date3,
+ .duration_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK +
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ .prp = false,
+ .cfp = true,
+ };
+ pbproc_fc_sack_t sack_fc = {
+ .dt_av = PBPROC_FC_DT_SACK,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = tp->config.tei + 8,
+ .cfs = false,
+ .bdf = true,
+ .svn = 0,
+ .rrtf = false,
+ .mfs_rsp_data = MFS_FSM_RSP_ACK,
+ .mfs_rsp_mgmt = MFS_FSM_RSP_ACK,
+ .sackt3 = 0,
+ .sackt2 = 0,
+ .sackt1 = 0,
+ .sackt0 = 0,
+ .sacki = { 0, 0 },
+ .sacki_last = 0,
+ .fccs_av = 0,
+ };
+ const uint pre_fc_fl_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + MAC_RIFS_DEFAULT_TCK;
+ const uint sack_length_tck = MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_CIFS_TCK;
+ scenario_entry_t sack_entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 6),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_tx_param_sound, .fc_mode = PHY_FC_MODE_AV_1,
+ .nb_pb = 1, .mod = PHY_MOD_ROBO,
+ .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date + pre_fc_fl_tck,
+ .pre_detection = true),
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date - MAC_SLOT_TCK,
+ .prp_won = prp_won, .slot_count = 5,
+ .fc_av = PARENT_OF (pbproc_fc_t, sack,
+ &sack_fc)->words),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT_COND (prp_won, ca_backoff_deferred, .slot_count = 3),
+ SCENARIO_EVENT_COND (!prp_won, ca_backoff_cancel),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date - MAC_SLOT_TCK + sack_length_tck),
+ SCENARIO_END
+ };
+ scenario_entry_t access_entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 6),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_tx_param_sound, .fc_mode = PHY_FC_MODE_AV_1,
+ .nb_pb = 1, .mod = PHY_MOD_ROBO,
+ .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date, .want_conf = false,
+ .stop_tx_on_prp_lost = true),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date + pre_fc_fl_tck,
+ .pre_detection = true),
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access2,
+ .prp_won = prp_won, .slot_count = 600),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT_COND (prp_won, ca_backoff_deferred, .slot_count = 598),
+ SCENARIO_EVENT_COND (!prp_won, ca_backoff_cancel),
+ SCENARIO_EVENT (ca_access_vcs_restart, .end_date = date3),
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access3,
+ .prp_won = prp_won, .slot_count = 600),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (phy_tx_param_sound, .fc_mode = PHY_FC_MODE_AV_1,
+ .nb_pb = 1, .mod = PHY_MOD_ROBO,
+ .fecrate = PHY_FEC_RATE_1_2,
+ .pb_size = PHY_PB_SIZE_520, .gil = PHY_GIL_417,
+ .symbol_nb = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date3, .want_conf = false,
+ .stop_tx_on_prp_lost = false),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date3),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date3 + pre_fc_fl_tck,
+ .pre_detection = true),
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date3 - MAC_SLOT_TCK,
+ .prp_won = prp_won, .slot_count = 5,
+ .fc_av = PARENT_OF (pbproc_fc_t, sack,
+ &sack_fc)->words),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_backoff_deferred, .slot_count = 3),
+ SCENARIO_EVENT (phy_tx_cancel),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date3 - MAC_SLOT_TCK + sack_length_tck),
+ SCENARIO_END
+ };
+ scenario_entry_t late_entries[] = {
+ SCENARIO_ACTION (phy_access, .mfs = mfs, .access_param = &access,
+ .prp_won = true, .slot_count = 6,
+ .delay_tck = late ? PBPROC_ANTICIP_TCK : 0),
+ SCENARIO_EVENT (ca_access_hold),
+ SCENARIO_EVENT (ca_access_get_mfs),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_backoff_deferred,
+ .slot_count = access.duration_tck / MAC_SLOT_TCK),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_access_defer, .date = date),
+ SCENARIO_END
+ };
+ scenario_entry_t *entries =
+ late ? late_entries : (rx_fc ? sack_entries : access_entries);
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, entries, &globals);
+ if (!late)
+ test_pbproc_check_stats (
+ t, tp,
+ .prp_lost = prp_won ? 0 : 1,
+ .cw_lost = rx_fc ? (prp_won ? 1 : 0) : (prp_won ? 2 : 1),
+ .rx_handle_fc = 1,
+ .rx_nfu = 1,
+ .tx_sound = rx_fc ? 1 : 2,
+ .tx_sound_noack = rx_fc ? 1 : 2,
+ );
+ else
+ test_pbproc_check_stats (t, tp, .tx_invalid = 1, .tx_late = 1);
+ test_fail_unless (mfs->stats.num_mpdus == 0);
+ test_fail_unless (mfs->stats.num_bursts == 0);
+ test_fail_unless (mfs->stats.num_pbs == 0);
+ test_fail_unless (mfs->stats.num_segs_suc == 0);
+ /* check reply count increase */
+ if (!rx_fc && !late)
+ test_fail_unless (mfs->no_reply_count == 2);
+ utils_mfs_tx_cleanup (mfs);
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+ pbproc_set_chandata_conf (tp->pbproc, NULL, 0, false);
+}
+
+void
+tx_sound_error_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "error");
+ test_pbproc_init (&tp);
+ test_begin (t, "no ack")
+ {
+ tx_sound_cancel_test (t, &tp, true, false, false);
+ } test_end;
+ test_begin (t, "cw lost")
+ {
+ tx_sound_cancel_test (t, &tp, true, true, false);
+ } test_end;
+ test_begin (t, "prp lost")
+ {
+ tx_sound_cancel_test (t, &tp, false, true, false);
+ } test_end;
+ test_begin (t, "prp lost and no frame")
+ {
+ tx_sound_cancel_test (t, &tp, false, false, false);
+ } test_end;
+ test_begin (t, "tx late")
+ {
+ tx_sound_cancel_test (t, &tp, true, false, true);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+tx_sound_test_suite (test_t t)
+{
+ test_suite_begin (t, "tx sound");
+ tx_sound_basic_test_case (t);
+ tx_sound_error_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
diff --git a/cesar/mac/pbproc/test/pbproc_eoc/src/utils.c b/cesar/mac/pbproc/test/pbproc_eoc/src/utils.c
new file mode 100644
index 0000000000..d9e7383266
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc_eoc/src/utils.c
@@ -0,0 +1,271 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/utils.c
+ * \brief Utilities.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/utils.h"
+
+#include "lib/blk.h"
+#include "lib/slist.h"
+#include "mac/common/timings.h"
+#include "mac/common/interval.h"
+#include "mac/pbproc/pbproc.h"
+#include "mac/pbproc/inc/mfs.h"
+
+mfs_tx_t *
+utils_mfs_tx_prepare (bool bcast, bool mme, uint lid, uint tei, int seg_nb)
+{
+ /* Create a MFS without holes. */
+ return utils_mfs_tx_holes_prepare(bcast, mme, lid, tei, seg_nb, 0, NULL);
+}
+
+mfs_tx_t *
+utils_mfs_tx_holes_prepare (bool bcast, bool mme, uint lid, uint tei,
+ int seg_nb, u64 holes_bmp, mac_store_t *store)
+{
+ mfs_tx_t *mfs;
+ /* Create an MFS. */
+ if (!store)
+ {
+ mfs = blk_alloc ();
+ mfs_tx_init (mfs, bcast, mme, lid, tei);
+ }
+ else
+ {
+ bool added;
+ mfs = mac_store_mfs_add_tx (store, bcast, mme, lid, tei, &added);
+ dbg_assert (added);
+ }
+ /* Default value for receiver window size */
+ mfs->window_size = mfs_window_size[MFS_WINDOW_SIZE_256];
+ if (seg_nb)
+ {
+ /* Add blocks to it. */
+ blk_t *blk_first, *blk_last;
+ blk_first = blk_alloc_desc_range (seg_nb, &blk_last);
+ pb_t *seg_first, *seg_last;
+ seg_first = PARENT_OF (pb_t, blk, blk_first);
+ seg_last = PARENT_OF (pb_t, blk, blk_last);
+ pb_t *seg, *lseg;
+ bool start_counting_holes = false;
+ uint expiration_count = 1;
+ for (lseg = NULL, seg = seg_first;
+ lseg != seg_last;
+ lseg = seg, seg = seg->next)
+ {
+ /* Use the bitmap to attribute the SSNs. */
+ while(holes_bmp & 1)
+ {
+ mfs->next_ssn++;
+ holes_bmp >>= 1;
+ if (start_counting_holes)
+ mfs->holes_seg_nb++;
+ }
+ start_counting_holes = true;
+ holes_bmp >>= 1;
+ seg->header.ssn = mfs->next_ssn++;
+ seg->header.mfbo = 0;
+ seg->header.vpbf = true;
+ seg->header.mmqf = mme;
+ seg->header.mfbf = false;
+ seg->header.opsf = false;
+ seg->header.rsvd = 0;
+ seg->expiration_ntb = expiration_count * UTILS_MFS_EXPIRATION_NTB_STEP
+ + TEST_PBPROC_NTB_OFFSET_TCK + TEST_PBPROC_EXPIRATION_DATE_OFFSET;
+ expiration_count++;
+ }
+ pbproc_mfs_insert_ (mfs, seg_first, seg_last, seg_nb);
+ pbproc_mfs_provide (mfs, seg_nb);
+ }
+ else
+ {
+ mfs->seg_nb = seg_nb;
+ }
+ return mfs;
+}
+
+static mfs_tx_t * local_mfs = NULL;
+
+mfs_tx_t *
+utils_mfs_tx_prepare_save (bool bcast, bool mme, uint lid, uint tei,
+ uint seg_nb)
+{
+ local_mfs = utils_mfs_tx_prepare(bcast, mme, lid, tei, seg_nb);
+ return local_mfs;
+}
+
+void
+utils_mfs_tx_cleanup (mfs_tx_t *mfs)
+{
+ if (mfs->head)
+ {
+ blk_release_desc_range (&mfs->head->blk, &mfs->tail->blk);
+ slist_init (mfs->, bare);
+ }
+ blk_release (mfs);
+}
+
+tonemap_t *
+utils_sta_prepare_default_tonemap (test_pbproc_t *tp, bool tx, uint tei,
+ uint tmi, uint tm_mod, uint tm_max_fl_tck,
+ uint *dx)
+{
+ dbg_assert (tmi < TONEMAP_INDEX_NB
+ || tmi == TONEMAP_INDEX_INITIAL_START
+ || tmi == TONEMAP_INDEX_INITIAL_ERROR
+ || tmi == TONEMAP_INDEX_INITIAL_SOUND_COMPLETE);
+ mac_store_sta_add (tp->store, tei);
+ sta_t *sta = mac_store_sta_get (tp->store, tei);
+ dbg_assert (sta);
+ if (tm_max_fl_tck)
+ {
+ uint max_fl_av = MAC_TCK_TO_FL (tm_max_fl_tck);
+ if (tx)
+ sta->tx_tonemaps->max_fl_av = max_fl_av;
+ else
+ sta->rx_tonemaps->max_fl_av = max_fl_av;
+ }
+ if (tx)
+ sta->tx_tonemaps->default_tmi = tmi;
+ else
+ sta->rx_tonemaps->default_tmi = tmi;
+ tonemap_t *tm = NULL;
+ if (tmi == TONEMAP_INDEX_INITIAL_START
+ || tmi == TONEMAP_INDEX_INITIAL_ERROR
+ || tmi == TONEMAP_INDEX_INITIAL_SOUND_COMPLETE)
+ {
+ /* Use ROBO. */
+ tm = &tp->config.tonemask_info.tonemap_robo[PHY_MOD_ROBO];
+ }
+ else if (tmi >= PHY_MOD_ROBO_NB)
+ {
+ if (tm_mod)
+ {
+ /* Create a tonemap. */
+ tm = tonemap_alloc ();
+ if (tx)
+ sta->tx_tonemaps->tm[tmi] = tm;
+ else
+ sta->rx_tonemaps->tm[tmi] = tm;
+ tm->cpf = true;
+ tm->fecrate = PHY_FEC_RATE_16_21;
+ tm->gil = PHY_GIL_417;
+ tm->bits_per_symbol = tm_mod * tp->config.tonemask_info.carrier_nb;
+ tonemap_update (tm, TONEMAP_P_PBERROR_DEFAULT_UF32);
+ /* Do not fill tonemap, unused. */
+ }
+ else
+ {
+ /* Reuse previously defined one. */
+ if (tx)
+ tm = sta->tx_tonemaps->tm[tmi];
+ else
+ tm = sta->rx_tonemaps->tm[tmi];
+ /* If no tonemap, use ROBO for SOUND frame. */
+ if (!tm)
+ tm = &tp->config.tonemask_info.tonemap_robo[PHY_MOD_ROBO];
+ }
+ }
+ else
+ {
+ /* Use a ROBO one. */
+ tm = &tp->config.tonemask_info.tonemap_robo[tmi];
+ }
+ sta->rx_tonemaps->sound_frame_counter = TONEMAP_SOUND_FRAME_COUNTER;
+ blk_release (sta);
+ if (dx)
+ *dx = tm->gil == PHY_GIL_417 ? MAC_DX417_TCK
+ : (tm->gil == PHY_GIL_567 ? MAC_DX567_TCK : MAC_DX3534_TCK);
+ return tm;
+}
+
+uint
+utils_sta_prepare_intervals (test_pbproc_t *tp, uint tei,
+ utils_interval_t *intervals,
+ uint default_tmi)
+{
+ uint intervals_version;
+ utils_interval_t *i;
+ dbg_assert (tp);
+ sta_t *sta = mac_store_sta_get (tp->store, tei);
+ dbg_assert (sta);
+ tonemaps_t *tms = sta->tx_tonemaps;
+ dbg_assert (tms->default_tmi < TONEMAP_INDEX_NB);
+ for (i = intervals; i->end_offset_tck; i++)
+ {
+ dbg_check (mac_interval_append (
+ tms, MAC_TCK_TO_ATU (i->end_offset_tck), i->tmi));
+ if (i->tm_mod && !tms->tm[i->tmi])
+ {
+ tonemap_t *tm = tonemap_alloc ();
+ tms->tm[i->tmi] = tm;
+ tm->cpf = true;
+ tm->fecrate = PHY_FEC_RATE_16_21;
+ tm->gil = PHY_GIL_417;
+ tm->bits_per_symbol =
+ i->tm_mod * tp->config.tonemask_info.carrier_nb;
+ tonemap_update (tm, TONEMAP_P_PBERROR_DEFAULT_UF32);
+ /* Do not fill tonemap, unused. */
+ }
+ }
+ mac_interval_commit_changes (tms, 0);
+ tms->default_tmi = default_tmi;
+ intervals_version = tms->intervals->version;
+ blk_release (sta);
+ return intervals_version;
+}
+
+void
+utils_prepare_encryption (test_pbproc_t *tp, bool encrypted, bool sta_auth,
+ uint tei, uint nek_switch)
+{
+ dbg_assert (tp);
+ dbg_assert (nek_switch == 0 || nek_switch == 1);
+ static mac_nek_t nek_store[2] = {
+ /* 0 */
+ {
+ .eks = 0,
+ .in_use = true,
+ .nek_enc = { 0xe0c75493, 0xda5ece2a, 0x956229e9, 0x85b0b79b },
+ .nek_dec = { 0x9e0c7631, 0xc26064c3, 0x97180120, 0xb81f230c }
+ },
+ /* 1 */
+ {
+ .eks = MAC_EKS_NB,
+ .in_use = false,
+ .nek_enc = { 0, 0, 0, 0 },
+ .nek_dec = { 0, 0, 0, 0 }
+ }
+ };
+ if (encrypted)
+ {
+ tp->config.authenticated = true;
+ tp->config.nek_mgr.use[nek_switch] = &nek_store[0];
+ tp->config.nek_mgr.use[!nek_switch] = &nek_store[1];
+ /* Setup allocation. */
+ tp->pbproc->alloc.nek_switch = nek_switch;
+ if (sta_auth)
+ {
+ sta_t *sta = mac_store_sta_get (tp->store, tei);
+ dbg_assert (sta);
+ sta->authenticated = true;
+ blk_release (sta);
+ }
+ }
+ else
+ {
+ tp->config.authenticated = false;
+ tp->config.nek_mgr.use[nek_switch] = &nek_store[1];
+ tp->config.nek_mgr.use[!nek_switch] = &nek_store[1];
+ }
+}
+