summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cesar/bsu/beacon/Module1
-rw-r--r--cesar/bsu/beacon/beacon.h229
-rw-r--r--cesar/bsu/beacon/defs.h159
-rw-r--r--cesar/bsu/beacon/inc/misc.h198
-rw-r--r--cesar/bsu/beacon/inc/region.h43
-rw-r--r--cesar/bsu/beacon/inc/schedule.h78
-rw-r--r--cesar/bsu/beacon/src/beacon.c972
-rw-r--r--cesar/bsu/beacon/test/utest/Makefile7
-rw-r--r--cesar/bsu/beacon/test/utest/src/beacon.c305
-rw-r--r--cesar/bsu/beacon/test/utest/src/test.c417
-rw-r--r--cesar/bsu/beacon/test/utest/test.h78
-rw-r--r--cesar/common/tests/tests4
12 files changed, 2491 insertions, 0 deletions
diff --git a/cesar/bsu/beacon/Module b/cesar/bsu/beacon/Module
new file mode 100644
index 0000000000..5bbb2cec31
--- /dev/null
+++ b/cesar/bsu/beacon/Module
@@ -0,0 +1 @@
+SOURCES:=beacon.c
diff --git a/cesar/bsu/beacon/beacon.h b/cesar/bsu/beacon/beacon.h
new file mode 100644
index 0000000000..82c1b5c2bb
--- /dev/null
+++ b/cesar/bsu/beacon/beacon.h
@@ -0,0 +1,229 @@
+#ifndef bsu_beacon_h
+#define bsu_beacon_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu/beacon/beacon.h
+ * \brief Beacon library
+ * \ingroup bsu_beacon
+ *
+ * Functions to read and write beacons.
+ */
+#include "bsu/beacon/defs.h"
+#include "bsu/beacon/inc/region.h"
+#include "bsu/beacon/inc/schedule.h"
+#include "bsu/beacon/inc/misc.h"
+#include "mac/common/pb.h"
+#include "mac/pbproc/pbproc.h"
+
+/** Number of schedules information kept from the beacon. */
+#define BSU_BEACON_SCHEDULES_MAX 3
+
+enum bsu_beacon_type_t
+{
+ BSU_BEACON_TYPE_CENTRAL,
+ BSU_BEACON_TYPE_DISCOVER,
+ BSU_BEACON_TYPE_PROXY,
+ BSU_BEACON_TYPE_NB
+};
+typedef enum bsu_beacon_type_t bsu_beacon_type_t;
+
+enum bsu_beacon_region_type_t
+{
+ BSU_BEACON_REGION_RESERVED,
+ BSU_BEACON_REGION_SHARED_CSMA,
+ BSU_BEACON_REGION_LOCAL_CSMA,
+ BSU_BEACON_REGION_STAYOUT,
+ BSU_BEACON_REGION_PROTECTED,
+ BSU_BEACON_REGION_BEACON,
+ BSU_BEACON_REGION_NB
+};
+typedef enum bsu_beacon_region_type_t bsu_beacon_region_type_t;
+
+struct bsu_beacon_variant_fields_t
+{
+ /** Network Identifier. */
+ u64 nid;
+ BITFIELDS_WORD
+ (
+ /** Hybrid mode. */
+ u32 hm:8;,
+ /** Non-Coordinating Networks Reported. */
+ u32 ncnr:8;,
+ /** Network Power Saving Mode. */
+ u32 npsm:8;,
+ /** Number of beacon slots. */
+ u32 numslots:8;
+ );
+ BITFIELDS_WORD
+ (
+ /** Beacon slot usage. */
+ u32 slotusage:8;,
+ /** Slot identifier. */
+ u32 slotid:8;,
+ /** AC Line Synchronization Status. */
+ u32 aclsss:8;,
+ /** Handover in Progress. */
+ u32 hoip:8;
+ );
+ BITFIELDS_WORD
+ (
+ /** RTS Broadcast Flag. */
+ u32 rtsbf:8;,
+ /** Network Mode. */
+ u32 nm:8;,
+ /** CCo Capability. */
+ u32 ccocap:8;,
+ /** Reserved. */
+ u32 rsvd:8;
+ );
+};
+typedef struct bsu_beacon_variant_fields_t bsu_beacon_variant_fields_t;
+
+/** Beacon Management information. */
+struct bsu_beacon_bmi_t
+{
+ /** Number of beacon entries. */
+ u32 nbe;
+ /** Region beacon entry. */
+ bsu_beacon_bmi_region_t region;
+ /** Persistent schedule. */
+ bsu_beacon_bmi_persistent_schedule_t ps;
+ /** Non persistent schedule. */
+ bsu_beacon_bmi_non_persistent_schedule_t nps;
+ /** Discover bentry. */
+ bsu_beacon_bmi_discover_t discover;
+ /** Beacon period start time offset. */
+ bsu_beacon_bmi_bpsto_t bpsto;
+ /** Discover info bentry. */
+ bsu_beacon_bmi_discover_info_t discover_info;
+ /** Encryption key change. */
+ bsu_beacon_bmi_eks_t eks;
+ /** CCo Handover. */
+ bsu_beacon_bmi_handover_t handover;
+ /** Beacon relocation. */
+ bsu_beacon_bmi_relocation_t relocation;
+ /** AC Line synchronization countdown. */
+ bsu_beacon_bmi_aclsc_t aclsc;
+ /** Change number of slots. */
+ bsu_beacon_bmi_change_num_slot_t cns;
+ /** Change hybrid mode. */
+ bsu_beacon_bmi_change_hybrid_mode_t change_hm;
+ /** Change SNID. */
+ bsu_beacon_bmi_change_snid_t change_snid;
+ /** Mac Address (present). */
+ bsu_beacon_bmi_mac_address_t mac_address_present;
+};
+typedef struct bsu_beacon_bmi_t bsu_beacon_bmi_t;
+
+/** beacon computed parameters. */
+struct bsu_beacon_params_t
+{
+ /** Beacon period start date. */
+ u32 bpsd_date [4];
+ /** Frequency error. */
+ u32 frequency_error;
+ /** Tick offset, difference between the NTB and PHY Date clock. */
+ u32 tick_offset;
+};
+typedef struct bsu_beacon_params_t bsu_beacon_params_t;
+
+/** beacon description structure. */
+struct bsu_beacon_t
+{
+ /** Data are valid for the beacon period starting at this date. */
+ u32 beacon_period_start_date;
+ /** Variant fields. */
+ bsu_beacon_variant_fields_t vf;
+ /** Beacon Management Information. */
+ bsu_beacon_bmi_t bmis;
+ /** Beacon parameters. */
+ bsu_beacon_params_t bsu_params;
+};
+typedef struct bsu_beacon_t bsu_beacon_t;
+
+/** Schedule description for the AVLN. */
+struct bsu_beacon_schedules_t
+{
+ /** Hybrid mode. */
+ mac_coexistence_mode_t hm[BSU_BEACON_SCHEDULES_MAX];
+ /** SNID. */
+ u16 snid[BSU_BEACON_SCHEDULES_MAX];
+ /** NEK switch. */
+ uint nek_switch[BSU_BEACON_SCHEDULES_MAX];
+ /** Persistent schedule. */
+ bsu_beacon_bmi_persistent_schedule_t ps;
+ /** Non persistent schedule. */
+ bsu_beacon_bmi_non_persistent_schedule_t nps;
+ /** Beacon period start time offset. */
+ bsu_beacon_bmi_bpsto_t bpsto;
+};
+typedef struct bsu_beacon_schedules_t bsu_beacon_schedules_t;
+
+/** AVLN data. */
+struct bsu_beacon_avln_t
+{
+ /** NID. */
+ u64 nid;
+ /** SNID. */
+ u16 snid;
+ /** CCo's TEI. */
+ u8 tei;
+ /** Schedule description. */
+ bsu_beacon_schedules_t schedules;
+};
+typedef struct bsu_beacon_avln_t bsu_beacon_avln_t;
+
+BEGIN_DECLS
+
+/**
+ * Write a beacon to be sent on the medium
+ * \param beacon the beacon containing the data to store.
+ * \param type the beacon type to send.
+ * \param mac_config the mac config object.
+ * \param params the TX beacon params containing the BPSTO and BTO.
+ * \return a beacon ready to send over the medium.
+ */
+pb_beacon_t*
+bsu_beacon_write (bsu_beacon_t *beacon, bsu_beacon_type_t type,
+ mac_config_t *mac_config,
+ pbproc_tx_beacon_params_t *params);
+
+/**
+ * Read the necessary data from the beacon to compute the Schedules for
+ * the CA.
+ * \param beacon the beacon received from the medium.
+ * \param schedules schedules structure to store the data.
+ */
+void
+bsu_beacon_read_schedules (pb_beacon_t *beacon,
+ bsu_beacon_schedules_t *schedules);
+
+/**
+ * Read the whole beacon and store the data into the beacon structure.
+ * \param pbbeacon the beacon received from the medium.
+ * \param beacon the structure to store the data.
+ * \param type the beacon type.
+ * \param tei the Source TEI present in the beacon.
+ * \param mac_address the Source MAC Address if present in beacon.
+ * \return true on success false otherwise.
+ */
+bool
+bsu_beacon_read (pb_beacon_t *pbbeacon, bsu_beacon_t *beacon,
+ bsu_beacon_type_t *type, u8 *tei, mac_t *mac_address);
+
+/**
+ * Decrease the countdown values of the beacon.
+ * \param beacon the beacon structure to decrease the values.
+ */
+void
+bsu_beacon_countdown (bsu_beacon_t *beacon);
+
+END_DECLS
+
+#endif /* bsu_beacon_h */
diff --git a/cesar/bsu/beacon/defs.h b/cesar/bsu/beacon/defs.h
new file mode 100644
index 0000000000..93a1c22e74
--- /dev/null
+++ b/cesar/bsu/beacon/defs.h
@@ -0,0 +1,159 @@
+#ifndef bsu_beacon_inc_bmi_defs_h
+#define bsu_beacon_inc_bmi_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu_beacon/inc/bmi_defs.h
+ * \brief Beacon entries definition.
+ * \ingroup bsu_beacon
+ */
+
+/** Non coordinated mode. */
+enum bsu_beacon_non_coordinated_mode_t
+{
+ BSU_BEACON_NON_COORDINATED_NETWORK,
+ BSU_BEACON_NON_COORDINATED_NETWORK_REPORTED,
+ BSU_BEACON_NON_COORDINATED_MAX
+};
+typedef enum bsu_beacon_non_coordinated_mode_t
+bsu_beacon_non_coordinated_mode_t;
+
+/** Power Saving mode. */
+enum bsu_beacon_npsm_t
+{
+ BSU_BEACON_NPSM_NOT_ACTIVE,
+ BSU_BEACON_NPSM_ACTIVE,
+ BSU_BEACON_NPSM_MAX
+};
+typedef enum bsu_beacon_npsm_t bsu_beacon_npsm_t;
+
+/** Handover in progress. */
+enum bsu_beacon_hoip_t
+{
+ BSU_BEACON_HOIP_FALSE,
+ BSU_BEACON_HOIP_TRUE,
+ BSU_BEACON_HOIP_MAX
+};
+typedef enum bsu_beacon_hoip_t bsu_beacon_hoip_t;
+
+/** Network mode. */
+enum bsu_beacon_nm_t
+{
+ BSU_BEACON_NM_UNCOORDINATED,
+ BSU_BEACON_NM_COORDINATED,
+ BSU_BEACON_NM_CSMA_ONLY,
+ BSU_BEACON_NM_NB
+};
+typedef enum bsu_beacon_nm_t bsu_beacon_nm_t;
+
+/** CCo Cap. */
+enum bsu_beacon_cco_cap_t
+{
+ BSU_BEACON_CCO_LEVEL0,
+ BSU_BEACON_CCO_LEVEL1,
+ BSU_BEACON_CCO_LEVEL2,
+ BSU_BEACON_CCO_LEVEL3
+};
+typedef enum bsu_beacon_cco_cap_t bsu_beacon_cco_cap_t;
+
+enum bsu_beacon_eks_kbc_t
+{
+ BSU_BEACON_EKS_KBC_NEK,
+ BSU_BEACON_EKS_KBC_NMK,
+ BSU_BEACON_EKS_KBC_NB
+};
+typedef enum bsu_beacon_eks_kbc_t bsu_beacon_eks_kbc_t;
+
+enum bsu_beacon_entry_header_t
+{
+ BSU_BEACON_ENTRY_HEADER_NON_PERSISTENT_SCHEDULE,
+ BSU_BEACON_ENTRY_HEADER_PERSISTENT_SCHEDULE,
+ BSU_BEACON_ENTRY_HEADER_REGIONS,
+ BSU_BEACON_ENTRY_HEADER_MAC_ADDRESS,
+ BSU_BEACON_ENTRY_HEADER_DISCOVER,
+ BSU_BEACON_ENTRY_HEADER_DISCOVERED_INFO,
+ BSU_BEACON_ENTRY_HEADER_BEACON_PERIOD_START_TIME_OFFSET,
+ BSU_BEACON_ENTRY_HEADER_ENCRYPTION_KEY_CHANGE,
+ BSU_BEACON_ENTRY_HEADER_CCO_HANDOVER,
+ BSU_BEACON_ENTRY_HEADER_BEACON_RELOCATION,
+ BSU_BEACON_ENTRY_HEADER_AC_LINE_SYNC_COUNTDOWN,
+ BSU_BEACON_ENTRY_HEADER_CHANGE_NUMSLOTS,
+ BSU_BEACON_ENTRY_HEADER_CHANGE_HM,
+ BSU_BEACON_ENTRY_HEADER_CHANGE_SNID,
+ BSU_BEACON_ENTRY_HEADER_RSVD_MIN = 0x0E,
+ BSU_BEACON_ENTRY_HEADER_RSVD_MAX = 0xFE,
+ BSU_BEACON_ENTRY_HEADER_VENDOR=0xFF
+};
+typedef enum bsu_beacon_entry_header_t bsu_beacon_entry_header_t;
+
+#define BSU_BEACON_ENTRY_IS_BENTRY(val) \
+ (((val) < BSU_BEACON_ENTRY_HEADER_RSVD_MIN) \
+ || ((val) == BSU_BEACON_ENTRY_HEADER_VENDOR))
+
+/** Bentry header size. */
+#define BSU_BEACON_ENTRY_SIZE_HEADER 2
+
+/** Mac Address bentry size. */
+#define BSU_BEACON_ENTRY_SIZE_MAC_ADDRESS 6
+
+/** Discover Bentry. */
+#define BSU_BEACON_ENTRY_SIZE_DISCOVER 1
+
+/** Discover Info Bentry. */
+#define BSU_BEACON_ENTRY_SIZE_DISCOVER_INFO 4
+
+/** Beacon Period Start Time Offset. */
+#define BSU_BEACON_ENTRY_SIZE_BPSTO 3
+
+/** Encryption key change. */
+#define BSU_BEACON_ENTRY_SIZE_EKC 2
+
+/** Handover. */
+#define BSU_BEACON_ENTRY_SIZE_HOIP 2
+
+/** Beacon Relocation. */
+#define BSU_BEACON_ENTRY_SIZE_RLO 4
+
+/** AC Line synchronisation. */
+#define BSU_BEACON_ENTRY_SIZE_ACL 2
+
+/** Change Num Slots. */
+#define BSU_BEACON_ENTRY_SIZE_CHANGE_NUMSLOTS 2
+
+/** Change hybrid mode. */
+#define BSU_BEACON_ENTRY_SIZE_CHANGE_HM 1
+
+/** Change SNID. */
+#define BSU_BEACON_ENTRY_SIZE_CHANGE_SNID 1
+
+/* Variable ones. */
+
+/** Define the size in bytes of a SAI with start time. */
+#define BSU_BEACON_ENTRY_SIZE_SCHED_SAI_STPF 4
+
+/** Define the size in bytes of a SAI without start time. */
+#define BSU_BEACON_ENTRY_SIZE_SCHED_SAI_NSTPF 3
+
+/** Define the macro to compute a non persistent schedule bentry. */
+#define BSU_BEACON_ENTRY_SIZE_NON_PERSISTENT_SCHED(sai, nsai) \
+ (1 + (sai * BSU_BEACON_ENTRY_SIZE_SCHED_SAI_STPF) \
+ + (nsai * BSU_BEACON_ENTRY_SIZE_SCHED_SAI_NSTPF))
+
+/** Define the macro to compute a persistent schedule bentry. */
+#define BSU_BEACON_ENTRY_SIZE_PERSISTENT_SCHED(sai, nsai) \
+ (2 + (sai * BSU_BEACON_ENTRY_SIZE_SCHED_SAI_STPF) \
+ + (nsai * BSU_BEACON_ENTRY_SIZE_SCHED_SAI_NSTPF))
+
+/** Define the size in bytes of a region definition. */
+#define BSU_BEACON_ENTRY_SIZE_REGION_DESC 2
+
+/** Define the Macro to compute a region bentry. */
+#define BSU_BEACON_ENTRY_SIZE_REGION(nr) \
+ (1 + BSU_BEACON_ENTRY_SIZE_REGION_DESC * nr)
+
+#endif /* bsu_beacon_inc_bmi_defs_h */
diff --git a/cesar/bsu/beacon/inc/misc.h b/cesar/bsu/beacon/inc/misc.h
new file mode 100644
index 0000000000..b968ac85e2
--- /dev/null
+++ b/cesar/bsu/beacon/inc/misc.h
@@ -0,0 +1,198 @@
+#ifndef bsu_beacon_inc_misc_h
+#define bsu_beacon_inc_misc_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu_beacon/inc/misc.h
+ * \brief Standard bsu_beacon entries.
+ * \ingroup bsu_beacon
+ *
+ * \warn All structures are aligned on 32 bits.
+ */
+
+/** Discover bentry. */
+struct bsu_beacon_bmi_discover_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** TEI. */
+ u32 tei:8;,
+ /** Reserved. */
+ u32 rsvd:16;
+ );
+};
+typedef struct bsu_beacon_bmi_discover_t bsu_beacon_bmi_discover_t;
+
+/** Discover infor bentry. */
+struct bsu_beacon_bmi_discover_info_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Reserved. */
+ u32 rsvd:24;,
+ /** Discover info data in a word. */
+ u32 info_data;
+ );
+};
+typedef struct bsu_beacon_bmi_discover_info_t bsu_beacon_bmi_discover_info_t;
+
+/** Beacon period start time offset. */
+struct bsu_beacon_bmi_bpsto_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Beacon period start time offset. */
+ u32 bpsto:24;
+ );
+};
+typedef struct bsu_beacon_bmi_bpsto_t bsu_beacon_bmi_bpsto_t;
+
+/** Encryption key change. */
+struct bsu_beacon_bmi_eks_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Key change countdown. */
+ u32 kccd:8;,
+ /** Key being changed. */
+ u32 kbc:8;,
+ /** New EKS. */
+ u32 new_eks:8;
+ );
+};
+typedef struct bsu_beacon_bmi_eks_t bsu_beacon_bmi_eks_t;
+
+/** CCo Handover. */
+struct bsu_beacon_bmi_handover_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Handover countdown. */
+ u32 hcd:8;,
+ /** New CCo TEI. */
+ u32 tei:8;,
+ /** Reserved. */
+ u32 reserved:8;
+ );
+};
+typedef struct bsu_beacon_bmi_handover_t bsu_beacon_bmi_handover_t;
+
+/** Relocation bentry. */
+struct bsu_beacon_bmi_relocation_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:4;,
+ /** Countdown. */
+ u32 rcd:6;,
+ /** Relocation type. */
+ u32 rlt:1;,
+ /** Leaving group flag. */
+ u32 lgf:1;,
+ /** Relocation offset. */
+ u32 rlo:17;,
+ /** Relocation slot id. */
+ u32 rlslotid:3;
+ );
+};
+typedef struct bsu_beacon_bmi_relocation_t bsu_beacon_bmi_relocation_t;
+
+/** AC Line synchronization countdown. */
+struct bsu_beacon_bmi_aclsc_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Countdown. */
+ u32 countdown:6;,
+ /** Reserved. */
+ u32 rsvd0:2;,
+ /** Reason code. */
+ u32 reason_code:2;,
+ /** Reserved. */
+ u32 rsvd1:14;
+ );
+};
+typedef struct bsu_beacon_bmi_aclsc_t bsu_beacon_bmi_aclsc_t;
+
+/** Change number of slots. */
+struct bsu_beacon_bmi_change_num_slot_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** NumSlots Change Countdown. */
+ u32 nsccd:6;,
+ /** Reserved. */
+ u32 rsvd0:2;,
+ /** New NumSlot value. */
+ u32 newnumslot:3;,
+ /** Reserved. */
+ u32 rsvd1:13;
+ );
+};
+typedef struct bsu_beacon_bmi_change_num_slot_t
+bsu_beacon_bmi_change_num_slot_t;
+
+/** Change hybrid mode. */
+struct bsu_beacon_bmi_change_hybrid_mode_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Hybrid mode change countdown. */
+ u32 hmccd:6;,
+ /** New Hybrid mode. */
+ u32 newhm:2;,
+ /** Reserved. */
+ u32 rsvd:16;
+ );
+};
+typedef struct bsu_beacon_bmi_change_hybrid_mode_t
+bsu_beacon_bmi_change_hybrid_mode_t;
+
+/** Change SNID. */
+struct bsu_beacon_bmi_change_snid_t
+{
+ BITFIELDS_WORD
+ (
+ /** Present. */
+ u32 present:8;,
+ /** Snid change countdown. */
+ u32 snidccd:4;,
+ /** New SNID. */
+ u32 new_snid:4;,
+ /** reserved. */
+ u32 rsvd:16;
+ );
+};
+typedef struct bsu_beacon_bmi_change_snid_t bsu_beacon_bmi_change_snid_t;
+
+/** Mac Address. */
+struct bsu_beacon_bmi_mac_address_t
+{
+ /** Present. */
+ u32 present;
+};
+typedef struct bsu_beacon_bmi_mac_address_t bsu_beacon_bmi_mac_address_t;
+
+#endif /* bsu_beacon_inc_misc_h */
diff --git a/cesar/bsu/beacon/inc/region.h b/cesar/bsu/beacon/inc/region.h
new file mode 100644
index 0000000000..0e7cbd66b7
--- /dev/null
+++ b/cesar/bsu/beacon/inc/region.h
@@ -0,0 +1,43 @@
+#ifndef bsu_beacon_inc_region_h
+#define bsu_beacon_inc_region_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu_beacon/inc/region.h
+ * \brief Beacon entry exchange data description.
+ * \ingroup bsu_beacon
+ */
+
+/** Number of maximum region available. */
+#define BSU_BEACON_BMI_REGION_NAX 10
+
+struct bsu_beacon_bmi_region_desc_t
+{
+ BITFIELDS_WORD
+ (
+ /** Region type. */
+ u32 rt:4;,
+ /** Region end time us. */
+ u32 end_time_atu:12;,
+ /** Reserved. */
+ u32 rsvd:16;
+ );
+};
+typedef struct bsu_beacon_bmi_region_desc_t bsu_beacon_bmi_region_desc_t;
+
+/** Region bsu_beacon entry. */
+struct bsu_beacon_bmi_region_t
+{
+ /** Number of regions. */
+ uint nb;
+ /** Array of number of regions. */
+ bsu_beacon_bmi_region_desc_t region[BSU_BEACON_BMI_REGION_NAX];
+};
+typedef struct bsu_beacon_bmi_region_t bsu_beacon_bmi_region_t;
+
+#endif /* bsu_beacon_inc_region_h */
diff --git a/cesar/bsu/beacon/inc/schedule.h b/cesar/bsu/beacon/inc/schedule.h
new file mode 100644
index 0000000000..479717d7a4
--- /dev/null
+++ b/cesar/bsu/beacon/inc/schedule.h
@@ -0,0 +1,78 @@
+#ifndef bsu_beacon_inc_schedule_h
+#define bsu_beacon_inc_schedule_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu_beacon/inc/schedule.h
+ * \brief Schedule bsu_beacon entry description.
+ * \ingroup bsu_beacon
+ */
+
+/** Maximum number of Schedule Allocation Unit. */
+#define BSU_BEACON_BMIS_SCHEDULES_SAI_MAX 5
+
+/** Maximum number of Persistent bsu_beacon entries. */
+#define BSU_BEACON_BMI_PERSISTENT_SCHEDULE_MAX 2
+
+struct bsu_beacon_sai_t
+{
+ BITFIELDS_WORD
+ (
+ /** Start Time Present Flag. */
+ u32 stpf:1;,
+ /** GLID. */
+ u32 glid:7;,
+ /** Start time. */
+ u32 start_time_atu:12;,
+ /** End time. */
+ u32 end_time_atu:12;
+ );
+};
+typedef struct bsu_beacon_sai_t bsu_beacon_sai_t;
+
+struct bsu_beacon_bmi_persistent_schedule_desc_t
+{
+ BITFIELDS_WORD
+ (
+ /** Previous countdown. */
+ u32 pscd:8;,
+ /** Current schedule countdown. */
+ u32 cscd:8;,
+ /** Number of session. */
+ u32 ns:8;,
+ /** Reserved. */
+ u32 rsvd:8;
+ );
+ /** Schedules. */
+ bsu_beacon_sai_t sais[BSU_BEACON_BMIS_SCHEDULES_SAI_MAX];
+};
+typedef struct bsu_beacon_bmi_persistent_schedule_desc_t
+bsu_beacon_bmi_persistent_schedule_desc_t;
+
+struct bsu_beacon_bmi_persistent_schedule_t
+{
+ /** Number of persistent schedule data. */
+ uint nb;
+ /** Persistent schedule descriptions. */
+ bsu_beacon_bmi_persistent_schedule_desc_t
+ ps[BSU_BEACON_BMI_PERSISTENT_SCHEDULE_MAX];
+};
+typedef struct bsu_beacon_bmi_persistent_schedule_t
+bsu_beacon_bmi_persistent_schedule_t;
+
+struct bsu_beacon_bmi_non_persistent_schedule_t
+{
+ /** Number of session. */
+ uint ns;
+ /** Schedules. */
+ bsu_beacon_sai_t sais[BSU_BEACON_BMIS_SCHEDULES_SAI_MAX];
+};
+typedef struct bsu_beacon_bmi_non_persistent_schedule_t
+bsu_beacon_bmi_non_persistent_schedule_t;
+
+#endif /* bsu_beacon_inc_schedule_h */
diff --git a/cesar/bsu/beacon/src/beacon.c b/cesar/bsu/beacon/src/beacon.c
new file mode 100644
index 0000000000..1192c81282
--- /dev/null
+++ b/cesar/bsu/beacon/src/beacon.c
@@ -0,0 +1,972 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu/src/beacon.c
+ * \brief BSU bsu_beacon functions.
+ * \ingroup bsu
+ *
+ * Functions to read and write bsu_beacons.
+ */
+#include "common/std.h"
+#include "lib/bitstream.h"
+#include "bsu/beacon/beacon.h"
+#include "cp/defs.h"
+
+/** Define the bsu_beacon size in the data part of the block. The first part
+ * of the NID is stored in the block descriptor. */
+#define BSU_BEACON_SIZE 128
+
+/**
+ * Write the beacon variant fields.
+ * \param phy_beacon the beacon bloc.
+ * \param stream the bitstream context.
+ * \param mac_config the mac config object.
+ * \param beacon the data to use to write the beacon.
+ * \param type the beacon type.
+ */
+static void
+bsu_beacon_write_variant_fields (pb_beacon_t *phy_beacon,
+ bitstream_t *stream,
+ mac_config_t *mac_config,
+ bsu_beacon_t *beacon,
+ bsu_beacon_type_t type)
+{
+ phy_beacon->first_data_word = beacon->vf.nid;
+ bitstream_write (stream, beacon->vf.nid >> 32, 22);
+ bitstream_write (stream, beacon->vf.hm, 2);
+ bitstream_write (stream, mac_config->tei, 8);
+ bitstream_write (stream, type, 3);
+ bitstream_write (stream, beacon->vf.ncnr, 1);
+ bitstream_write (stream, beacon->vf.npsm, 1);
+ bitstream_write (stream, beacon->vf.numslots, 3);
+ bitstream_write (stream, beacon->vf.slotusage, 8);
+ bitstream_write (stream, beacon->vf.slotid, 3);
+ bitstream_write (stream, beacon->vf.aclsss, 3);
+ bitstream_write (stream, beacon->vf.hoip, 1);
+ bitstream_write (stream, beacon->vf.rtsbf, 1);
+ bitstream_write (stream, beacon->vf.nm, 2);
+ bitstream_write (stream, beacon->vf.ccocap, 2);
+ bitstream_write (stream, 0, 4);
+}
+
+/**
+ * Write the regions entries in the beacon.
+ * \param stream the bitstream context.
+ * \param region the region bentry.
+ */
+static void
+bsu_beacon_write_bmi_region (bitstream_t *stream,
+ bsu_beacon_bmi_region_t *region)
+{
+ uint nb;
+ dbg_assert (region->nb);
+ /* Store region header value. */
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_REGIONS, 8);
+ uint size = BSU_BEACON_ENTRY_SIZE_REGION (region->nb);
+ bitstream_write (stream, size, 8);
+ bitstream_write (stream, region->nb, 6);
+ bitstream_write (stream, 0, 2);
+ for (nb = 0; nb < region->nb; nb++)
+ {
+ bitstream_write (stream, region->region[nb].rt, 4);
+ bitstream_write (stream, region->region[nb].end_time_atu, 12);
+ }
+}
+
+/**
+ * Write SAI in the beacon.
+ * \param stream the bitstream context.
+ * \param sai the data to use to write the beacon.
+ */
+static void
+bsu_beacon_write_bmi_schedule_sai (bitstream_t *stream,
+ bsu_beacon_sai_t *sai)
+{
+ bitstream_write (stream, sai->stpf, 1);
+ bitstream_write (stream, sai->glid, 7);
+ if (sai->stpf)
+ bitstream_write (stream, sai->start_time_atu, 12);
+ bitstream_write (stream, sai->end_time_atu, 12);
+}
+
+/**
+ * Write Non persistent schedule in the beacon.
+ * \param stream the bitstream context.
+ * \param nps The uncompressed non persistent bsu_beacon entries to store.
+ * \param data the beginning of the beacon.
+ */
+static void
+bsu_beacon_write_bmi_non_persistent (bitstream_t *stream,
+ bsu_beacon_bmi_non_persistent_schedule_t *nps,
+ u8 *data)
+{
+ if (nps->ns)
+ {
+ u32 offset;
+ int nbsai = 0;
+ int nbnsai = 0;
+ uint ns = 0;
+ bitstream_write (stream,
+ BSU_BEACON_ENTRY_HEADER_NON_PERSISTENT_SCHEDULE, 8);
+ offset = bitstream_written_bits (stream);
+ /* Skip the length, it will be stored at the end. */
+ bitstream_write (stream, 0, 8);
+ /* Store the number of session. */
+ bitstream_write (stream, nps->ns, 6);
+ bitstream_write (stream, 0, 2);
+ /* Store the session. */
+ for (ns = 0; ns < nps->ns; ns++)
+ {
+ if (nps->sais[ns].stpf)
+ nbsai++;
+ else
+ nbnsai++;
+ bsu_beacon_write_bmi_schedule_sai (stream, &nps->sais[ns]);
+ }
+ /* Store the length. */
+ bitstream_direct_write (data, offset,
+ BSU_BEACON_ENTRY_SIZE_NON_PERSISTENT_SCHED (nbsai, nbnsai), 8);
+ }
+}
+
+/**
+ * Write a unique Persistent schedule in the beacon.
+ * \param stream the bitstream context.
+ * \param ps the persistent schedule beacon entry to store.
+ * \param data the beginning of the beacon.
+ */
+static void
+bsu_beacon_write_bmi_persistent__store (bitstream_t *stream,
+ bsu_beacon_bmi_persistent_schedule_desc_t *ps,
+ u8 *data)
+{
+ u32 offset;
+ int nbsai = 0;
+ int nbnsai = 0;
+ int ns = 0;
+ bitstream_write (stream,
+ BSU_BEACON_ENTRY_HEADER_PERSISTENT_SCHEDULE, 8);
+ offset = bitstream_written_bits (stream);
+ /* Skip the length, it will be stored at the end. */
+ bitstream_write (stream, 0, 8);
+ /* Store the countdowns. */
+ bitstream_write (stream, ps->pscd, 3);
+ bitstream_write (stream, ps->cscd, 3);
+ bitstream_write (stream, 0, 2);
+ bitstream_write (stream, ps->ns, 6);
+ bitstream_write (stream, 0, 2);
+ for (ns = 0; ns < ps->ns; ns++)
+ {
+ if (ps->sais[ns].stpf)
+ nbsai++;
+ else
+ nbnsai++;
+ bsu_beacon_write_bmi_schedule_sai (stream, &ps->sais[ns]);
+ }
+ /* Store the length. */
+ bitstream_direct_write (
+ data, offset, BSU_BEACON_ENTRY_SIZE_PERSISTENT_SCHED (nbsai, nbnsai),
+ 8);
+}
+
+/**
+ * Write Persistent schedule in the beacon.
+ * \param stream the bitstream context.
+ * \param ps The uncompressed persistent beacon entries to store.
+ * \param data the beginning of the beacon.
+ */
+static void
+bsu_beacon_write_bmi_persistent (bitstream_t *stream,
+ bsu_beacon_bmi_persistent_schedule_t *ps,
+ u8 *data)
+{
+ uint nb;
+ if (ps->nb)
+ for (nb = 0; nb < ps->nb; nb++)
+ bsu_beacon_write_bmi_persistent__store (stream, &ps->ps[nb],
+ data);
+}
+
+/**
+ * Write the discover beacon entry.
+ * \param stream the bitstream context.
+ * \param discover the discover beacon entry to write.
+ */
+static void
+bsu_beacon_write_bmi_discover (bitstream_t *stream,
+ bsu_beacon_bmi_discover_t *discover)
+{
+ if (discover->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_DISCOVER, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_DISCOVER, 8);
+ bitstream_write (stream, discover->tei, 8);
+ }
+}
+
+/**
+ * Write the beacon period start time offset bentry.
+ * \param stream the bitstream context.
+ * \param bpsto the beacon period start time offset beacon entry.
+ * \return the offset in octets of the data position in the beacon.
+ */
+static u32
+bsu_beacon_write_bmi_bpsto (bitstream_t *stream,
+ bsu_beacon_bmi_bpsto_t *bpsto)
+{
+ u32 offset = 0;
+ if (bpsto->present)
+ {
+ bitstream_write (stream,
+ BSU_BEACON_ENTRY_HEADER_BEACON_PERIOD_START_TIME_OFFSET,
+ 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_BPSTO, 8);
+ offset = bitstream_written_bits (stream) / 8;
+ bitstream_write (stream, 0, BSU_BEACON_ENTRY_SIZE_BPSTO * 8);
+ }
+ return offset;
+}
+
+/**
+ * Write the discover info beacon entry.
+ * \param beacon the data to use to write the beacon.
+ * \param discover_info the beacon entry to store.
+ */
+static void
+bsu_beacon_write_bmi_discover_info (
+ bitstream_t *stream, bsu_beacon_bmi_discover_info_t *discover_info)
+{
+ if (discover_info->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_DISCOVERED_INFO, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_DISCOVER_INFO, 8);
+ bitstream_write (stream, discover_info->info_data, 32);
+ }
+}
+
+/**
+ * Write the encryption key change beacon entry.
+ * \param stream the bitstream context.
+ * \param eks the encryption key change beacon entry.
+ */
+static void
+bsu_beacon_write_bmi_eks (bitstream_t *stream, bsu_beacon_bmi_eks_t *eks)
+{
+ if (eks->present)
+ {
+ bitstream_write (stream,
+ BSU_BEACON_ENTRY_HEADER_ENCRYPTION_KEY_CHANGE,
+ 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_EKC, 8);
+ bitstream_write (stream, eks->kccd, 6);
+ bitstream_write (stream, eks->kbc, 1);
+ bitstream_write (stream, 0, 1);
+ bitstream_write (stream, eks->new_eks, 4);
+ bitstream_write (stream, 0, 4);
+ }
+}
+
+/**
+ * Write the handover beacon entry.
+ * \param stream the bitstream context.
+ * \param handover the beacon entry to write.
+ */
+static void
+bsu_beacon_write_bmi_handover (bitstream_t *stream,
+ bsu_beacon_bmi_handover_t *handover)
+{
+ if (handover->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_CCO_HANDOVER, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_HOIP, 8);
+ bitstream_write (stream, handover->hcd, 6);
+ bitstream_write (stream, 0, 2);
+ bitstream_write (stream, handover->tei, 8);
+ }
+}
+
+/**
+ * Write the bsu_beacon relocation entry.
+ * \param stream the bitstream context.
+ * \param relocation the beacon relocation entry data to write.
+ */
+static void
+bsu_beacon_write_bmi_relocation (bitstream_t *stream,
+ bsu_beacon_bmi_relocation_t *relocation)
+{
+ if (relocation->present)
+ {
+ bitstream_write (stream,
+ BSU_BEACON_ENTRY_HEADER_BEACON_RELOCATION,
+ 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_RLO, 8);
+ bitstream_write (stream, relocation->rcd, 6);
+ bitstream_write (stream, relocation->rlt, 1);
+ bitstream_write (stream, relocation->lgf, 1);
+ bitstream_write (stream, relocation->rlo, 17);
+ bitstream_write (stream, relocation->rlslotid, 3);
+ bitstream_write (stream, 0, 4);
+ }
+}
+
+/**
+ * Write ACLSC beacon entry.
+ * \param stream the bitstream context.
+ * \param aclsc the beacon entry to store in the beacon.
+ */
+static void
+bsu_beacon_write_bmi_aclsc (bitstream_t *stream,
+ bsu_beacon_bmi_aclsc_t *aclsc)
+{
+ if (aclsc->present)
+ {
+ bitstream_write (stream,
+ BSU_BEACON_ENTRY_HEADER_AC_LINE_SYNC_COUNTDOWN,
+ 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_ACL, 8);
+ bitstream_write (stream, aclsc->countdown, 6);
+ bitstream_write (stream, 0, 2);
+ bitstream_write (stream, aclsc->reason_code, 2);
+ bitstream_write (stream, 0, 6);
+ }
+}
+
+/**
+ * Write the change number of slots beacon entry.
+ * \param stream the bitstream context.
+ * \param cns the beacon entry to store in the beacon.
+ */
+static void
+bsu_beacon_write_bmi_change_num_slot (bitstream_t *stream,
+ bsu_beacon_bmi_change_num_slot_t *cns)
+{
+ if (cns->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_CHANGE_NUMSLOTS, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_CHANGE_NUMSLOTS, 8);
+ bitstream_write (stream, cns->nsccd, 6);
+ bitstream_write (stream, 0, 2);
+ bitstream_write (stream, cns->newnumslot, 3);
+ bitstream_write (stream, 0, 5);
+ }
+}
+
+/**
+ * Write the change hybrid mode beacon entry.
+ * \param stream the bitstream context.
+ * \param hm the beacon entry to store in the beacon.
+ */
+static void
+bsu_beacon_write_bmi_change_hm (bitstream_t *stream,
+ bsu_beacon_bmi_change_hybrid_mode_t *hm)
+{
+ if (hm->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_CHANGE_HM, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_CHANGE_HM, 8);
+ bitstream_write (stream, hm->hmccd, 6);
+ bitstream_write (stream, hm->newhm, 2);
+ }
+}
+
+/**
+ * Write the change snid beacon entry.
+ * \param stream the bitstream context.
+ * \param snid the beacon entry to store in the beacon.
+ */
+static void
+bsu_beacon_write_bmi_change_snid (bitstream_t *stream,
+ bsu_beacon_bmi_change_snid_t *snid)
+{
+ if (snid->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_CHANGE_SNID, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_CHANGE_SNID, 8);
+ bitstream_write (stream, snid->snidccd, 4);
+ bitstream_write (stream, snid->new_snid, 4);
+ }
+}
+
+/**
+ * Write the Mac address beacon entry.
+ * \param stream the bitstream context.
+ * \param mac_config the mac config object.
+ * \param mac the beacon entry to store in the beacon.
+ */
+static void
+bsu_beacon_write_bmi_mac_address (bitstream_t *stream,
+ mac_config_t *mac_config,
+ bsu_beacon_bmi_mac_address_t *mac)
+{
+ if (mac->present)
+ {
+ bitstream_write (stream, BSU_BEACON_ENTRY_HEADER_MAC_ADDRESS, 8);
+ bitstream_write (stream, BSU_BEACON_ENTRY_SIZE_MAC_ADDRESS, 8);
+ bitstream_write_large (stream, mac_config->sta_mac_address, 48);
+ }
+}
+
+pb_beacon_t*
+bsu_beacon_write (bsu_beacon_t *beacon, bsu_beacon_type_t type,
+ mac_config_t *mac_config, pbproc_tx_beacon_params_t *params)
+{
+ bitstream_t stream;
+ pb_beacon_t *pbbeacon;
+ u32 offset;
+ dbg_assert (beacon);
+ dbg_assert (type < BSU_BEACON_TYPE_NB);
+ dbg_assert (mac_config);
+ dbg_assert (params);
+ /* Allocate the beacon. */
+ pbbeacon = (pb_beacon_t *) blk_alloc_desc ();
+ bitstream_write_init (&stream, pbbeacon->data, BSU_BEACON_SIZE);
+ bsu_beacon_write_variant_fields (
+ pbbeacon, &stream, mac_config, beacon, type);
+ bitstream_write (&stream, beacon->bmis.nbe, 8);
+ bsu_beacon_write_bmi_region (&stream, &beacon->bmis.region);
+ bsu_beacon_write_bmi_non_persistent (&stream, &beacon->bmis.nps,
+ pbbeacon->data);
+ bsu_beacon_write_bmi_persistent (&stream, &beacon->bmis.ps,
+ pbbeacon->data);
+ offset = bsu_beacon_write_bmi_bpsto (&stream,
+ &beacon->bmis.bpsto);
+ bsu_beacon_write_bmi_discover (&stream, &beacon->bmis.discover);
+ bsu_beacon_write_bmi_discover_info (&stream,
+ &beacon->bmis.discover_info);
+ bsu_beacon_write_bmi_eks (&stream, &beacon->bmis.eks);
+ bsu_beacon_write_bmi_handover (&stream, &beacon->bmis.handover);
+ bsu_beacon_write_bmi_relocation (&stream,
+ &beacon->bmis.relocation);
+ bsu_beacon_write_bmi_aclsc (&stream, &beacon->bmis.aclsc);
+ bsu_beacon_write_bmi_change_num_slot (&stream,
+ &beacon->bmis.cns);
+ bsu_beacon_write_bmi_change_hm (&stream,
+ &beacon->bmis.change_hm);
+ bsu_beacon_write_bmi_change_snid (&stream,
+ &beacon->bmis.change_snid);
+ bsu_beacon_write_bmi_mac_address (&stream, mac_config,
+ &beacon->bmis.mac_address_present);
+ bitstream_finalise (&stream);
+ params->bpsto = pbbeacon->data + offset;
+ return pbbeacon;
+}
+
+/**
+ * Read the beacon variant fields.
+ * \param phy_beacon the beacon received from the medium.
+ * \param stream the bitstream context.
+ * \param mac_config the mac config object.
+ * \param beacon the data to use to write the beacon.
+ * \param type the beacon type.
+ * \param tei the variable to store the TEI.
+ * \return true on success, false otherwise.
+ */
+static bool
+bsu_beacon_read_variant_fields (pb_beacon_t *phy_beacon,
+ bitstream_t *stream,
+ bsu_beacon_t *beacon,
+ bsu_beacon_type_t *type, u8 *tei)
+{
+ beacon->vf.nid = ((u64) bitstream_read (stream, 22)) << 32
+ | phy_beacon->first_data_word;
+ beacon->vf.hm = bitstream_read (stream, 2);
+ *tei = bitstream_read (stream, 8);
+ *type = bitstream_read (stream, 3);
+ beacon->vf.ncnr = bitstream_read (stream, 1);
+ beacon->vf.npsm = bitstream_read (stream, 1);
+ beacon->vf.numslots = bitstream_read (stream, 3);
+ beacon->vf.slotusage = bitstream_read (stream, 8);
+ beacon->vf.slotid = bitstream_read (stream, 3);
+ beacon->vf.aclsss = bitstream_read (stream, 3);
+ beacon->vf.hoip = bitstream_read (stream, 1);
+ beacon->vf.rtsbf = bitstream_read (stream, 1);
+ beacon->vf.nm = bitstream_read (stream, 2);
+ beacon->vf.ccocap = bitstream_read (stream, 2);
+ bitstream_skip (stream, 4);
+ if ((*type < BSU_BEACON_TYPE_NB)
+ && (beacon->vf.nm < BSU_BEACON_NM_NB)
+ && (beacon->vf.nid >> CP_NID_SIZE_BITS) == 0)
+ return true;
+ return false;
+}
+
+/**
+ * Read SAI in the beacon.
+ * \param stream the bitstream context.
+ * \param sai the schedule to fill.
+ */
+static void
+bsu_beacon_read_bmi_schedules_sai (bitstream_t *stream, bsu_beacon_sai_t *sai)
+{
+ sai->stpf = bitstream_read (stream, 1);
+ sai->glid = bitstream_read (stream, 7);
+ if (sai->stpf)
+ sai->start_time_atu = bitstream_read (stream, 12);
+ sai->end_time_atu = bitstream_read (stream, 12);
+}
+
+/**
+ * Read Non Persistent schedules from the beacon.
+ * \param stream the bitstream context.
+ * \param np the structure to store the schedules.
+ */
+static void
+bsu_beacon_read_bmi_non_persistent (
+ bitstream_t *stream, bsu_beacon_bmi_non_persistent_schedule_t *np)
+{
+ uint nb;
+ np->ns = bitstream_read (stream, 6);
+ bitstream_skip (stream, 2);
+ for (nb = 0; nb < np->ns; nb++)
+ bsu_beacon_read_bmi_schedules_sai (stream, &np->sais[nb]);
+}
+
+/**
+ * Read Persistent schedules from the beacon.
+ * \param stream the bitstream context.
+ * \param np the structure to store the schedules.
+ */
+static void
+bsu_beacon_read_bmi_persistent (
+ bitstream_t *stream, bsu_beacon_bmi_persistent_schedule_desc_t *p)
+{
+ uint nb;
+ p->pscd = bitstream_read (stream, 3);
+ p->cscd = bitstream_read (stream, 3);
+ bitstream_skip (stream, 2);
+ p->ns = bitstream_read (stream, 6);
+ bitstream_skip (stream, 2);
+ for (nb = 0; nb < p->ns; nb++)
+ bsu_beacon_read_bmi_schedules_sai (stream, &p->sais[nb]);
+}
+
+/**
+ * Read the beacon period start time offset beacon entry.
+ * \param ctx the module context.
+ * \param stream the bitstream context.
+ * \param bpsto the structure to store the BPSTO value.
+ */
+static void
+bsu_beacon_read_bmi_bpsto (bitstream_t *stream, bsu_beacon_bmi_bpsto_t *bpsto)
+{
+ bpsto->present = true;
+ bpsto->bpsto = bitstream_read (stream, 24);
+}
+
+void
+bsu_beacon_read_schedules (pb_beacon_t *beacon,
+ bsu_beacon_schedules_t *schedules)
+{
+ bitstream_t stream;
+ int i, nbe, nb_persistent = 0;
+ bsu_beacon_entry_header_t header;
+ uint length;
+ dbg_assert (beacon);
+ dbg_assert (schedules);
+ /* Initialise the bitstream context to read the beacon. */
+ bitstream_read_init (&stream, beacon->data, BSU_BEACON_SIZE);
+ /* Skip the NID. */
+ bitstream_skip (&stream, 22);
+ schedules->hm[0] = bitstream_read (&stream, 2);
+ /* Skip the end of variant fields. */
+ bitstream_skip (&stream, 40);
+ /* Read number of beacon entry. */
+ nbe = bitstream_read (&stream, 8);
+ for (i = 0; i < nbe; i++)
+ {
+ header = bitstream_read (&stream, 8);
+ length = bitstream_read (&stream, 8);
+ if (header == BSU_BEACON_ENTRY_HEADER_NON_PERSISTENT_SCHEDULE)
+ bsu_beacon_read_bmi_non_persistent (&stream, &schedules->nps);
+ else if (header == BSU_BEACON_ENTRY_HEADER_PERSISTENT_SCHEDULE)
+ bsu_beacon_read_bmi_persistent (&stream,
+ &schedules->ps.ps[nb_persistent++]);
+ else if (header ==
+ BSU_BEACON_ENTRY_HEADER_BEACON_PERIOD_START_TIME_OFFSET)
+ bsu_beacon_read_bmi_bpsto (&stream, &schedules->bpsto);
+ else
+ /* skip entry. */
+ bitstream_skip (&stream, length * 8);
+ }
+ bitstream_finalise (&stream);
+ schedules->ps.nb = nb_persistent;
+}
+
+/**
+ * Read the beacon entry header and length.
+ * \param stream the bitstream context.
+ * \param header the pointer to store the header.
+ * \param length the pointer to store the length.
+ * \return true on success, false otherwise.
+ */
+bool
+bsu_beacon_read_bmi_header (bitstream_t *bitstream, uint *header,
+ uint *length)
+{
+ *header = bitstream_read (bitstream, 8);
+ *length = bitstream_read (bitstream, 8);
+ if (BSU_BEACON_ENTRY_IS_BENTRY (*header))
+ return true;
+ return false;
+}
+
+/**
+ * Read the beacon region entry.
+ * \param bitstream the bitstream context.
+ * \param region the structure to store the data.
+ * \return true on success, false otherwise.
+ */
+static bool
+bsu_beacon_read_bmi_region (bitstream_t *bitstream,
+ bsu_beacon_bmi_region_t *region)
+{
+ uint i;
+ bool ok = true;
+ region->nb = bitstream_read (bitstream, 6);
+ dbg_assert (region->nb <= BSU_BEACON_BMI_REGION_NAX);
+ bitstream_skip (bitstream, 2);
+ for (i = 0; ok && i < region->nb; i++)
+ {
+ region->region[i].rt = bitstream_read (bitstream, 4);
+ region->region[i].end_time_atu = bitstream_read (bitstream, 12);
+ ok = region->region[i].rt < BSU_BEACON_REGION_NB;
+ }
+ return ok;
+}
+
+/**
+ * Read the beacon mac address entry.
+ * \param bitstream the bitstream context.
+ * \param mac_address to store data,
+ * \return true on success, false otherwise.
+ */
+static bool
+bsu_beacon_read_bmi_mac_address (bitstream_t *bitstream, mac_t *mac_address)
+{
+ *mac_address = bitstream_read_large (bitstream, 48);
+ return MAC_IS_VALID (*mac_address);
+}
+
+/**
+ * Read the beacon discover entry.
+ * \param bitstream the bitstream context.
+ * \param discover the discover structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_discover (bitstream_t *bitstream,
+ bsu_beacon_bmi_discover_t *discover)
+{
+ discover->tei = bitstream_read (bitstream, 8);
+ discover->present = MAC_TEI_IS_STA (discover->tei);
+}
+
+/**
+ * Read the beacon discover info entry.
+ * \param bitstream the bitstream context.
+ * \param info the info structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_discover_info (bitstream_t *bitstream,
+ bsu_beacon_bmi_discover_info_t *info)
+{
+ info->info_data = bitstream_read (bitstream, 32);
+ info->present = true;
+}
+
+/**
+ * Read the beacon handover entry.
+ * \param bitstream the bitstream context.
+ * \param handover the handover structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_handover (bitstream_t *bitstream,
+ bsu_beacon_bmi_handover_t *handover)
+{
+ handover->hcd = bitstream_read (bitstream, 6);
+ bitstream_skip (bitstream, 2);
+ handover->tei = bitstream_read (bitstream, 8);
+ handover->present = MAC_TEI_IS_STA (handover->tei);
+}
+
+/**
+ * Read the Change Hybrid mode.
+ * \param bitstream the bitstream context.
+ * \param hm the hybrid mode structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_change_hm (bitstream_t *bitstream,
+ bsu_beacon_bmi_change_hybrid_mode_t *hm)
+{
+ hm->present = true;
+ hm->hmccd = bitstream_read (bitstream, 6);
+ hm->newhm = bitstream_read (bitstream, 2);
+}
+
+/**
+ * Read the Change SNID.
+ * \param bitstream the bitstream context.
+ * \param snid the snid structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_change_snid (bitstream_t *bitstream,
+ bsu_beacon_bmi_change_snid_t *snid)
+{
+ snid->present = true;
+ snid->snidccd = bitstream_read (bitstream, 4);
+ snid->new_snid = bitstream_read (bitstream, 4);
+}
+
+/**
+ * Read the EKS bentry.
+ * \param bitstream the bitstream context.
+ * \param ekc the encryption key change structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_eks (bitstream_t *bitstream, bsu_beacon_bmi_eks_t *ekc)
+{
+ ekc->kccd = bitstream_read (bitstream, 6);
+ ekc->kbc = bitstream_read (bitstream, 1);
+ bitstream_skip (bitstream, 1);
+ ekc->new_eks = bitstream_read (bitstream, 4);
+ bitstream_skip (bitstream, 4);
+ ekc->present = (ekc->kbc < BSU_BEACON_EKS_KBC_NB);
+}
+
+/**
+ * Read the relocation bentry.
+ * \param bitstream the bitstream context.
+ * \param relocation the relocation structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_relocation (bitstream_t *stream,
+ bsu_beacon_bmi_relocation_t *relocation)
+{
+ relocation->present = true;
+ relocation->rcd = bitstream_read (stream, 6);
+ relocation->rlt = bitstream_read (stream, 1);
+ relocation->lgf = bitstream_read (stream, 1);
+ relocation->rlo = bitstream_read (stream, 17);
+ relocation->rlslotid = bitstream_read (stream, 3);
+ bitstream_skip (stream, 4);
+}
+
+/**
+ * Read the AC Line synchronisation bentry.
+ * \param bitstream the bitstream context.
+ * \param acl the acl structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_aslsc (bitstream_t *stream, bsu_beacon_bmi_aclsc_t *aclsc)
+{
+ aclsc->present = true;
+ aclsc->countdown = bitstream_read (stream, 6);
+ bitstream_skip (stream, 2);
+ aclsc->reason_code = bitstream_read (stream, 2);
+ bitstream_skip (stream, 6);
+}
+
+/**
+ * Read the change number of slots beacon entry.
+ * \param stream the bitstream context.
+ * \param cns the cns structure to store the data.
+ */
+static void
+bsu_beacon_read_bmi_change_num_slot (bitstream_t *stream,
+ bsu_beacon_bmi_change_num_slot_t *cns)
+{
+ cns->present = true;
+ cns->nsccd = bitstream_read (stream, 6);
+ bitstream_skip (stream, 2);
+ cns->newnumslot = bitstream_read (stream, 3);
+ bitstream_skip (stream, 5);
+}
+
+bool
+bsu_beacon_read (pb_beacon_t *pbbeacon, bsu_beacon_t *beacon,
+ bsu_beacon_type_t *type, u8 *tei, mac_t *mac_address)
+{
+ bitstream_t stream;
+ int nb_persistent = 0;
+ bsu_beacon_entry_header_t header;
+ uint nbe, length;
+ bool ok = false;
+ dbg_assert (pbbeacon);
+ dbg_assert (beacon);
+ /* If the CRC is false, stop all the data inside are corrupted. */
+ if (pbbeacon->phy_pb.pb_rx.pb_measurement.crc_error)
+ return false;
+ /* Initialise the data needed for the job. */
+ bitstream_read_init (&stream, pbbeacon->data, BSU_BEACON_SIZE);
+ ok = bsu_beacon_read_variant_fields (
+ pbbeacon, &stream, beacon, type, tei);
+ beacon->bmis.nbe = bitstream_read (&stream, 8);
+ // Processing beacon entries.
+ for (nbe = 0; ok && nbe < beacon->bmis.nbe; nbe++)
+ {
+ ok = bsu_beacon_read_bmi_header (&stream, &header, &length);
+ if (ok)
+ {
+ switch (header)
+ {
+ case BSU_BEACON_ENTRY_HEADER_REGIONS:
+ ok = bsu_beacon_read_bmi_region (
+ &stream, &beacon->bmis.region);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_NON_PERSISTENT_SCHEDULE:
+ bsu_beacon_read_bmi_non_persistent (
+ &stream, &beacon->bmis.nps);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_PERSISTENT_SCHEDULE:
+ bsu_beacon_read_bmi_persistent (
+ &stream, &beacon->bmis.ps.ps[nb_persistent++]);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_MAC_ADDRESS:
+ ok = bsu_beacon_read_bmi_mac_address (&stream, mac_address);
+ beacon->bmis.mac_address_present.present = ok;
+ break;
+ case BSU_BEACON_ENTRY_HEADER_DISCOVER:
+ bsu_beacon_read_bmi_discover (
+ &stream, &beacon->bmis.discover);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_DISCOVERED_INFO:
+ bsu_beacon_read_bmi_discover_info (
+ &stream, &beacon->bmis.discover_info);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_BEACON_PERIOD_START_TIME_OFFSET:
+ bsu_beacon_read_bmi_bpsto (&stream, &beacon->bmis.bpsto);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CCO_HANDOVER:
+ bsu_beacon_read_bmi_handover (
+ &stream, &beacon->bmis.handover);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CHANGE_HM:
+ bsu_beacon_read_bmi_change_hm (
+ &stream, &beacon->bmis.change_hm);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CHANGE_SNID:
+ bsu_beacon_read_bmi_change_snid (
+ &stream, &beacon->bmis.change_snid);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_ENCRYPTION_KEY_CHANGE:
+ bsu_beacon_read_bmi_eks (&stream, &beacon->bmis.eks);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_BEACON_RELOCATION:
+ bsu_beacon_read_bmi_relocation (&stream,
+ &beacon->bmis.relocation);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_AC_LINE_SYNC_COUNTDOWN:
+ bsu_beacon_read_bmi_aslsc (&stream, &beacon->bmis.aclsc);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CHANGE_NUMSLOTS:
+ bsu_beacon_read_bmi_change_num_slot (
+ &stream, &beacon->bmis.cns);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_VENDOR:
+ default:
+ if (BYTES_SIZE_TO_BITS (length) <
+ bitstream_available_bits (&stream))
+ bitstream_skip (&stream, BYTES_SIZE_TO_BITS (length));
+ break;
+ }
+ }
+ }
+ bitstream_finalise (&stream);
+ beacon->bmis.ps.nb = nb_persistent;
+ /* If the beacon seams still ok check if the mandatory fields are
+ * present. */
+ if (ok
+ && !((*type == BSU_BEACON_TYPE_CENTRAL)
+ && (beacon->bmis.region.nb != 0)
+ && (beacon->bmis.nps.ns != 0 || beacon->bmis.ps.nb != 0)
+ && (((beacon->vf.nm == BSU_BEACON_NM_CSMA_ONLY)
+ && (beacon->bmis.bpsto.present == true))
+ || (beacon->vf.nm != BSU_BEACON_NM_CSMA_ONLY))
+ && (((beacon->vf.hoip == true)
+ && (beacon->bmis.handover.present == true))
+ || (beacon->vf.hoip == false)))
+ && !((*type == BSU_BEACON_TYPE_DISCOVER)
+ && (beacon->bmis.region.nb != 0)
+ && (beacon->bmis.mac_address_present.present == true)
+ && (beacon->bmis.discover_info.present == true)
+ && (beacon->bmis.bpsto.present == true))
+ && !((*type == BSU_BEACON_TYPE_PROXY)
+ && (beacon->bmis.bpsto.present == true)))
+ ok = false;
+ return ok;
+}
+
+void
+bsu_beacon_countdown (bsu_beacon_t *beacon)
+{
+ uint nb;
+ dbg_assert (beacon);
+ /* Parse persistent schedules and decrease the counter. */
+ for (nb = 0; nb < beacon->bmis.ps.nb; nb++)
+ {
+ /* Invalidate the persistent schedule if the current countdown is
+ * null. */
+ if (beacon->bmis.ps.ps[nb].pscd == 0
+ && beacon->bmis.ps.ps[nb].cscd == 0)
+ {
+ uint i;
+ beacon->bmis.ps.nb --;
+ /* move all the schedules after this one to this current position.
+ * */
+ for (i = nb; i < beacon->bmis.ps.nb; i++)
+ beacon->bmis.ps.ps[i] = beacon->bmis.ps.ps[i+1];
+ nb--;
+ }
+ /* Previous countdown. */
+ else if (beacon->bmis.ps.ps[nb].pscd)
+ beacon->bmis.ps.ps[nb].pscd--;
+ else if (beacon->bmis.ps.ps[nb].cscd)
+ beacon->bmis.ps.ps[nb].cscd--;
+ }
+ /* Encryption key change. */
+ if (beacon->bmis.eks.present)
+ {
+ beacon->bmis.eks.kccd --;
+ beacon->bmis.eks.present = beacon->bmis.eks.kccd;
+ }
+ /* CCo handover. */
+ if (beacon->bmis.handover.present)
+ {
+ beacon->bmis.handover.hcd --;
+ beacon->bmis.handover.present = beacon->bmis.handover.hcd;
+ }
+ /* Relocation beacon entry. */
+ if (beacon->bmis.relocation.present)
+ {
+ beacon->bmis.relocation.rcd --;
+ beacon->bmis.relocation.present = beacon->bmis.relocation.rcd;
+ }
+ /* AC Line synchronization beacon entry. */
+ if (beacon->bmis.aclsc.present)
+ {
+ beacon->bmis.aclsc.countdown --;
+ beacon->bmis.aclsc.present = beacon->bmis.aclsc.countdown;
+ }
+ /* Change num slots beacon entry. */
+ if (beacon->bmis.cns.present)
+ {
+ beacon->bmis.cns.nsccd --;
+ beacon->bmis.cns.present = beacon->bmis.cns.nsccd;
+ }
+ /* Change HM beacon entry. */
+ if (beacon->bmis.change_hm.present)
+ {
+ beacon->bmis.change_hm.hmccd --;
+ beacon->bmis.change_hm.present = beacon->bmis.change_hm.hmccd;
+ }
+ /* Change SNID beacon entry. */
+ if (beacon->bmis.change_snid.present)
+ {
+ beacon->bmis.change_snid.snidccd --;
+ beacon->bmis.change_snid.present = beacon->bmis.change_snid.snidccd;
+ }
+}
diff --git a/cesar/bsu/beacon/test/utest/Makefile b/cesar/bsu/beacon/test/utest/Makefile
new file mode 100644
index 0000000000..50de64f980
--- /dev/null
+++ b/cesar/bsu/beacon/test/utest/Makefile
@@ -0,0 +1,7 @@
+BASE = ../../../..
+
+HOST_PROGRAMS = beacon
+beacon_SOURCES = test.c beacon.c
+beacon_MODULES = lib bsu/beacon mac/common
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/bsu/beacon/test/utest/src/beacon.c b/cesar/bsu/beacon/test/utest/src/beacon.c
new file mode 100644
index 0000000000..fbe930949f
--- /dev/null
+++ b/cesar/bsu/beacon/test/utest/src/beacon.c
@@ -0,0 +1,305 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file beacon/test/utest/src/beacon.c
+ * \brief Beacon library unit test.
+ * \ingroup beacon
+ *
+ */
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/bitstream.h"
+#include "bsu/beacon/test/utest/test.h"
+#include <string.h>
+
+bool
+bsu_beacon_read_bmi_header (bitstream_t *bitstream, uint *header,
+ uint *length);
+
+static void
+test_mac_config_init (mac_config_t *mac_config)
+{
+ mac_config_init (mac_config);
+ mac_config->sta_mac_address = 0x123456789abcull;
+ mac_config->tei = 0xa;
+}
+
+void
+test_case_beacon_write_read (test_t t)
+{
+ pb_beacon_t *pbbeacon;
+ pbproc_tx_beacon_params_t params;
+ bsu_beacon_t beacon, beacon_recv;
+ mac_config_t mac_config;
+ bsu_beacon_schedules_t schedules;
+ u8 tei;
+ u64 mac_addr;
+ bsu_beacon_type_t type;
+ test_mac_config_init (&mac_config);
+ memset (&beacon, 0, sizeof (bsu_beacon_t));
+ memset (&beacon_recv, 0, sizeof (bsu_beacon_t));
+ test_case_begin (t, "BSU beacon write/read");
+ test_begin (t, "Write Central Beacon")
+ {
+ bsu_beacon_test_create_beacon (&beacon);
+ pbbeacon = bsu_beacon_write (&beacon,
+ BSU_BEACON_TYPE_CENTRAL,
+ &mac_config,
+ &params);
+ bsu_beacon_test_beacon_check_generation (t, &mac_config,
+ &beacon, pbbeacon,
+ BSU_BEACON_TYPE_CENTRAL);
+ }
+ test_end;
+ test_begin (t, "Read central beacon")
+ {
+ bsu_beacon_read_schedules (pbbeacon, &schedules);
+ bsu_beacon_test_beacon_check_read (t, &beacon, &schedules);
+ }
+ test_end;
+ test_begin (t, "Read completely")
+ {
+ bool returned;
+ pbbeacon->phy_pb.pb_rx.pb_measurement.crc_error = false;
+ returned = bsu_beacon_read (pbbeacon, &beacon_recv, &type, &tei,
+ &mac_addr);
+ /* The bpsto value is set by the PBProc.*/
+ beacon_recv.bmis.bpsto.bpsto = beacon.bmis.bpsto.bpsto;
+ test_fail_unless (returned == true);
+ test_fail_unless (
+ memcmp (&beacon, &beacon_recv, sizeof (bsu_beacon_t)) == 0);
+ test_fail_unless (mac_addr == mac_config.sta_mac_address);
+ test_fail_unless (tei == mac_config.tei);
+ pbbeacon->phy_pb.pb_rx.pb_measurement.crc_error = true;
+ returned = bsu_beacon_read (pbbeacon, &beacon_recv, &type, &tei,
+ &mac_addr);
+ test_fail_unless (returned == false);
+ blk_release_desc ((blk_t*) pbbeacon);
+ }
+ test_end;
+}
+
+void
+test_case_countdown (test_t t)
+{
+ bsu_beacon_t beacon;
+ test_case_begin (t, "Beacon countdown");
+ test_begin (t, "countdown on schedules.")
+ {
+ bsu_beacon_test_create_beacon (&beacon);
+ beacon.bmis.ps.ps[0].cscd = 1;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.ps.nb == 2);
+ test_fail_unless (beacon.bmis.ps.ps[0].pscd == 0);
+ test_fail_unless (beacon.bmis.ps.ps[0].cscd == 1);
+ test_fail_unless (beacon.bmis.ps.ps[1].pscd == 1);
+ test_fail_unless (beacon.bmis.ps.ps[1].cscd == 5);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.ps.nb == 2);
+ test_fail_unless (beacon.bmis.ps.ps[0].pscd == 0);
+ test_fail_unless (beacon.bmis.ps.ps[0].cscd == 0);
+ test_fail_unless (beacon.bmis.ps.ps[1].pscd == 0);
+ test_fail_unless (beacon.bmis.ps.ps[1].cscd == 5);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.ps.nb == 1);
+ test_fail_unless (beacon.bmis.ps.ps[0].pscd == 0);
+ test_fail_unless (beacon.bmis.ps.ps[0].cscd == 4);
+ }
+ test_end;
+ test_begin (t, "Encryption key change countdown")
+ {
+ beacon.bmis.eks.present = true;
+ beacon.bmis.eks.kccd = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.eks.present == true);
+ test_fail_unless (beacon.bmis.eks.kccd == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.eks.present == false);
+ }
+ test_end;
+ test_begin (t, "CCo handover countdown")
+ {
+ beacon.bmis.handover.present = true;
+ beacon.bmis.handover.hcd = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.handover.present == true);
+ test_fail_unless (beacon.bmis.handover.hcd == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.handover.present == false);
+ }
+ test_end;
+ test_begin (t, "Beacon relocation countdown")
+ {
+ beacon.bmis.relocation.present = true;
+ beacon.bmis.relocation.rcd = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.relocation.present == true);
+ test_fail_unless (beacon.bmis.relocation.rcd == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.relocation.present == false);
+ }
+ test_end;
+ test_begin (t, "AC Line Synchronization countdown")
+ {
+ beacon.bmis.aclsc.present = true;
+ beacon.bmis.aclsc.countdown = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.aclsc.present == true);
+ test_fail_unless (beacon.bmis.aclsc.countdown == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.aclsc.present == false);
+ }
+ test_end;
+ test_begin (t, "Change number of slots countdown")
+ {
+ beacon.bmis.cns.present = true;
+ beacon.bmis.cns.nsccd = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.cns.present == true);
+ test_fail_unless (beacon.bmis.cns.nsccd == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.cns.present == false);
+ }
+ test_end;
+ test_begin (t, "Change Hybrid mode countdown")
+ {
+ beacon.bmis.change_hm.present = true;
+ beacon.bmis.change_hm.hmccd = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.change_hm.present == true);
+ test_fail_unless (beacon.bmis.change_hm.hmccd == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.change_hm.present == false);
+ }
+ test_end;
+ test_begin (t, "Change SNID countdown")
+ {
+ beacon.bmis.change_snid.present = true;
+ beacon.bmis.change_snid.snidccd = 2;
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.change_snid.present == true);
+ test_fail_unless (beacon.bmis.change_snid.snidccd == 1);
+ bsu_beacon_countdown (&beacon);
+ test_fail_unless (beacon.bmis.change_snid.present == false);
+ }
+ test_end;
+}
+
+void
+test_case_beacon_variant_fields_error (test_t test)
+{
+ test_case_begin (test, "Variant fields error");
+ test_begin (test, "Wrong type or network mode")
+ {
+ mac_config_t mac_config;
+ bsu_beacon_t beacon;
+ pb_beacon_t *phy_beacon;
+ pbproc_tx_beacon_params_t params;
+ bsu_beacon_type_t type;
+ u8 tei;
+ u64 mac_addr;
+ bool returned;
+ test_mac_config_init (&mac_config);
+ /* Change network mode type. */
+ bsu_beacon_test_create_beacon (&beacon);
+ beacon.vf.nm = BSU_BEACON_NM_NB;
+ phy_beacon = bsu_beacon_write (&beacon, BSU_BEACON_TYPE_CENTRAL,
+ &mac_config, &params);
+ phy_beacon->phy_pb.pb_rx.pb_measurement.crc_error = false;
+ test_fail_unless (bsu_beacon_read (phy_beacon, &beacon,
+ &type, &tei, &mac_addr) == false);
+ blk_release_desc ((blk_t*) phy_beacon);
+ /* Reset network mode type. */
+ bsu_beacon_test_create_beacon (&beacon);
+ phy_beacon = bsu_beacon_write (&beacon, BSU_BEACON_TYPE_CENTRAL,
+ &mac_config, &params);
+ phy_beacon->phy_pb.pb_rx.pb_measurement.crc_error = false;
+ bitstream_direct_write (phy_beacon->data, 32, BSU_BEACON_TYPE_NB, 3);
+ returned = bsu_beacon_read (phy_beacon, &beacon, &type, &tei,
+ &mac_addr);
+ test_fail_unless (type == BSU_BEACON_TYPE_NB);
+ test_fail_unless (returned == false);
+ blk_release_desc ((blk_t*) phy_beacon);
+ }
+ test_end;
+}
+
+void
+test_case_beacon_bmi_header_false (test_t test)
+{
+ test_case_begin (test, "Wrong Beacon entry header");
+ test_begin (test, "")
+ {
+ u8 buffer[2];
+ bsu_beacon_entry_header_t header;
+ uint length;
+ bitstream_t stream;
+ bool ok;
+ buffer[0] = BSU_BEACON_ENTRY_HEADER_RSVD_MIN;
+ buffer[1] = 8;
+ bitstream_read_init (&stream, buffer, 2);
+ ok = bsu_beacon_read_bmi_header (&stream, &header, &length);
+ test_fail_unless (ok == false);
+ buffer[0] = BSU_BEACON_ENTRY_HEADER_AC_LINE_SYNC_COUNTDOWN;
+ bitstream_read_init (&stream, buffer, 2);
+ ok = bsu_beacon_read_bmi_header (&stream, &header, &length);
+ test_fail_unless (ok == true);
+ }
+ test_end;
+}
+
+void
+test_case_beacon_bmi_vendor_bentry (test_t test)
+{
+ test_case_begin (test, "Vendor specific");
+ test_begin (test, "")
+ {
+ mac_config_t mac_config;
+ bsu_beacon_t beacon;
+ pb_beacon_t *phy_beacon;
+ pbproc_tx_beacon_params_t params;
+ bsu_beacon_type_t type;
+ u8 tei;
+ u64 mac_addr;
+ bool returned;
+ test_mac_config_init (&mac_config);
+ /* Change network mode type. */
+ bsu_beacon_test_create_beacon (&beacon);
+ phy_beacon = bsu_beacon_write (&beacon, BSU_BEACON_TYPE_CENTRAL,
+ &mac_config, &params);
+ phy_beacon->phy_pb.pb_rx.pb_measurement.crc_error = false;
+ bitstream_direct_write (phy_beacon->data, 72,
+ BSU_BEACON_ENTRY_HEADER_VENDOR, 8);
+ memset (&beacon, 0, sizeof (bsu_beacon_t));
+ returned = bsu_beacon_read (phy_beacon, &beacon, &type, &tei,
+ &mac_addr);
+ test_fail_unless (returned == false);
+ blk_release_desc ((blk_t*) phy_beacon);
+ }
+ test_end;
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t test;
+ test_init (test, argc, argv);
+ test_suite_begin (test, "Beacon");
+ test_case_beacon_write_read (test);
+ test_case_countdown (test);
+ test_case_beacon_variant_fields_error (test);
+ test_case_beacon_bmi_header_false (test);
+ test_case_beacon_bmi_vendor_bentry (test);
+ test_begin (test, "Memory")
+ {
+ test_fail_if (blk_check_memory() == false, "Memory not freed");
+ }
+ test_end;
+ test_result (test);
+ return test_nb_failed (test) == 0 ? 0 : 1;
+}
diff --git a/cesar/bsu/beacon/test/utest/src/test.c b/cesar/bsu/beacon/test/utest/src/test.c
new file mode 100644
index 0000000000..8d1f488696
--- /dev/null
+++ b/cesar/bsu/beacon/test/utest/src/test.c
@@ -0,0 +1,417 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu/beacon/test/utest/src/test.c
+ * \brief bsu/beacon
+ * \ingroup bsu_beacon
+ *
+ */
+#include "common/std.h"
+#include "bsu/beacon/beacon.h"
+#include "bsu/beacon/defs.h"
+#include "lib/test.h"
+#include "lib/bitstream.h"
+#include "mac/common/pb.h"
+#include <string.h>
+
+void
+bsu_beacon_test_schedules_persistent (
+ bsu_beacon_bmi_persistent_schedule_t *ps)
+{
+ /* Persistent schedules. */
+ ps->nb = 2;
+ ps->ps[0].pscd = 1;
+ ps->ps[0].cscd = 5;
+ ps->ps[0].ns = 1;
+ ps->ps[0].sais[0].stpf = true;
+ ps->ps[0].sais[0].glid = 0;
+ ps->ps[0].sais[0].start_time_atu = 700;
+ ps->ps[0].sais[0].end_time_atu = 1000;
+ ps->ps[1].pscd = 2;
+ ps->ps[1].cscd = 5;
+ ps->ps[1].ns = 2;
+ ps->ps[1].sais[0].stpf = true;
+ ps->ps[1].sais[0].glid = 0;
+ ps->ps[1].sais[0].start_time_atu = 50;
+ ps->ps[1].sais[0].end_time_atu = 500;
+ ps->ps[1].sais[1].stpf = false;
+ ps->ps[1].sais[1].glid = 0;
+ ps->ps[1].sais[1].start_time_atu = 0;
+ ps->ps[1].sais[1].end_time_atu = 1600;
+}
+
+void
+bsu_beacon_test_schedules_non_persistent (
+ bsu_beacon_bmi_non_persistent_schedule_t *nps)
+{
+ /* Non persistent schedules. */
+ nps->ns = 3;
+ nps->sais[0].stpf = true;
+ nps->sais[0].glid = 0;
+ nps->sais[0].start_time_atu = 500;
+ nps->sais[0].end_time_atu = 700;
+ nps->sais[1].stpf = true;
+ nps->sais[1].glid = 0;
+ nps->sais[1].start_time_atu = 1600;
+ nps->sais[1].end_time_atu = 2500;
+ nps->sais[2].stpf = false;
+ nps->sais[2].glid = 0;
+ nps->sais[2].start_time_atu = 0;
+ nps->sais[2].end_time_atu = 3907;
+}
+
+void
+bsu_beacon_test_create_beacon (bsu_beacon_t *beacon)
+{
+ dbg_assert (beacon);
+ memset (beacon, 0, sizeof (bsu_beacon_t));
+ beacon->vf.nid = 0x11223344556677ull;
+ beacon->vf.hm = MAC_COEXISTENCE_FULL_HYBRID_MODE;
+ beacon->vf.ncnr = false;
+ beacon->vf.npsm = false;
+ beacon->vf.numslots = 0;
+ beacon->vf.slotusage = 0;
+ beacon->vf.slotid = 0;
+ beacon->vf.aclsss = true;
+ beacon->vf.hoip = false;
+ beacon->vf.rtsbf = false;
+ beacon->vf.nm = false;
+ beacon->vf.ccocap = 0;
+ beacon->vf.rsvd = 0;
+ /* Regions. */
+ beacon->bmis.region.nb = 2;
+ beacon->bmis.region.region[0].rt = BSU_BEACON_REGION_BEACON;
+ beacon->bmis.region.region[0].end_time_atu = 50;
+ beacon->bmis.region.region[1].rt = BSU_BEACON_REGION_SHARED_CSMA;
+ beacon->bmis.region.region[1].end_time_atu = 3907;
+ bsu_beacon_test_schedules_persistent (&beacon->bmis.ps);
+ bsu_beacon_test_schedules_non_persistent (&beacon->bmis.nps);
+ /* BSPTO. */
+ beacon->bmis.bpsto.present = true;
+ beacon->bmis.bpsto.bpsto = 0xfed0;
+ /* Discover. */
+ beacon->bmis.discover.present = true;
+ beacon->bmis.discover.tei = 0xc;
+ /* Discover info. */
+ beacon->bmis.discover_info.present = true;
+ beacon->bmis.discover_info.info_data = 0xcafecafe;
+ /* Encryption key change. */
+ beacon->bmis.eks.present = true;
+ beacon->bmis.eks.kccd = 5;
+ beacon->bmis.eks.kbc = 1;
+ beacon->bmis.eks.new_eks = 2;
+ /* Handover. */
+ beacon->bmis.handover.present = true;
+ beacon->bmis.handover.hcd = true;
+ beacon->bmis.handover.tei = 0xd;
+ /* Beacon relocation. */
+ beacon->bmis.relocation.present = true;
+ beacon->bmis.relocation.rcd = 3;
+ beacon->bmis.relocation.rlt = true;
+ beacon->bmis.relocation.lgf = true;
+ beacon->bmis.relocation.rlo = 3;
+ beacon->bmis.relocation.rlslotid = 4;
+ /* Relocation ACLS. */
+ beacon->bmis.aclsc.present = true;
+ beacon->bmis.aclsc.countdown = 5;
+ beacon->bmis.aclsc.reason_code = 0;
+ /* CNS. */
+ beacon->bmis.cns.present = true;
+ beacon->bmis.cns.nsccd = 5;
+ beacon->bmis.cns.newnumslot = 4;
+ /* Hybrid mode. */
+ beacon->bmis.change_hm.present = true;
+ beacon->bmis.change_hm.hmccd = 7;
+ beacon->bmis.change_hm.newhm = 2;
+ /* Change snid. */
+ beacon->bmis.change_snid.present = true;
+ beacon->bmis.change_snid.snidccd = 4;
+ beacon->bmis.change_snid.new_snid = 0xf;
+ /* Mac address. */
+ beacon->bmis.mac_address_present.present = true;
+ /* Number of beacon entries. */
+ beacon->bmis.nbe = 15;
+}
+
+void
+bsu_beacon_test_beacon_check_generation (test_t t,
+ mac_config_t *mac_config,
+ bsu_beacon_t *beacon,
+ pb_beacon_t *phy_beacon,
+ bsu_beacon_type_t type)
+{
+ bitstream_t stream;
+ u64 nid;
+ uint j, i, nbe, nb_ps = 0, length;
+ bsu_beacon_entry_header_t header;
+ uint nb_sai = 0;
+ uint nb_nsai = 0;
+ dbg_assert (beacon);
+ dbg_assert (phy_beacon);
+
+ test_begin (t, "Beacon verification")
+ {
+ nid = phy_beacon->first_data_word;
+ bitstream_read_init (&stream, phy_beacon->data, BLK_SIZE);
+ nid |= (u64) bitstream_read (&stream, 22) << 32;
+ test_fail_unless (nid == beacon->vf.nid);
+ test_fail_unless (beacon->vf.hm == bitstream_read (&stream, 2));
+ test_fail_unless (mac_config->tei == bitstream_read (&stream, 8));
+ test_fail_unless (type == bitstream_read (&stream, 3));
+ test_fail_unless (beacon->vf.ncnr == bitstream_read (&stream, 1));
+ test_fail_unless (beacon->vf.npsm == bitstream_read (&stream, 1));
+ test_fail_unless (beacon->vf.numslots == bitstream_read (&stream, 3));
+ test_fail_unless (beacon->vf.slotusage == bitstream_read (&stream, 8));
+ test_fail_unless (beacon->vf.slotid == bitstream_read (&stream, 3));
+ test_fail_unless (beacon->vf.aclsss == bitstream_read (&stream, 3));
+ test_fail_unless (beacon->vf.hoip == bitstream_read (&stream, 1));
+ test_fail_unless (beacon->vf.rtsbf == bitstream_read (&stream, 1));
+ test_fail_unless (beacon->vf.nm == bitstream_read (&stream, 2));
+ test_fail_unless (beacon->vf.ccocap == bitstream_read (&stream, 2));
+ /* Reserved bits. */
+ bitstream_skip (&stream, 4);
+ /* Number of Beacon Entries. */
+ nbe = bitstream_read (&stream, 8);
+ test_fail_unless (beacon->bmis.nbe == nbe);
+ test_fail_unless (nbe != 0);
+ // Processing beacon entries.
+ for (j = 0; j < nbe; j++)
+ {
+ header = bitstream_read (&stream, 8);
+ length = bitstream_read (&stream, 8);
+ switch (header)
+ {
+ case BSU_BEACON_ENTRY_HEADER_REGIONS:
+ /* Region beacon entry (Mandatory). */
+ test_fail_unless (length ==
+ BSU_BEACON_ENTRY_SIZE_REGION
+ (beacon->bmis.region.nb));
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.region.nb);
+ bitstream_skip (&stream, 2);
+ for (i = 0; i < beacon->bmis.region.nb; i++)
+ {
+ test_fail_unless (bitstream_read (&stream, 4) ==
+ beacon->bmis.region.region[i].rt);
+ test_fail_unless (bitstream_read (&stream, 12) ==
+ beacon->bmis.region.region[i].end_time_atu);
+ }
+ break;
+ case BSU_BEACON_ENTRY_HEADER_NON_PERSISTENT_SCHEDULE:
+ nb_sai = 0;
+ nb_nsai = 0;
+ test_fail_unless (beacon->bmis.nps.ns ==
+ bitstream_read (&stream, 6));
+ bitstream_skip (&stream, 2);
+ for (i = 0; i < beacon->bmis.nps.ns; i++)
+ {
+ test_fail_unless (bitstream_read (&stream, 1) ==
+ beacon->bmis.nps.sais[i].stpf);
+ test_fail_unless (bitstream_read (&stream, 7) ==
+ beacon->bmis.nps.sais[i].glid);
+ if (beacon->bmis.nps.sais[i].stpf)
+ {
+ test_fail_unless (bitstream_read (&stream, 12) ==
+ beacon->bmis.nps.sais[i].start_time_atu);
+ nb_sai++;
+ }
+ else
+ nb_nsai++;
+ test_fail_unless (bitstream_read (&stream, 12) ==
+ beacon->bmis.nps.sais[i].end_time_atu);
+ }
+ test_fail_unless (length ==
+ BSU_BEACON_ENTRY_SIZE_NON_PERSISTENT_SCHED
+ (nb_sai, nb_nsai));
+ break;
+ case BSU_BEACON_ENTRY_HEADER_PERSISTENT_SCHEDULE:
+ nb_sai = 0;
+ nb_nsai = 0;
+ test_fail_unless (beacon->bmis.ps.ps[nb_ps].pscd ==
+ bitstream_read (&stream, 3));
+ test_fail_unless (beacon->bmis.ps.ps[nb_ps].cscd ==
+ bitstream_read (&stream, 3));
+ bitstream_skip (&stream, 2);
+ test_fail_unless (beacon->bmis.ps.ps[nb_ps].ns ==
+ bitstream_read (&stream, 6));
+ bitstream_skip (&stream, 2);
+ for (i = 0; i < beacon->bmis.ps.ps[nb_ps].ns; i++)
+ {
+ test_fail_unless (bitstream_read (&stream, 1) ==
+ beacon->bmis.ps.ps[nb_ps].sais[i].stpf);
+ test_fail_unless (bitstream_read (&stream, 7) ==
+ beacon->bmis.ps.ps[nb_ps].sais[i].glid);
+ if (beacon->bmis.ps.ps[nb_ps].sais[i].stpf)
+ {
+ test_fail_unless (bitstream_read (&stream, 12) ==
+ beacon->bmis.ps.ps[nb_ps].sais[i].start_time_atu);
+ nb_sai++;
+ }
+ else
+ nb_nsai++;
+ test_fail_unless (bitstream_read (&stream, 12) ==
+ beacon->bmis.ps.ps[nb_ps].sais[i].end_time_atu);
+ }
+ test_fail_unless (length ==
+ BSU_BEACON_ENTRY_SIZE_PERSISTENT_SCHED
+ (nb_sai, nb_nsai));
+ nb_ps++;
+ break;
+ case BSU_BEACON_ENTRY_HEADER_MAC_ADDRESS:
+ test_fail_unless (beacon->bmis.mac_address_present.present ==
+ true);
+ test_fail_unless (mac_config->sta_mac_address ==
+ bitstream_read_large (&stream, 48));
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_MAC_ADDRESS);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_DISCOVER:
+ test_fail_unless (beacon->bmis.discover.present == true);
+ test_fail_unless (beacon->bmis.discover.tei ==
+ bitstream_read (&stream, 8));
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_DISCOVER);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_DISCOVERED_INFO:
+ test_fail_unless (beacon->bmis.discover_info.present == true);
+ test_fail_unless (beacon->bmis.discover_info.info_data ==
+ bitstream_read (&stream, 32));
+ test_fail_unless (length ==
+ BSU_BEACON_ENTRY_SIZE_DISCOVER_INFO);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_BEACON_PERIOD_START_TIME_OFFSET:
+ test_fail_unless (beacon->bmis.bpsto.present == true);
+ test_fail_unless (bitstream_read (&stream, 24) == 0);
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_BPSTO);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CCO_HANDOVER:
+ test_fail_unless (beacon->bmis.handover.present == true);
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.handover.hcd);
+ bitstream_skip (&stream, 2);
+ test_fail_unless (bitstream_read (&stream, 8) ==
+ beacon->bmis.handover.tei);
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_HOIP);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CHANGE_HM:
+ test_fail_unless (beacon->bmis.change_hm.present == true);
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_CHANGE_HM);
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.change_hm.hmccd);
+ test_fail_unless (bitstream_read (&stream, 2) ==
+ beacon->bmis.change_hm.newhm);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CHANGE_SNID:
+ test_fail_unless (beacon->bmis.change_snid.present == true);
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_CHANGE_SNID);
+ test_fail_unless (bitstream_read (&stream, 4) ==
+ beacon->bmis.change_snid.snidccd);
+ test_fail_unless (bitstream_read (&stream, 4) ==
+ beacon->bmis.change_snid.new_snid);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_ENCRYPTION_KEY_CHANGE:
+ test_fail_unless (beacon->bmis.eks.present == true);
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_EKC);
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.eks.kccd);
+ test_fail_unless (bitstream_read (&stream, 1) ==
+ beacon->bmis.eks.kbc);
+ bitstream_skip (&stream, 1);
+ test_fail_unless (bitstream_read (&stream, 4) ==
+ beacon->bmis.eks.new_eks);
+ bitstream_skip (&stream, 4);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_BEACON_RELOCATION:
+ test_fail_unless (beacon->bmis.relocation.present == true);
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_RLO);
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.relocation.rcd);
+ test_fail_unless (bitstream_read (&stream, 1) ==
+ beacon->bmis.relocation.rlt);
+ test_fail_unless (bitstream_read (&stream, 1) ==
+ beacon->bmis.relocation.lgf);
+ test_fail_unless (bitstream_read (&stream, 17) ==
+ beacon->bmis.relocation.rlo);
+ test_fail_unless (bitstream_read (&stream, 3) ==
+ beacon->bmis.relocation.rlslotid);
+ bitstream_skip (&stream, 4);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_AC_LINE_SYNC_COUNTDOWN:
+ test_fail_unless (length == BSU_BEACON_ENTRY_SIZE_ACL);
+ test_fail_unless (beacon->bmis.aclsc.present == true);
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.aclsc.countdown);
+ bitstream_skip (&stream, 2);
+ test_fail_unless (bitstream_read (&stream, 2) ==
+ beacon->bmis.aclsc.reason_code);
+ bitstream_skip (&stream, 6);
+ break;
+ case BSU_BEACON_ENTRY_HEADER_CHANGE_NUMSLOTS:
+ test_fail_unless (length ==
+ BSU_BEACON_ENTRY_SIZE_CHANGE_NUMSLOTS);
+ test_fail_unless (beacon->bmis.cns.present == true);
+ test_fail_unless (bitstream_read (&stream, 6) ==
+ beacon->bmis.cns.nsccd);
+ bitstream_skip (&stream, 2);
+ test_fail_unless (bitstream_read (&stream, 3) ==
+ beacon->bmis.cns.newnumslot);
+ bitstream_skip (&stream, 5);
+ break;
+ default:
+ test_fail_unless (false);
+ }
+ }
+ }
+ test_end;
+}
+
+void
+bsu_beacon_test_beacon_check_read (test_t t, bsu_beacon_t *beacon,
+ bsu_beacon_schedules_t *sched)
+{
+ uint i,j;
+ test_begin (t, "Beacon check read")
+ {
+ /* Only verify the schedules. */
+ test_fail_unless (beacon->bmis.ps.nb == sched->ps.nb);
+ for (i = 0; i < beacon->bmis.ps.nb; i++)
+ {
+ test_fail_unless (beacon->bmis.ps.ps[i].pscd ==
+ sched->ps.ps[i].pscd);
+ test_fail_unless (beacon->bmis.ps.ps[i].cscd ==
+ sched->ps.ps[i].cscd);
+ test_fail_unless (beacon->bmis.ps.ps[i].ns ==
+ sched->ps.ps[i].ns);
+ for (j = 0; j < sched->ps.ps[i].ns; j ++)
+ {
+ test_fail_unless (beacon->bmis.ps.ps[i].sais[j].stpf ==
+ sched->ps.ps[i].sais[j].stpf);
+ test_fail_unless (beacon->bmis.ps.ps[i].sais[j].glid ==
+ sched->ps.ps[i].sais[j].glid);
+ if (sched->ps.ps[i].sais[j].stpf)
+ test_fail_unless (beacon->bmis.ps.ps[i].sais[j].start_time_atu ==
+ sched->ps.ps[i].sais[j].start_time_atu);
+ test_fail_unless (beacon->bmis.ps.ps[i].sais[j].end_time_atu ==
+ sched->ps.ps[i].sais[j].end_time_atu);
+ }
+ }
+ test_fail_unless (beacon->bmis.nps.ns ==
+ sched->nps.ns);
+ for (i = 0; i < beacon->bmis.nps.ns; i++)
+ {
+ test_fail_unless (beacon->bmis.nps.sais[i].stpf ==
+ sched->nps.sais[i].stpf);
+ test_fail_unless (beacon->bmis.nps.sais[i].glid ==
+ sched->nps.sais[i].glid);
+ if (sched->nps.sais[i].stpf)
+ test_fail_unless (beacon->bmis.nps.sais[i].start_time_atu ==
+ sched->nps.sais[i].start_time_atu);
+ test_fail_unless (beacon->bmis.nps.sais[i].end_time_atu ==
+ sched->nps.sais[i].end_time_atu);
+ }
+ }
+ test_end;
+}
diff --git a/cesar/bsu/beacon/test/utest/test.h b/cesar/bsu/beacon/test/utest/test.h
new file mode 100644
index 0000000000..66f7fb658a
--- /dev/null
+++ b/cesar/bsu/beacon/test/utest/test.h
@@ -0,0 +1,78 @@
+#ifndef bsu_beacon_test_utest_test_h
+#define bsu_beacon_test_utest_test_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2010 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bsu/beacon/test/utest/test.h
+ * \brief Tests functions.
+ * \ingroup bsu_beacon
+ */
+#include "bsu/beacon/beacon.h"
+#include "mac/common/pb.h"
+
+BEGIN_DECLS
+
+/**
+ * Fill persistent schedules for the unit tests.
+ * \param ps the persistent schedules.
+ */
+void
+bsu_beacon_test_schedules_persistent (
+ bsu_beacon_bmi_persistent_schedule_t *ps);
+
+/**
+ * Fill non persistent schedules for the unit tests.
+ * \param nps the non persistent schedules.
+ */
+void
+bsu_beacon_test_schedules_non_persistent (
+ bsu_beacon_bmi_non_persistent_schedule_t *nps);
+
+/**
+ * Create a beacon.
+ * \param beacon structure to fill.
+ *
+ * Creates a beacon with 2 regions, 2 non persistent allocations, 2 Persistent
+ * allocations.
+ */
+void
+bsu_beacon_test_create_beacon (bsu_beacon_t *beacon);
+
+/**
+ * Verify the data present in the generated beacon are equal to the one in the
+ * beacon beacon.
+ * \param t test context.
+ * \param mac_config the mac config object.
+ * \param beacon the beacon data beacon.
+ * \param phy_beacon the beacon generated by the beacon.
+ * \param type the beacon type.
+ *
+ * \Warn the TEI in the phy_beacon is compared with the TEI in the mac
+ * config.
+ */
+void
+bsu_beacon_test_beacon_check_generation (test_t t,
+ mac_config_t *mac_config,
+ bsu_beacon_t *beacon,
+ pb_beacon_t *phy_beacon,
+ bsu_beacon_type_t type);
+
+/**
+ * Verify the read data corresponds to the one provided to generate the
+ * beacon.
+ * \param t test context.
+ * \param beacon the bsu data beacon.
+ * \param sched the schedules filled with the data in the real beacon.
+ */
+void
+bsu_beacon_test_beacon_check_read (test_t t, bsu_beacon_t *beacon,
+ bsu_beacon_schedules_t *sched);
+
+END_DECLS
+
+#endif /* bsu_beacon_test_utest_test_h */
diff --git a/cesar/common/tests/tests b/cesar/common/tests/tests
index ea8c31bffc..e30d08e44d 100644
--- a/cesar/common/tests/tests
+++ b/cesar/common/tests/tests
@@ -476,3 +476,7 @@ make
test_general/station/tonemap:
make -f host-Makefile
tone_map_exchange_no_snr: python py/sc01_bl_initial.py --maximus
+
+cesar/beacon/test/utest:
+make COV=y
+cov-target beacon: ./obj/beacon