summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilenko Jelisavcic2013-01-23 11:58:47 +0100
committerMilenko Jelisavcic2013-05-17 17:06:56 +0200
commitc4af9ed1b61707fab13f3f6900a2b963ecec563e (patch)
tree532bee2e6b467e25a823c20766054c528dd4d796
parentb5a00337ad99cc8451d0c0a7090858c4117599b5 (diff)
cesar/mac/pbproc: modify rts-cts part, refs #3976
* limit rts-cts tolerance. * cancel prepared mpdu. * add support for sound frames. * activate tx rts-cts.
-rw-r--r--cesar/mac/pbproc/Module2
-rw-r--r--cesar/mac/pbproc/src/fsm_top.c2
-rw-r--r--cesar/mac/pbproc/src/fsm_tx_rts_cts.c57
-rw-r--r--cesar/mac/pbproc/src/pbproc.c2
-rw-r--r--cesar/mac/pbproc/src/prep_mpdu.c3
-rw-r--r--cesar/mac/pbproc/test/pbproc/Makefile2
-rw-r--r--cesar/mac/pbproc/test/pbproc/src/prep_mpdu.c80
-rw-r--r--cesar/mac/pbproc/test/pbproc/src/rx_rts_cts.c33
-rw-r--r--cesar/mac/pbproc/test/pbproc/src/test_pbproc.c4
-rw-r--r--cesar/mac/pbproc/test/pbproc/src/tx_rts_cts.c318
10 files changed, 472 insertions, 31 deletions
diff --git a/cesar/mac/pbproc/Module b/cesar/mac/pbproc/Module
index 8a14e1e5e0..1b25205d1d 100644
--- a/cesar/mac/pbproc/Module
+++ b/cesar/mac/pbproc/Module
@@ -2,7 +2,7 @@ SOURCES := mfs.c pbproc.c fc.c \
prep_mpdu.c \
fsm.c fsm_top.c fsm_handle_fc.c \
fsm_rx_data.c fsm_rx_beacon.c fsm_rx_sound.c \
- fsm_tx_data.c fsm_tx_sound.c \
+ fsm_tx_data.c fsm_tx_sound.c fsm_tx_rts_cts.c \
sacki_enc.c sacki_dec.c
ifeq ($(CONFIG_TRACE),y)
SOURCES += trace.c
diff --git a/cesar/mac/pbproc/src/fsm_top.c b/cesar/mac/pbproc/src/fsm_top.c
index 760d2c9e32..23b7cf54d1 100644
--- a/cesar/mac/pbproc/src/fsm_top.c
+++ b/cesar/mac/pbproc/src/fsm_top.c
@@ -177,7 +177,7 @@ pbproc_ftop__idle__access (pbproc_t *ctx)
ctx->prep_mpdu.current->pb_nb_total);
if (ctx->prep_mpdu.rts_cts)
{
- //pbproc_ftrc__handle (ctx);
+ pbproc_ftrc__handle (ctx);
}
else if (ctx->prep_mpdu.sound_reason_code != TONEMAP_SRC_NULL)
{
diff --git a/cesar/mac/pbproc/src/fsm_tx_rts_cts.c b/cesar/mac/pbproc/src/fsm_tx_rts_cts.c
index 792ca3add5..00aa587f08 100644
--- a/cesar/mac/pbproc/src/fsm_tx_rts_cts.c
+++ b/cesar/mac/pbproc/src/fsm_tx_rts_cts.c
@@ -17,6 +17,7 @@
#include "mac/pbproc/inc/fsm_top.h"
#include "mac/pbproc/inc/fsm_tx_data.h"
+#include "mac/pbproc/inc/fsm_tx_sound.h"
#include "mac/pbproc/inc/fsm_handle_fc.h"
#include "mac/pbproc/inc/prep_mpdu.h"
@@ -36,18 +37,33 @@ void ARCH_ILRAM
pbproc_ftrc__handle (pbproc_t *ctx)
{
dbg_claim (ctx);
- phy_tx_frame (ctx->phy, ctx->prep_mpdu.rts_tx_date, false,
- ctx->access.access_date, ctx->prep_mpdu.rts_fc_av.words, 0,
- PHY_PB_SIZE_NONE, PHY_FC_MODE_AV_1);
+ if (PHY_FC_MODE_IS_HYBRID (ctx->prep_mpdu.fc_mode))
+ phy_tx_fc10 (ctx->phy, ctx->prep_mpdu.rts_tx_date,
+ ctx->prep_mpdu.fc10);
+ phy_tx_param_short (ctx->phy, ctx->prep_mpdu.fc_mode);
+ phy_tx_frame (ctx->phy, ctx->prep_mpdu.rts_tx_date, false, true,
+ ctx->prep_mpdu.rts_fc_av.words);
ca_access_vcs_restart_eifs (ctx->ca, ctx->prep_mpdu.rts_tx_date);
phy_rx_activate (ctx->phy, false,
- ctx->prep_mpdu.rts_tx_date + ctx->rts_tck, true);
+ ctx->prep_mpdu.rts_tx_date
+ + ctx->times.rts_rcg_tck, true);
pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_TX_WAIT_CTS);
}
-void ARCH_ILRAM
-pbproc_ftrc__tx_wait_cts__rx_fc (pbproc_t *ctx,
- u32 rx_date,
+static void
+pbproc_ftrc_tx_cancel (pbproc_t *ctx)
+{
+ dbg_claim (ctx);
+ ctx->stats.rts_fail++;
+ pbproc_prep_mpdu_t *prep = &ctx->prep_mpdu;
+ if (prep->sound_reason_code != TONEMAP_SRC_NULL)
+ pbproc_prep_mpdu_sound_ack (ctx, false);
+ else
+ pbproc_prep_mpdu_cancel_burst (ctx);
+}
+
+void ARCH_ILRAM_PRIO (2)
+pbproc_ftrc__tx_wait_cts__rx_fc (pbproc_t *ctx, u32 rx_date,
const pbproc_fc_t *fc_av)
{
dbg_claim (ctx);
@@ -57,32 +73,37 @@ pbproc_ftrc__tx_wait_cts__rx_fc (pbproc_t *ctx,
&& fc_av->rts_cts.rtsf == false
&& fc_av->generic.access == false
&& fc_av->generic.snid == ctx->alloc.snid
- && fc_av->rts_cts.stei == ctx->prep_mpdu.dtei
+ && fc_av->rts_cts.stei == ctx->prep_mpdu.rts_fc_av.rts_cts.dtei
&& fc_av->rts_cts.dtei == ctx->config->tei
&& fc_av->rts_cts.lid == ctx->prep_mpdu.lid
- && fc_av->rts_cts.mcf == ctx->prep_mpdu.mcf
- && less_mod2p32 (ctx->prep_mpdu.rts_tx_date + ctx->times.rts_rcg_tck
- - ctx->times.tolerance_tck, rx_date)
&& less_mod2p32 (ctx->prep_mpdu.rts_tx_date + ctx->times.rts_rcg_tck
- + ctx->times.tolerance_tck, rx_date))
+ - MAC_TOLERANCE_TCK, rx_date)
+ && !less_mod2p32 (ctx->prep_mpdu.rts_tx_date + ctx->times.rts_rcg_tck
+ + MAC_TOLERANCE_TCK, rx_date))
{
+ /* Prepare reception of FC only. Unblock the HW.*/
+ phy_rx_prepare_short (ctx->phy);
/* XXX Could add some checks, for duration for example. */
- /* Ok, now transmit data. */
- pbproc_ftda__handle (ctx);
+ /* Ok, now transmit data/sound. */
+ if (ctx->prep_mpdu.sound_reason_code != TONEMAP_SRC_NULL)
+ pbproc_ftso__handle (ctx);
+ else
+ pbproc_ftda__handle (ctx);
}
else
{
/* Not our CTS. */
- ctx->stats.rts_fail++;
pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
+ /* Cancel the transmission. */
+ pbproc_ftrc_tx_cancel (ctx);
}
}
-void ARCH_ILRAM
+void ARCH_ILRAM_PRIO (2)
pbproc_ftrc__tx_wait_cts__access (pbproc_t *ctx)
{
dbg_claim (ctx);
- ctx->stats.rts_fail++;
+ /* Cancel the transmission. */
+ pbproc_ftrc_tx_cancel (ctx);
pbproc_ftop__idle__access (ctx);
}
-
diff --git a/cesar/mac/pbproc/src/pbproc.c b/cesar/mac/pbproc/src/pbproc.c
index 167aadc38d..df2b1df00e 100644
--- a/cesar/mac/pbproc/src/pbproc.c
+++ b/cesar/mac/pbproc/src/pbproc.c
@@ -250,7 +250,7 @@ pbproc_init (mac_config_t *config, mac_store_t *store)
pbproc_frda_init (ctx);
pbproc_frbe_init (ctx);
pbproc_frso_init (ctx);
- //pbproc_ftrc_init (ctx);
+ pbproc_ftrc_init (ctx);
pbproc_ftda_init (ctx);
pbproc_ftso_init (ctx);
/* Setup traffic indicator. */
diff --git a/cesar/mac/pbproc/src/prep_mpdu.c b/cesar/mac/pbproc/src/prep_mpdu.c
index a7a9659d88..a6b0055801 100644
--- a/cesar/mac/pbproc/src/prep_mpdu.c
+++ b/cesar/mac/pbproc/src/prep_mpdu.c
@@ -270,7 +270,8 @@ pbproc_prep_mpdu (pbproc_t *ctx, mfs_tx_t *mfs)
? MAC_TEI_UNASSOCIATED : ctx->config->tei;
/* Should we use RTS CTS?
* TODO: real test is more complex. */
- prep->rts_cts = mfs->common.bcast && ctx->config->rts_broadcast;
+ prep->rts_cts = mfs->common.bcast && ctx->config->rts_broadcast
+ && MAC_TEI_IS_STA (ack_dtei);
/* Prepare start dates and raw access duration. */
if (prep->rts_cts)
{
diff --git a/cesar/mac/pbproc/test/pbproc/Makefile b/cesar/mac/pbproc/test/pbproc/Makefile
index 57ae1ebd61..ac1bb9d877 100644
--- a/cesar/mac/pbproc/test/pbproc/Makefile
+++ b/cesar/mac/pbproc/test/pbproc/Makefile
@@ -4,7 +4,7 @@ INCLUDES = mac/pbproc/test/pbproc/override mac/pbproc/test/pbproc
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 rx_rts_cts.c \
+ rx_data.c rx_sound.c rx_rts_cts.c tx_rts_cts.c\
scenario_defs.c ca.c phy.c hal.c utils.c
test_pbproc_MODULES = lib lib/scenario mac/pbproc mac/common hal/watchdog
hal_watchdog_MODULE_SOURCES =
diff --git a/cesar/mac/pbproc/test/pbproc/src/prep_mpdu.c b/cesar/mac/pbproc/test/pbproc/src/prep_mpdu.c
index fb8b9bc994..852feac5df 100644
--- a/cesar/mac/pbproc/test/pbproc/src/prep_mpdu.c
+++ b/cesar/mac/pbproc/test/pbproc/src/prep_mpdu.c
@@ -31,6 +31,8 @@ struct prep_mpdu_test_t
bool mme;
/** Partial acknowledgement. */
bool partial_ack;
+ /** RTS_CTS. BCAST and partial_ack enabled. */
+ bool rts_broadcast;
/** Number of MFS segments. */
int mfs_seg_nb;
/** Duration of the access, measured as a number of symbol. */
@@ -147,6 +149,7 @@ prep_mpdu_test_f (test_t t, test_pbproc_t *tp, u32 date,
uint seg_nb_pending = params->seg_nb_pending;
tp->config.partial_ack_tei_default =
params->partial_ack || params->unassociated ? 3 : MAC_TEI_BCAST;
+ tp->config.rts_broadcast = params->rts_broadcast;
/* Ask for channel data to enable sound transmission. */
u32 chandata_conf[1] = { 0 };
pbproc_set_chandata_conf (
@@ -223,6 +226,16 @@ prep_mpdu_test_f (test_t t, test_pbproc_t *tp, u32 date,
+ 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;
+ uint rts_cts_dur_tck = 0;
+ /* RTS_CTS is active when: bcast and (partial ack or regular data). */
+ bool rts_cts = params->partial_ack && params->bcast
+ && params->rts_broadcast
+ && access->duration_tck >= MAC_MS_TO_TCK (1);
+ if (rts_cts)
+ {
+ rts_cts_dur_tck = tp->pbproc->times.rts_rcg_cts_cmg_tck;
+ access->duration_tck += rts_cts_dur_tck;
+ }
access->prp = false;
access->cfp = cfp;
tp->pbproc->detect.beacon_detected = params->beacon_detected;
@@ -246,11 +259,11 @@ prep_mpdu_test_f (test_t t, test_pbproc_t *tp, u32 date,
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->rts_cts == 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);
+ test_fail_unless (prep->tx_date == date + rts_cts_dur_tck);
}
if (sound_reason_code != TONEMAP_SRC_NULL)
{
@@ -373,6 +386,29 @@ prep_mpdu_test_f (test_t t, test_pbproc_t *tp, u32 date,
test_fail_unless (prep->flp_tck == MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ MAC_PAYLOAD_TCK (params->symb_nb, dx)
+ eff_rifs_tck);
+ if (rts_cts)
+ {
+ test_fail_unless (prep->rts_tx_date == access->access_date);
+ test_fail_unless (prep->tx_date == prep->rts_tx_date
+ + rts_cts_dur_tck);
+ /* Test RTS_CTS frame control. */
+ pbproc_fc_rts_cts_t fc = prep->rts_fc_av.rts_cts;
+ test_fail_unless (fc.dt_av = PBPROC_FC_DT_RTS_CTS
+ && fc.access == false
+ && fc.snid == tp->snid);
+ test_fail_unless (fc.stei == stei);
+ test_fail_unless (fc.dtei == ack_dtei);
+ test_fail_unless (fc.rtsf == true);
+ test_fail_unless (fc.mcf == params->bcast);
+ test_fail_unless (fc.mnbf == (params->bcast && params->unassociated));
+ /* Calculate complete rts_cts duration. */
+ uint rts_cts_duration = MAC_RCG_TCK + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK + MAC_CMG_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (params->symb_nb, dx) + eff_rifs_tck
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK;
+ test_fail_unless (fc.dur == MAC_TCK_TO_FL (rts_cts_duration));
+ }
if (params->encrypted)
{
test_fail_if (prep->bypass_aes);
@@ -821,6 +857,46 @@ prep_mpdu_basic_test_case (test_t t)
.symb_nb = 19, .main_seg_nb_total = 1,
.hp10_detected = true, .hp11_detected = true);
} test_end;
+ test_begin (t, "robo rts_cts multicast data partial ack")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 2, .duration_symb_nb = 40,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .rts_broadcast = true, .bcast = true,
+ .partial_ack = true);
+ } test_end;
+ test_begin (t, "robo rts_cts multicast data partial ack limit dur")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 2, .duration_symb_nb = 25,
+ .symb_nb = 19, .main_seg_nb_total = 1,
+ .rts_broadcast = true, .bcast = true,
+ .partial_ack = true);
+ } test_end;
+ test_begin (t, "robo rts_cts multicast data no partial ack")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 2, .duration_symb_nb = 40,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .rts_broadcast = true, .bcast = true);
+ } test_end;
+ test_begin (t, "robo rts_cts regular data (long frame)")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 2, .duration_symb_nb = 40,
+ .symb_nb = 38, .main_seg_nb_total = 2,
+ .rts_broadcast = true);
+ } test_end;
+ test_begin (t, "tm rts_cts regular data (short frame)")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 2, .duration_symb_nb = 40,
+ .symb_nb = 2, .main_seg_nb_total = 2,
+ .rts_broadcast = true,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
+ test_begin (t, "tm rts_cts regular data (long frame)")
+ {
+ prep_mpdu_test (t, &tp, 0, .mfs_seg_nb = 100, .duration_symb_nb = 60,
+ .symb_nb = 50, .main_seg_nb_total = 83,
+ .rts_broadcast = true,
+ .tmi = 5, .tm_mod = 10);
+ } test_end;
test_pbproc_uninit (&tp);
}
diff --git a/cesar/mac/pbproc/test/pbproc/src/rx_rts_cts.c b/cesar/mac/pbproc/test/pbproc/src/rx_rts_cts.c
index cb6baa0561..b4c42a20e4 100644
--- a/cesar/mac/pbproc/test/pbproc/src/rx_rts_cts.c
+++ b/cesar/mac/pbproc/test/pbproc/src/rx_rts_cts.c
@@ -36,6 +36,8 @@ struct rx_rts_cts_desc_t
bool mcf;
/** Multi-network broadcast flag. */
bool mnbf;
+ /** Hybrid mode. */
+ bool hybrid;
};
typedef struct rx_rts_cts_desc_t rx_rts_cts_desc_t;
@@ -50,10 +52,15 @@ rx_rts_cts_test_ (test_t t, test_pbproc_t *tp, rx_rts_cts_desc_t *desc)
bool reply = !desc->access_nfu && !desc->snid_nfu && !desc->tei_nfu
&& !desc->cts;
uint date = 0x123456;
- uint reply_date = date + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ const uint pre_fcs_tck = (desc->hybrid ?
+ MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK :
+ MAC_PREAMBLE_TCK) + MAC_FC_AV_TCK;
+ uint reply_date = date + pre_fcs_tck
+ (desc->cts ? MAC_CMG_TCK : MAC_RCG_TCK);
- uint after_date = reply_date
- + (reply ? MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CMG_TCK : 0);
+ uint after_date = reply_date + (reply ? pre_fcs_tck + MAC_CMG_TCK : 0);
+ uint fc_mode = desc->hybrid ? PHY_FC_MODE_HYBRID_1 : PHY_FC_MODE_AV_1;
+ const uint beacon_tck = MAC_MS_TO_TCK (1000) / 50;
+ test_pbproc_alloc (tp, desc->hybrid, date / beacon_tck * beacon_tck);
pbproc_fc_t fc = { .rts_cts = {
.dt_av = PBPROC_FC_DT_RTS_CTS,
.access = desc->access_nfu,
@@ -85,8 +92,9 @@ rx_rts_cts_test_ (test_t t, test_pbproc_t *tp, rx_rts_cts_desc_t *desc)
SCENARIO_EVENT (phy_tx_cancel),
SCENARIO_EVENT (ca_access_hold),
SCENARIO_EVENT (phy_rx_prepare_short),
- SCENARIO_EVENT_COND (reply, phy_tx_param_short,
- .fc_mode = PHY_FC_MODE_AV_1),
+ SCENARIO_EVENT_COND (desc->hybrid && reply, phy_tx_fc10,
+ .date = reply_date, .fc10 = 0),
+ SCENARIO_EVENT_COND (reply, phy_tx_param_short, .fc_mode = fc_mode),
SCENARIO_EVENT_COND (reply, phy_tx_frame, .date = reply_date,
.want_conf = false, .stop_tx_on_prp_lost = true),
SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = after_date),
@@ -125,7 +133,7 @@ rx_rts_cts_test_ (test_t t, test_pbproc_t *tp, rx_rts_cts_desc_t *desc)
test_fail_unless (cts.mnbf == desc->mnbf);
test_fail_unless (cts.mcf == desc->mcf);
test_fail_unless (cts.dur == desc->dur_fl - MAC_TCK_TO_FL (
- MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_RCG_TCK));
+ pre_fcs_tck + MAC_RCG_TCK));
test_fail_unless (cts.reserved0 == 0);
test_fail_unless (cts.reserved1 == 0);
test_fail_unless (cts.reserved2 == 0);
@@ -168,6 +176,19 @@ rx_rts_cts_basic_test_case (test_t t)
{
rx_rts_cts_test (t, &tp, .dur_fl = 1000, .mnbf = true, .mcf = true);
} test_end;
+ test_begin (t, "fu hybrid")
+ {
+ rx_rts_cts_test (t, &tp, .dur_fl = 1000, .hybrid = true);
+ } test_end;
+ test_begin (t, "fu hybrid partial ack")
+ {
+ rx_rts_cts_test (t, &tp, .dur_fl = 1000, .mcf = true, .hybrid = true);
+ } test_end;
+ test_begin (t, "fu hybrid multi network partial ack")
+ {
+ rx_rts_cts_test (t, &tp, .dur_fl = 1000, .mnbf = true, .mcf = true,
+ .hybrid = true);
+ } test_end;
test_pbproc_uninit (&tp);
}
diff --git a/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c b/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c
index 8ec218768a..eff5fa651e 100644
--- a/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c
+++ b/cesar/mac/pbproc/test/pbproc/src/test_pbproc.c
@@ -32,6 +32,9 @@ void
tx_sound_test_suite (test_t t);
void
+tx_rts_cts_test_suite (test_t t);
+
+void
rx_data_test_suite (test_t t);
void
@@ -518,6 +521,7 @@ main (int argc, char **argv)
prep_mpdu_test_suite (t);
tx_data_test_suite (t);
tx_sound_test_suite (t);
+ tx_rts_cts_test_suite (t);
rx_data_test_suite (t);
rx_sound_test_suite (t);
rx_rts_cts_test_suite (t);
diff --git a/cesar/mac/pbproc/test/pbproc/src/tx_rts_cts.c b/cesar/mac/pbproc/test/pbproc/src/tx_rts_cts.c
new file mode 100644
index 0000000000..1a93f36c7e
--- /dev/null
+++ b/cesar/mac/pbproc/test/pbproc/src/tx_rts_cts.c
@@ -0,0 +1,318 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2012 MStar
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/tx_rts_cts.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"
+
+enum rts_cts_test_t
+{
+ RTS_CTS_TEST_DATA,
+ RTS_CTS_TEST_CTS_LATE,
+ RTS_CTS_TEST_CTS_NFU,
+ RTS_CTS_TEST_CTS_NO,
+};
+typedef enum rts_cts_test_t rts_cts_test_t;
+
+void
+tx_rts_cts_test (test_t t, test_pbproc_t *tp, u32 date, uint mfs_seg_nb,
+ uint duration_tck, uint symb_nb,
+ uint data_seg_nb_total, uint tmi, rts_cts_test_t type,
+ bool hybrid)
+{
+ test_within (t);
+ const uint lid = 1;
+ const uint stei = tp->config.tei;
+ const uint dtei = MAC_TEI_BCAST;
+ const uint ack_dtei = 12;
+ tp->config.partial_ack_tei_default = ack_dtei;
+ tp->config.rts_broadcast = true;
+ 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;
+ if (tmi != PHY_MOD_ROBO)
+ tm = utils_sta_prepare_default_tonemap (tp, true, dtei, tmi, 10, 0,
+ &dx);
+ uint rifs_tck = tmi < PHY_MOD_ROBO_NB ? MAC_RIFS_DEFAULT_TCK
+ : MAC_RIFS_SPC_ANY_TCK;
+ mfs_tx_t *mfs = utils_mfs_tx_prepare (true, false, lid, dtei, mfs_seg_nb);
+ test_pbproc_alloc (tp, hybrid, date / beacon_tck * beacon_tck);
+ uint fc_mode = hybrid ? PHY_FC_MODE_HYBRID_1 : PHY_FC_MODE_AV_1;
+ ca_access_param_t access = {
+ .access_date = date,
+ .duration_tck = duration_tck,
+ .prp = true,
+ .cfp = false,
+ };
+ /* CTS. */
+ pbproc_fc_rts_cts_t rts_cts_fc = {
+ .dt_av = PBPROC_FC_DT_RTS_CTS,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = stei,
+ .stei = ack_dtei + (type == RTS_CTS_TEST_CTS_NFU ? 2 : 0),
+ .rtsf = false,
+ .lid = lid,
+ .mnbf = false,
+ .mcf = false,
+ .dur = 1000,
+ .reserved0 = 0,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .fccs_av = 0,
+ };
+ /* SACK for sent frame. */
+ pbproc_fc_sack_t sack_fc = {
+ .dt_av = PBPROC_FC_DT_SACK,
+ .access = false,
+ .snid = tp->snid,
+ .dtei = stei,
+ .rrtf = false,
+ .mfs_rsp_data = MFS_FSM_RSP_ACK,
+ .mfs_rsp_mgmt = MFS_FSM_RSP_ACK,
+ .sackt3 = 0,
+ .sackt2 = 0,
+ .sackt1 = 0,
+ .sackt0 = PBPROC_FC_SACKT_UNIFORM,
+ .sacki = {0x1, 0},/* All OK. */
+ .sacki_last = 0,
+ .fccs_av = 0,
+ };
+ const uint pre_fcs_tck = (hybrid ? MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK :
+ MAC_PREAMBLE_TCK) + MAC_FC_AV_TCK;
+ const uint pre_fc_fl_tck = pre_fcs_tck
+ + MAC_PAYLOAD_TCK (symb_nb, MAC_DX417_TCK) + rifs_tck;
+ const uint rts_cts_rcg_tck = pre_fcs_tck + MAC_RCG_TCK;
+ /* Short scenario. Frame are not sent.*/
+ bool rts_fail = type == RTS_CTS_TEST_CTS_LATE ||
+ type == RTS_CTS_TEST_CTS_NO || type == RTS_CTS_TEST_CTS_NFU;
+ bool no_cts = type == RTS_CTS_TEST_CTS_NO;
+ uint date2 = date + tp->pbproc->times.rts_rcg_cts_cmg_tck;
+ uint date3 = date + rts_cts_rcg_tck +
+ (type == RTS_CTS_TEST_CTS_LATE ? MAC_TOLERANCE_TCK + 100 : 0);
+ /* Scenarios. */
+ scenario_entry_t entries_long[] = {
+ /* Send RTS. */
+ 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 (hybrid, phy_tx_fc10, .date = date,
+ .fc10 = 0x200000),
+ SCENARIO_EVENT (phy_tx_param_short, .fc_mode = fc_mode),
+ 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 + rts_cts_rcg_tck,
+ .pre_detection = true),
+ /* Receive CTS. */
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date + rts_cts_rcg_tck,
+ .fc_av = (u32 *) &rts_cts_fc, .slot_count = 15),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ /* Prepare to send frame. Phase I, send only BCAST frame. No SACK. */
+ SCENARIO_EVENT_COND (hybrid, phy_tx_fc10, .date = date2,
+ .fc10 = 0x200000),
+ SCENARIO_EVENT (phy_pbdma_start, .bypass_aes = true,
+ .nb_total = data_seg_nb_total,
+ .nb_pb_it = 0, .chandata = false, .now = false),
+ SCENARIO_EVENT (phy_tx_param, .fc_mode = fc_mode,
+ .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 = symb_nb),
+ SCENARIO_EVENT (phy_tx_frame, .date = date2, .want_conf = true,
+ .stop_tx_on_prp_lost = false),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs, .start_date = date2),
+ SCENARIO_ACTION (phy_access_conf),
+ SCENARIO_EVENT (phy_tx_prepare),
+ SCENARIO_EVENT (ca_backoff_deferred, .slot_count = 13),
+ SCENARIO_EVENT (ca_access_vcs_restart_eifs,
+ .start_date = date2 + pre_fc_fl_tck),
+ SCENARIO_EVENT (phy_rx_activate, .now = false,
+ .date = date2 + pre_fc_fl_tck,
+ .pre_detection = true),
+ /* Wait for SACKD. */
+ SCENARIO_ACTION (phy_rx_fc, .rx_date = date2 + pre_fc_fl_tck,
+ .fc_av = (u32 *) &sack_fc),
+ SCENARIO_EVENT (phy_rx_prepare_short),
+ SCENARIO_EVENT (ca_access_done),
+ SCENARIO_EVENT (ca_backoff_success),
+ SCENARIO_EVENT (ca_access_vcs_restart,
+ .end_date = date2 + pre_fc_fl_tck + pre_fcs_tck
+ + MAC_CIFS_TCK),
+ SCENARIO_END
+ };
+ scenario_entry_t entries_short[] = {
+ /* Send RTS. */
+ 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 (hybrid, phy_tx_fc10, .date = date,
+ .fc10 = 0x200000),
+ SCENARIO_EVENT (phy_tx_param_short, .fc_mode = fc_mode),
+ 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 + rts_cts_rcg_tck,
+ .pre_detection = true),
+ /* Receive CTS. */
+ SCENARIO_ACTION_COND (!no_cts, phy_rx_fc, .rx_date = date3,
+ .fc_av = (u32 *) &rts_cts_fc, .slot_count = 15),
+ SCENARIO_EVENT_COND (!no_cts, phy_tx_cancel),
+ SCENARIO_EVENT_COND (!no_cts, ca_access_hold),
+ SCENARIO_EVENT_COND (!no_cts, phy_rx_prepare_short),
+ SCENARIO_EVENT_COND (!no_cts, ca_access_vcs_restart_eifs,
+ .start_date = date3 + rts_cts_rcg_tck),
+ SCENARIO_EVENT_COND (!no_cts, phy_rx_activate, .now = false,
+ .date = date3 + rts_cts_rcg_tck,
+ .pre_detection = true),
+ SCENARIO_EVENT_COND (!no_cts, ca_access_done),
+ /* Timeout. Access timer activated. */
+ SCENARIO_ACTION_COND (no_cts, phy_access, .prp_won = true,
+ .access_param = &access, .slot_count = 600),
+ SCENARIO_EVENT_COND (no_cts, ca_access_done),
+ SCENARIO_EVENT_COND (no_cts, ca_access_hold),
+ SCENARIO_EVENT_COND (no_cts, ca_access_get_mfs),
+ SCENARIO_EVENT_COND (no_cts, ca_access_done),
+ SCENARIO_EVENT_COND (no_cts, ca_access_defer, .date = date),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .tp = tp,
+ };
+ test_pbproc_check_stats_reset (tp);
+ scenario_run (t, rts_fail ? entries_short : entries_long, &globals);
+
+ test_pbproc_check_stats (t, tp, .tx_data = rts_fail ? 0 : 1,
+ .tx_data_wack = rts_fail ? 0 : 1,
+ .tx_data_wack_ack = rts_fail ? 0 : 1,
+ .rts_fail = rts_fail ? 1 : 0,
+ .rx_handle_fc = rts_fail && !no_cts ? 1 : 0,
+ .tx_invalid = no_cts ? 1 : 0,
+ .rx_nfu = rts_fail && !no_cts ? 1 : 0);
+ test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_NOP);
+ test_fail_unless (mfs->stats.num_mpdus == (rts_fail ? 0 : 1));
+ test_fail_unless (mfs->stats.num_bursts == (rts_fail ? 0 : 1));
+ test_fail_unless (mfs->stats.num_pbs == (rts_fail ? 0 : data_seg_nb_total));
+ test_fail_unless (mfs->stats.num_segs_suc == (rts_fail ? 0 :
+ data_seg_nb_total));
+ utils_mfs_tx_cleanup (mfs);
+ if (tmi != PHY_MOD_ROBO)
+ dbg_check (mac_store_sta_remove (tp->store, dtei));
+ test_fail_unless (tp->pbproc->fsm.current_state == PBPROC_FSM_STATE_IDLE);
+}
+
+void
+tx_rts_cts_test_case (test_t t)
+{
+ test_pbproc_t tp;
+ test_case_begin (t, "basic");
+ test_pbproc_init (&tp);
+ const int pre_fcs_tck_hyb = MAC_PREAMBLE_HYBRID_TCK + MAC_FC_10_TCK
+ + MAC_FC_AV_TCK;
+ test_begin (t, "data")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 30,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (50, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CMG_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_RCG_TCK,
+ 38, 2, PHY_MOD_ROBO, RTS_CTS_TEST_DATA, false);
+ } test_end;
+ test_begin (t, "cts late")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 20,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (50, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CMG_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_RCG_TCK,
+ 38, 2, PHY_MOD_ROBO, RTS_CTS_TEST_CTS_LATE, false);
+ } test_end;
+ test_begin (t, "cts nfu")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 40,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (50, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CMG_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_RCG_TCK,
+ 19, 1, PHY_MOD_ROBO, RTS_CTS_TEST_CTS_NFU, false);
+ } test_end;
+ test_begin (t, "cts no")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 40,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_PAYLOAD_TCK (50, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_CMG_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_RCG_TCK,
+ 19, 1, PHY_MOD_ROBO, RTS_CTS_TEST_CTS_NO, false);
+ } test_end;
+ test_begin (t, "data hybrid")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 30,
+ pre_fcs_tck_hyb + MAC_PAYLOAD_TCK (50, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + pre_fcs_tck_hyb + MAC_CMG_TCK
+ + pre_fcs_tck_hyb + MAC_RCG_TCK,
+ 19, 1, PHY_MOD_ROBO, RTS_CTS_TEST_DATA, true);
+ } test_end;
+ test_begin (t, "cts late hybrid")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 30,
+ pre_fcs_tck_hyb + MAC_PAYLOAD_TCK (50, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + pre_fcs_tck_hyb + MAC_CMG_TCK
+ + pre_fcs_tck_hyb + MAC_RCG_TCK,
+ 19, 1, PHY_MOD_ROBO, RTS_CTS_TEST_CTS_LATE, true);
+ } test_end;
+ test_begin (t, "cts nfu hybrid")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 30,
+ pre_fcs_tck_hyb + MAC_PAYLOAD_TCK (40, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + pre_fcs_tck_hyb + MAC_CMG_TCK
+ + pre_fcs_tck_hyb + MAC_RCG_TCK,
+ 19, 1, PHY_MOD_ROBO, RTS_CTS_TEST_CTS_NFU, true);
+ } test_end;
+ test_begin (t, "cts no hybrid")
+ {
+ tx_rts_cts_test (t, &tp, 5462132, 30,
+ pre_fcs_tck_hyb + MAC_PAYLOAD_TCK (30, MAC_DX417_TCK)
+ + MAC_RIFS_DEFAULT_TCK
+ + pre_fcs_tck_hyb + MAC_CMG_TCK
+ + pre_fcs_tck_hyb + MAC_RCG_TCK,
+ 19, 1, PHY_MOD_ROBO, RTS_CTS_TEST_CTS_NO, true);
+ } test_end;
+ test_pbproc_uninit (&tp);
+}
+
+void
+tx_rts_cts_test_suite (test_t t)
+{
+ test_suite_begin (t, "tx rst/cts");
+ tx_rts_cts_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}