summaryrefslogtreecommitdiff
path: root/cesar/cp/beacon/src/beacon.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cp/beacon/src/beacon.c')
-rw-r--r--cesar/cp/beacon/src/beacon.c311
1 files changed, 197 insertions, 114 deletions
diff --git a/cesar/cp/beacon/src/beacon.c b/cesar/cp/beacon/src/beacon.c
index 7ee0e6cfaf..b69cf9c83d 100644
--- a/cesar/cp/beacon/src/beacon.c
+++ b/cesar/cp/beacon/src/beacon.c
@@ -611,6 +611,197 @@ cp_beacon_poweron_init (cp_t *ctx)
}
/**
+ * Process the central beacon received.
+ * \param ctx the module context.
+ * \param beacon the beacon to process.
+ * \param net the network associated with the beacon.
+ * \return the station from the sta_mgr if the beacon has been processed.
+ */
+static cp_sta_t*
+cp_beacon_process_beacon_central (
+ cp_t *ctx, bsu_beacon_t *beacon, cp_net_t *net)
+{
+ cp_sta_t *sta = NULL;
+ mac_t cco_mac = beacon->bmis.mac_address.present ?
+ beacon->bmis.mac_address.mac_address : MAC_ZERO;
+ cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (ctx);
+ /* I Should follow instruction from the beacon only if I track it. */
+ if (own->nid_track == beacon->vf.nid
+ && own->tei_track == beacon->vf.stei
+ && beacon->params.rx_parameters.snid
+ == cp_sta_own_data_get_snid (ctx)
+ && own->cco_mac_addr_track == cco_mac)
+ {
+ net->hm = beacon->vf.hm;
+ net->avln_num_slots = beacon->vf.numslots;
+ cp_net_set_access (ctx, net, beacon->params.rx_parameters.access);
+ cp_net_set_slot_id_and_usage (ctx, net, beacon->vf.slotid,
+ beacon->vf.slotusage);
+ sta = cp_beacon_update_sta_peer (ctx, beacon, net);
+ if (beacon->params.frequency_error_valid
+ && ctx->beacon.spoc_update_interval_ms
+ && less_mod2p32 (
+ ctx->beacon.spoc_update_date, phy_date ()))
+ {
+ cp_beacon_clk_sync_call_spoc (
+ ctx, beacon->params.frequency_error);
+ ctx->beacon.spoc_update_date = phy_date ()
+ + MAC_MS_TO_TCK (ctx->beacon.spoc_update_interval_ms);
+ ctx->beacon.spoc_updated = true;
+ CP_TRACE_VERBOSE (SPOC, beacon->params.frequency_error);
+ }
+ /* I'm at least associated. */
+ if (cp_sta_own_data_get_tei (ctx))
+ {
+ /* Update the countdowns. */
+ if (beacon->bmis.change_snid.present)
+ {
+ ctx->beacon.snids.snidcd
+ = beacon->bmis.change_snid.snidccd;
+ ctx->beacon.snids.snid
+ = beacon->bmis.change_snid.new_snid;
+ }
+ if (beacon->bmis.change_hm.present)
+ {
+ ctx->beacon.hm.hmcd =
+ beacon->bmis.change_hm.hmccd;
+ ctx->beacon.hm.hm = beacon->bmis.change_hm.newhm;
+ }
+ if (beacon->bmis.handover.present)
+ {
+ ctx->beacon.hoip.hoipcd =
+ beacon->bmis.handover.hcd;
+ ctx->beacon.hoip.cco = beacon->bmis.handover.tei;
+ }
+ if (beacon->bmis.eks.present)
+ {
+ ctx->beacon.eks.kccd = beacon->bmis.eks.kccd;
+ ctx->beacon.eks.kbc = beacon->bmis.eks.kbc;
+ ctx->beacon.eks.new_eks =
+ beacon->bmis.eks.new_eks;
+ }
+ /** Update the schedules. */
+ cp_beacon_sta_compute_schedules (ctx, beacon);
+ bsu_beacon_bmi_discover_info_t discover;
+ cp_beacon_fill_discover_info (ctx, &discover);
+ bsu_update_discover_info (&discover);
+ /** Program the timer. */
+ cp_beacon_reconfigure_timer (ctx, false);
+ }
+ }
+ /* I'm not associated or the beacon comes from another Network. */
+ else if (!cp_sta_own_data_get_tei (ctx)
+ || (cp_sta_own_data_get_nid (ctx) != beacon->vf.nid
+ || (cp_sta_own_data_get_nid (ctx) == beacon->vf.nid
+ && cp_sta_own_data_get_snid (ctx)
+ != beacon->params.rx_parameters.snid)))
+ {
+ net->hm = beacon->vf.hm;
+ net->avln_num_slots = beacon->vf.numslots;
+ cp_net_set_access (ctx, net, beacon->params.rx_parameters.access);
+ cp_net_set_slot_id_and_usage (ctx, net, beacon->vf.slotid,
+ beacon->vf.slotusage);
+ sta = cp_beacon_update_sta_peer (ctx, beacon, net);
+ }
+ return sta;
+}
+
+/**
+ * Process the discover beacon received.
+ * \param ctx the module context.
+ * \param beacon the beacon to process.
+ * \param net the network associated with the beacon.
+ * \return the station from the sta_mgr if the beacon has been processed.
+ */
+static cp_sta_t*
+cp_beacon_process_beacon_discover (
+ cp_t *ctx, bsu_beacon_t *beacon, cp_net_t *net)
+{
+ mac_t peer_mac = beacon->bmis.mac_address.present ?
+ beacon->bmis.mac_address.mac_address : MAC_ZERO;
+ cp_sta_t *sta = cp_sta_mgr_sta_get_from_mac (ctx, peer_mac);
+ /* The station exists in the station manager. */
+ if (sta && cp_sta_get_tei (sta) == beacon->vf.stei)
+ {
+ sta = cp_beacon_update_sta_peer (ctx, beacon, net);
+ /* Discover beacons from our AVLN. */
+ if (cp_sta_own_data_get_tei (ctx)
+ && cp_sta_mgr_get_our_avln (ctx) == net)
+ {
+ bool updated = bitstream_direct_read (
+ &beacon->bmis.discover_info.info_data, 0, 1);
+ if (updated)
+ {
+ cp_fsm_event_t *event = cp_fsm_event_sta_new (
+ ctx, CP_FSM_EVENT_TYPE_discover_info_updated,
+ net, sta);
+ cp_fsm_post (ctx, event);
+ }
+ }
+ /* This reference is return by the station update peer. */
+ slab_release (sta);
+ }
+ /* Station does not exits, only the station from another AVLN should be
+ * added in the station manager. */
+ else if (beacon->vf.nid != cp_sta_own_data_get_nid (ctx)
+ || (beacon->vf.nid == cp_sta_own_data_get_nid (ctx)
+ && beacon->params.rx_parameters.snid
+ != cp_sta_own_data_get_snid (ctx)))
+ {
+ sta = cp_beacon_update_sta_peer (ctx, beacon, net);
+ /* This reference is return by the station update peer. */
+ slab_release (sta);
+ }
+ return sta;
+}
+
+/**
+ * Process beacons.
+ * \param ctx the module context.
+ * \param beacon the beacon to process.
+ */
+static void
+cp_beacon_process_beacon (cp_t *ctx, bsu_beacon_t *beacon)
+{
+ /** Add network and station info to local data. */
+ cp_net_t *net = cp_sta_mgr_add_avln (
+ ctx, beacon->params.rx_parameters.snid, beacon->vf.nid);
+ /** If no NET object available, do not process this beacon.
+ * This can happen on SNID conflict when some AVLN are powered on at
+ * the time, the SNID conflict will cause the CP to create a net
+ * object for each new tuple of {nid, snid}. STA mgr garbage should
+ * resolve the problem by removing the old AVLN but it takes its
+ * time. */
+ if (net && MAC_TEI_IS_STA (beacon->vf.stei))
+ {
+ cp_sta_t *sta = NULL;
+ if (beacon->vf.bt == BSU_BEACON_TYPE_CENTRAL)
+ sta = cp_beacon_process_beacon_central (ctx, beacon, net);
+ else if (beacon->vf.bt == BSU_BEACON_TYPE_DISCOVER)
+ sta = cp_beacon_process_beacon_discover (ctx, beacon, net);
+ /* Is the SNID in conflict. */
+ if (cp_sta_own_data_get_cco_status (ctx))
+ {
+ cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
+ if (our_net != net
+ && cp_net_get_snid (ctx, our_net)
+ == cp_net_get_snid (ctx, net)
+ && ctx->beacon.snids.snidcd == 0)
+ cp_fsm_post_new_event (ctx, bare, snid_conflict);
+ }
+ /* Raise the event in the FSM for station action. */
+ if (sta
+ && (beacon->vf.bt == BSU_BEACON_TYPE_CENTRAL
+ || beacon->vf.bt == BSU_BEACON_TYPE_PROXY))
+ cp_fsm_post_new_event (
+ ctx, beacon, BEACON, beacon, net, sta);
+ /* Release my reference on the STA. */
+ if (sta)
+ slab_release (sta);
+ }
+}
+
+/**
* Process the first beacon in the received list.
* \param ctx the control plane context.
*/
@@ -618,9 +809,6 @@ void
cp_beacon_get_and_process_beacon (cp_t *ctx)
{
dbg_assert (ctx);
- cp_net_t *net;
- cp_sta_t *sta;
- cp_sta_own_data_t *own;
bsu_beacon_t *beacon;
/** check the countdowns. */
cp_beacon_countdowns (ctx);
@@ -637,117 +825,7 @@ cp_beacon_get_and_process_beacon (cp_t *ctx)
BEACON_BEACON_PROCESS, phy_date(), beacon->vf.nid,
beacon->params.rx_parameters.snid, beacon->vf.stei,
beacon->vf.bt, beacon->params.rx_parameters.bts);
- /** Add network and station info to local data. */
- net = cp_sta_mgr_add_avln (
- ctx, beacon->params.rx_parameters.snid, beacon->vf.nid);
- /** If no NET object available, do not process this beacon.
- * This can happen on SNID conflict when some AVLN are powered on at
- * the time, the SNID conflict will cause the CP to create a net
- * object for each new tuple of {nid, snid}. STA mgr garbage should
- * resolve the problem by removing the old AVLN but it takes its
- * time. */
- if (net)
- {
- net->hm = beacon->vf.hm;
- net->avln_num_slots = beacon->vf.numslots;
- cp_net_set_access (ctx, net, beacon->params.rx_parameters.access);
- cp_net_set_slot_id_and_usage (ctx, net, beacon->vf.slotid,
- beacon->vf.slotusage);
- dbg_assert (beacon->vf.stei == MAC_TEI_UNASSOCIATED
- || MAC_TEI_IS_STA (beacon->vf.stei));
- sta = cp_beacon_update_sta_peer (ctx, beacon, net);
- /** Our station is associated and the beacon is from our CCo. */
- own = cp_sta_mgr_get_sta_own_data (ctx);
- if (beacon->vf.bt == BSU_BEACON_TYPE_CENTRAL
- && beacon->vf.nid == own->nid_track
- && beacon->vf.stei == own->tei_track
- && beacon->params.rx_parameters.snid
- == cp_sta_own_data_get_snid (ctx))
- {
- if (beacon->params.frequency_error_valid
- && ctx->beacon.spoc_update_interval_ms
- && less_mod2p32 (
- ctx->beacon.spoc_update_date, phy_date ()))
- {
- cp_beacon_clk_sync_call_spoc (
- ctx, beacon->params.frequency_error);
- ctx->beacon.spoc_update_date = phy_date ()
- + MAC_MS_TO_TCK (ctx->beacon.spoc_update_interval_ms);
- ctx->beacon.spoc_updated = true;
- CP_TRACE_VERBOSE (SPOC, beacon->params.frequency_error);
- }
- if (cp_sta_own_data_get_tei (ctx))
- {
- /* Update the countdowns. */
- if (beacon->bmis.change_snid.present)
- {
- ctx->beacon.snids.snidcd
- = beacon->bmis.change_snid.snidccd;
- ctx->beacon.snids.snid
- = beacon->bmis.change_snid.new_snid;
- }
- if (beacon->bmis.change_hm.present)
- {
- ctx->beacon.hm.hmcd =
- beacon->bmis.change_hm.hmccd;
- ctx->beacon.hm.hm = beacon->bmis.change_hm.newhm;
- }
- if (beacon->bmis.handover.present)
- {
- ctx->beacon.hoip.hoipcd =
- beacon->bmis.handover.hcd;
- ctx->beacon.hoip.cco = beacon->bmis.handover.tei;
- }
- if (beacon->bmis.eks.present)
- {
- ctx->beacon.eks.kccd = beacon->bmis.eks.kccd;
- ctx->beacon.eks.kbc = beacon->bmis.eks.kbc;
- ctx->beacon.eks.new_eks =
- beacon->bmis.eks.new_eks;
- }
- /** Update the schedules. */
- cp_beacon_sta_compute_schedules (ctx, beacon);
- bsu_beacon_bmi_discover_info_t discover;
- cp_beacon_fill_discover_info (ctx, &discover);
- bsu_update_discover_info (&discover);
- /** Program the timer. */
- cp_beacon_reconfigure_timer (ctx, false);
- }
- }
- /* Discover beacons from our AVLN. */
- else if (cp_sta_own_data_get_tei (ctx)
- && beacon->vf.bt == BSU_BEACON_TYPE_DISCOVER
- && beacon->vf.nid == cp_sta_own_data_get_nid (ctx)
- && beacon->params.rx_parameters.snid
- == cp_sta_own_data_get_snid (ctx))
- {
- bool updated = bitstream_direct_read (
- &beacon->bmis.discover_info.info_data, 0, 1);
- if (updated)
- {
- cp_fsm_event_t *event = cp_fsm_event_sta_new (
- ctx, CP_FSM_EVENT_TYPE_discover_info_updated,
- net, sta);
- cp_fsm_post (ctx, event);
- }
- }
- else if (cp_sta_own_data_get_cco_status (ctx))
- {
- /* Is the SNID in conflict. */
- cp_net_t *our_net = cp_sta_mgr_get_our_avln (ctx);
- if (our_net != net
- && cp_net_get_snid (ctx, our_net)
- == cp_net_get_snid (ctx, net)
- && ctx->beacon.snids.snidcd == 0)
- cp_fsm_post_new_event (ctx, bare, snid_conflict);
- }
- /** Raise the event in the FSM for station action. */
- if (beacon->vf.bt == BSU_BEACON_TYPE_CENTRAL
- || beacon->vf.bt == BSU_BEACON_TYPE_PROXY)
- cp_fsm_post_new_event (
- ctx, beacon, BEACON, beacon, net, sta);
- slab_release (sta);
- }
+ cp_beacon_process_beacon (ctx, beacon);
/** Release the beacon. */
blk_release (beacon);
}
@@ -762,6 +840,10 @@ cp_beacon_process_tracked_avln (cp_t *ctx, bsu_beacon_t *beacon,
dbg_assert (beacon);
dbg_assert (net);
own = cp_sta_mgr_get_sta_own_data (ctx);
+ own->nid_track = beacon->vf.nid;
+ own->tei_track = beacon->vf.stei;
+ own->cco_mac_addr_track = beacon->bmis.mac_address.present ?
+ beacon->bmis.mac_address.mac_address : MAC_ZERO;
own->hybrid_mode = beacon->vf.hm;
/* SPOC. */
ctx->beacon.spoc_update_date = phy_date ();
@@ -785,6 +867,7 @@ cp_beacon_process_untracked_avln (cp_t *ctx)
cp_sta_own_data_t *own = cp_sta_mgr_get_sta_own_data (ctx);
own->nid_track = 0;
own->tei_track = 0;
+ own->cco_mac_addr_track = MAC_ZERO;
/* Reset SPOC. */
ctx->beacon.spoc_updated = false;
cp_beacon_clk_sync_call_spoc (ctx, 0);