summaryrefslogtreecommitdiff
path: root/cesar/bsu/src
diff options
context:
space:
mode:
authorNélio Laranjeiro2011-05-04 16:36:17 +0200
committerNélio Laranjeiro2011-05-05 17:57:31 +0200
commit43e23b6d1358251bf2848cea2e8edb48289f6078 (patch)
treec2c2dd45afbebcf8f9a2415e76ce6df827e0fa84 /cesar/bsu/src
parentbe3ca553ef7c368e99d843e0b3b152fffb8c936e (diff)
cesar/bsu: fix schedule generation, closes #2432
When the station was acting as CCo. BSU was unable to modify the current schedule.
Diffstat (limited to 'cesar/bsu/src')
-rw-r--r--cesar/bsu/src/bsu.c157
1 files changed, 93 insertions, 64 deletions
diff --git a/cesar/bsu/src/bsu.c b/cesar/bsu/src/bsu.c
index b932b9b475..8982a423cc 100644
--- a/cesar/bsu/src/bsu.c
+++ b/cesar/bsu/src/bsu.c
@@ -9,6 +9,14 @@
* \file bsu/src/bsu.c
* \brief BSU core functions.
* \ingroup bsu
+ *
+ * Explanation of how bsu handles schedules programmation:
+ * - On timer event, BSU copy the first two CA schedules and just modify the
+ * start date. It creates the last and third one using data present in the
+ * beacon i.e. bsu->sta_avln->beacon.
+ * - On beacon reception, BSU write all the schedules for the CA, it allows
+ * the CA to have non persistent schedules programmed for the current
+ * beacon period.
*/
#include "common/std.h"
#include "lib/bitstream.h"
@@ -520,77 +528,95 @@ bsu_ca_schedules_nm_csma_only (bsu_t *ctx, bsu_beacon_t *beacon)
}
/**
- * End to fill the schedules and provide it to the CA.
+ * Get available slot of schedules for the CA.
* \param ctx the module context.
- * \param avln the station avln data containing the schedules read from the
- * beacon.
- * \param bp beacon period schedule array for the CA.
+ * \param indexes the array to fill with available slots.
*/
-PRIVATE inline void
-bsu_ca_schedules (bsu_t *ctx, bsu_avln_t *avln, ca_beacon_period_t *bp)
+PRIVATE void
+bsu_ca_schedules_available (bsu_t *ctx, uint *indexes)
{
- ca_schedule_t *schedule;
- uint i;
- u32 bpsd[BSU_BEACON_SCHEDULES_MAX];
- bsu_aclf_beacon_period_start_date (ctx->aclf, bpsd, COUNT (bpsd));
- /* Get the CA schedules from the next one and for BPSD_NB. */
- for (i = 1; i < COUNT (bpsd); i++)
+ uint i, j;
+ uint nb = 0;
+ bool in_use;
+ for (i = 0; i < CA_SCHEDULE_NB && nb < BSU_BEACON_SCHEDULES_MAX; i++)
{
- schedule = ca_alloc_get_schedule (ctx->ca, ctx->ca_index);
- bsu_schedules_merge (ctx, &avln->beacon, schedule, i);
- bsu_ca_schedules_settings (ctx, avln, schedule, i);
- bp[i].start_date = bpsd[i];
- bp[i].schedule_index = ctx->ca_index;
- ctx->ca_index++;
+ in_use = false;
+ for (j = 0; j < COUNT (ctx->ca_schedules_in_use) && !in_use; j++)
+ {
+ if (ctx->ca_schedules_in_use[j] == i)
+ in_use = true;
+ }
+ if (!in_use)
+ indexes[nb++] = i;
}
- /* Provide the schedules to the CA. */
- BSU_TRACE (SCHEDULES, bpsd[0], bpsd[1], bpsd[2]);
- ca_alloc_update_beacon_periods (ctx->ca, bp, COUNT (bpsd));
- ctx->ca_index = (ctx->ca_index + 1) % CA_SCHEDULE_NB;
}
/**
- * Fill the schedules and provide it to the CA on timer event.
+ * Fill the missing schedule for the CA.
* \param ctx the module context.
- * \param avln the station avln data containing the schedules read from the
- * beacon.
- * Merge the schedules read from the beacon.
- * Provide the schedules to the CA.
+ * \param avln the avln containing the data to fill the missing schedules.
+ * \param bp the array of data to provide to the CA.
+ * \param bpsd the array of beacon period start date to fill the
+ * allocations.
+ * \param start_index start filling the array at this index.
+ *
+ * This function takes an array with bp_nb - start_index elements filled
+ * corresponding to the current schedules in use in the CA. This should only
+ * fill the last ones.
+ *
+ * It is not this function responsibility to provide the computed schedules
+ * to the CA, the caller must handle it.
*/
-inline void
-bsu_ca_schedules__timer_event (bsu_t *ctx, bsu_avln_t *avln)
+PRIVATE void
+bsu_ca_schedule_prepare_missing (
+ bsu_t *ctx, bsu_avln_t *avln, ca_beacon_period_t *bp,
+ u32 *bpsd, uint start_index)
{
- dbg_assert (avln);
- ca_beacon_period_t beacon_period[BSU_BEACON_SCHEDULES_MAX];
- bsu_aclf_beacon_period_start_date (
- ctx->aclf, &beacon_period[0].start_date, 1);
- beacon_period[0].schedule_index = ctx->ca_index_last_first;
- bsu_ca_schedules (ctx, avln, beacon_period);
+ ca_schedule_t *schedule;
+ uint i, j;
+ uint ca_index[BSU_BEACON_SCHEDULES_MAX];
+ bsu_ca_schedules_available (ctx, ca_index);
+ /* Get non used schedules from the CA. */
+ for (i = start_index, j = 0; i < BSU_BEACON_SCHEDULES_MAX; i++, j++)
+ {
+ /* Get the next channel access index not in use. */
+ schedule = ca_alloc_get_schedule (ctx->ca, ca_index[j]);
+ bsu_schedules_merge (ctx, &avln->beacon, schedule, i);
+ bsu_ca_schedules_settings (ctx, avln, schedule, i);
+ bp[i].start_date = bpsd[i];
+ bp[i].schedule_index = ca_index[j];
+ }
+ /* Store the current schedules in use. */
+ for (i = 0; i < BSU_BEACON_SCHEDULES_MAX; i++)
+ ctx->ca_schedules_in_use[i] = bp[i].schedule_index;
}
/**
- * Fill the schedules and provide it to the CA on beacon reception.
+ * End to fill the schedules and provide it to the CA.
* \param ctx the module context.
* \param avln the station avln data containing the schedules read from the
* beacon.
- * Merge the schedules read from the beacon.
- * Provide the schedules to the CA.
+ * \param copy_nb copy the first nb schedules.
*/
-inline void
-bsu_ca_schedules__beacon_reception (bsu_t *ctx, bsu_avln_t *avln)
+void
+bsu_ca_schedules (bsu_t *ctx, bsu_avln_t *avln, uint copy_nb)
{
- dbg_assert (avln);
+ uint start_nb;
+ u32 bpsd[BSU_BEACON_SCHEDULES_MAX];
ca_beacon_period_t beacon_period[BSU_BEACON_SCHEDULES_MAX];
- ctx->ca_index_last_first =
- (ctx->ca_index_last_first + CA_SCHEDULE_NB / 2) % CA_SCHEDULE_NB;
- bsu_aclf_beacon_period_start_date (
- ctx->aclf, &beacon_period[0].start_date, 1);
- beacon_period[0].schedule_index = ctx->ca_index_last_first;
- ca_schedule_t *schedule =
- ca_alloc_get_schedule (ctx->ca, ctx->ca_index_last_first);
- bsu_schedules_merge (ctx, &avln->beacon, schedule, 0);
- bsu_ca_schedules_settings (ctx, avln, schedule, 0);
- bsu_ca_schedules (ctx, avln, beacon_period);
+ bsu_aclf_beacon_period_start_date (ctx->aclf, bpsd, COUNT (bpsd));
+ for (start_nb = 0; start_nb < copy_nb; start_nb++)
+ {
+ beacon_period[start_nb].start_date = bpsd[start_nb];
+ beacon_period[start_nb].schedule_index =
+ ctx->ca_schedules_in_use[start_nb];
+ }
+ bsu_ca_schedule_prepare_missing (
+ ctx, avln, beacon_period, bpsd, start_nb);
+ /* Provide the schedules to the CA. */
+ BSU_TRACE (SCHEDULES, bpsd[0], bpsd[1], bpsd[2]);
+ ca_alloc_update_beacon_periods (
+ ctx->ca, beacon_period, BSU_BEACON_SCHEDULES_MAX);
}
/**
@@ -803,7 +829,7 @@ bsu_timer_event_process (void *ud)
ctx->sta_avln->beacon.bmis.discover.present = false;
}
}
- bsu_ca_schedules__timer_event (ctx, ctx->sta_avln);
+ bsu_ca_schedules (ctx, ctx->sta_avln, 2);
bsu_avln_countdown_beacon_entries_apply_changes (ctx, ctx->sta_avln);
bsu_avln_countdown_beacon_entries (ctx, ctx->sta_avln);
bsu_aclf_track_powerline (ctx->aclf);
@@ -811,6 +837,15 @@ bsu_timer_event_process (void *ud)
bsu_aclf_shift_beacon_period_start_date (ctx->aclf);
else
bsu_aclf_ac_compute_beacon_period_start_date (ctx->aclf);
+ /* Shift schedules in use for next beacon period. */
+ uint i;
+ uint index_0 = ctx->ca_schedules_in_use[0];
+ for (i = 0; i < COUNT (ctx->ca_schedules_in_use) - 1; i++)
+ ctx->ca_schedules_in_use[i] = ctx->ca_schedules_in_use[i+1];
+ /* To avoid the schedule of index_0 to be requested it is put at
+ * the end of the array. This schedule will not be used for the next
+ * program. */
+ ctx->ca_schedules_in_use[i] = index_0;
bsu_reprogram_timer (
ctx, bsu_aclf_beacon_period_start_date_next (ctx->aclf));
bsu_stats_store (ctx);
@@ -886,8 +921,8 @@ bsu_init (bsu_aclf_t *aclf, mac_config_t *mac_config, phy_t *phy,
ctx->beacon_nb_recv[i] = 0;
for (i = 0; i < COUNT (ctx->beacon_nb_sent); i++)
ctx->beacon_nb_sent[i] = 0;
- ctx->ca_index = 1;
- ctx->ca_index_last_first = 0;
+ for (i = 0; i < COUNT (ctx->ca_schedules_in_use); i++)
+ ctx->ca_schedules_in_use[i] = CA_SCHEDULE_NB;
/* Trace. */
bsu_trace_init (ctx);
bsu_stats_init (ctx);
@@ -949,7 +984,7 @@ bsu_beacon_process__avln_tracked (bsu_t *ctx, bsu_beacon_t *beacon,
ctx->sta_avln->beacon.bmis.bpsto.present ?
ctx->sta_avln->beacon.bmis.bpsto.bpsto : 0);
/* Create the CA schedules. */
- bsu_ca_schedules__beacon_reception (ctx, ctx->sta_avln);
+ bsu_ca_schedules (ctx, ctx->sta_avln, 0);
}
BSU_TRACE (
BEACON_PROCESS, phy_date (), params->snid, beacon->vf.stei,
@@ -1221,14 +1256,6 @@ bsu_power_on (bsu_t *ctx, u8 snid)
ctx->nek_switch = 0;
dbg_assert (ctx->sta_avln->beacon.bmis.ps.nb != 0
|| ctx->sta_avln->beacon.bmis.nps.ns != 0);
- /* Create the first schedule. */
- ctx->ca_index_last_first =
- (ctx->ca_index_last_first + CA_SCHEDULE_NB / 2) %
- CA_SCHEDULE_NB;
- ca_schedule_t *schedule =
- ca_alloc_get_schedule (ctx->ca, ctx->ca_index_last_first);
- bsu_schedules_merge (ctx, &ctx->sta_avln->beacon, schedule, 0);
- bsu_ca_schedules_settings (ctx, ctx->sta_avln, schedule, 0);
arch_dsr_unlock ();
}
@@ -1244,7 +1271,9 @@ bsu_activate (bsu_t *ctx, bool status)
/* Program the first schedules in the CA. */
bsu_aclf_acl_frequency_detection (ctx->aclf);
bsu_aclf_ac_compute_beacon_period_start_date (ctx->aclf);
- bsu_ca_schedules__timer_event (ctx, ctx->sta_avln);
+ /* Prepare firsts schedules to the CA.*/
+ bsu_ca_schedules (ctx, ctx->sta_avln, 0);
+ /* Program the next wake up of the BSU. */
bsu_reprogram_timer (
ctx, bsu_aclf_beacon_period_start_date_next (ctx->aclf));
}