/* Cesar project {{{ * * Copyright (C) 2009 Spidcom * * <<>> * * }}} */ /** * \file cp/sta/action/src/vs.c * \brief STA action, VS MMEs req receive/cnf send functions definitions. * \ingroup cp_sta_action */ #include "common/std.h" #include "mac/common/store.h" #include "cp/msg/msg.h" #include "cp/sta/mgr/sta.h" #include "cp/sta/mgr/sta_mgr.h" #include "cp/inc/context.h" #include "mac/common/tonemap.h" #include "cp/sta/action/misc.h" #include "ce/rx/bitloading/nsr.h" #include "mac/sar/sar_pb_stats.h" /** * Handle STARTED => VS_GET_TONEMAP.REQ. * \param ctx control plane context * \param mme received MME handle */ void cp_sta_action_vs__started__vs_get_tonemap_req (cp_t *ctx, cp_mme_rx_t *mme_rx) { dbg_assert (ctx); dbg_assert (mme_rx); u32 beacon_delta = 0; tonemaps_t *tms = NULL; cp_msg_vs_get_tonemap_cnf_result_t result; /* Received data */ mac_t mac_addr; cp_msg_vs_get_tonemap_tmi_t tmi = 0; u8 tm_version; cp_msg_vs_get_tonemap_req_dir_t dir; /* Decode received MME. */ result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE; if (cp_msg_vs_get_tonemap_req_receive (ctx, mme_rx, &mac_addr, &tmi, &tm_version, &dir)) { /* Check Parameters */ cp_sta_t *cp_sta; sta_t *sta; /* Check mac is one of a valid station. */ cp_sta = cp_sta_mgr_sta_get_from_mac (ctx, mac_addr); if (cp_sta) { if (cp_sta_get_authenticated (ctx, cp_sta)) { /* Get sta. */ sta = mac_store_sta_get (ctx->mac_store, cp_sta_get_tei (cp_sta)); if (sta) { /* Get tone maps. */ switch (dir) { case CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_TX: tms = sta->tx_tonemaps; result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_SUCCESS; break; case CP_MSG_VS_GET_TONEMAP_REQ_DIRECTION_RX: tms = sta->rx_tonemaps; result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_SUCCESS; break; default: dbg_assert_default (); } /* Compare interval versions. */ if ((tmi != CP_MSG_VS_GET_TONEMAP_TMI_AND_INT_ONLY) && (tm_version != tms->intervals->version)) { result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_BAD_TMP_INT_LIST_ID; } else { if (!tms) result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE; else { /* Check tmi */ if ((tmi != CP_MSG_VS_GET_TONEMAP_TMI_AND_INT_ONLY) && (!tonemap_get (tms, tmi))) result = CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE; } } blk_release (sta); } } slab_release (cp_sta); } if (result == CP_MSG_VS_GET_TONEMAP_CNF_RESULT_FAILURE) { tmi = 0; tm_version = 0; tms = NULL; } else tm_version = tms->intervals->version; /* Send the MME. */ cp_msg_vs_get_tonemap_cnf_send (ctx, &mme_rx->peer, result, beacon_delta, tm_version, tms, tmi); } } void cp_sta_action_vs__started__vs_get_snr_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); /* Received data */ mac_t mac_addr; cp_msg_vs_get_snr_req_int_t tm_int_i; u8 int_id; u8 carrier_gr; /* Call Receive MME. */ if (cp_msg_vs_get_snr_req_receive (ctx, mme, &mac_addr, &tm_int_i, &int_id, &carrier_gr)) { cp_msg_vs_get_snr_cnf_t data_to_send; data_to_send.result = CP_MSG_VS_GET_SNR_CNF_RESULT_FAILURE; data_to_send.tm_ber = 0; data_to_send.int_id = 0; data_to_send.intervals_nb = 0; data_to_send.intervals = 0; data_to_send.carrier_gr = 0; /* get station and tei from mac */ sta_t *station = NULL; cp_tei_t tei = MAC_TEI_UNASSOCIATED; cp_sta_t *cp_sta = cp_sta_mgr_sta_get_from_mac (ctx, mac_addr); if (cp_sta) { if (cp_sta_get_authenticated (ctx, cp_sta)) { tei = cp_sta_get_tei (cp_sta); station = mac_store_sta_get (ctx->mac_store, tei); data_to_send.result = CP_MSG_VS_GET_SNR_CNF_RESULT_SUCCESS; } slab_release (cp_sta); } if (station) { /* get intervals info struct */ tonemap_intervals_t *intervals; intervals = station->rx_tonemaps->intervals; /* Check version : int_id */ if ((intervals->version != int_id) && (tm_int_i != CP_MSG_VS_GET_SNR_REQ_INT_LIST_ONLY)) { /* in this case return new version and interval list */ tm_int_i = CP_MSG_VS_GET_SNR_REQ_INT_LIST_ONLY; data_to_send.result = CP_MSG_VS_GET_SNR_CNF_RESULT_BAD_TMP_INT_LIST_ID; } data_to_send.int_id = intervals->version; data_to_send.intervals_nb = intervals->intervals_nb; data_to_send.intervals = intervals; data_to_send.carrier_gr = carrier_gr; } /* Fill snr */ uint all_snr_index; uint grp_snr_index; if ((tm_int_i != CP_MSG_VS_GET_SNR_REQ_INT_LIST_ONLY) && (data_to_send.result != CP_MSG_VS_GET_SNR_CNF_RESULT_FAILURE)) { /* Request the snr to the ce */ /* provide: tei, int_id, tm_int_i */ blk_t *cur_blk = ce_rx_get_nsr (ctx->ce_rx, tei, tm_int_i, int_id, &data_to_send.tm_ber); if (!cur_blk) data_to_send.result = CP_MSG_VS_GET_SNR_CNF_RESULT_FAILURE; else { u32 *data = (u32*) cur_blk->data; for (grp_snr_index = 0; grp_snr_index * CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB + carrier_gr < PHY_CARRIER_OFFSET; grp_snr_index++) { data_to_send.snr[grp_snr_index] = 0; } for (all_snr_index = grp_snr_index * CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB + carrier_gr; all_snr_index < PHY_CARRIER_OFFSET + PHY_CARRIER_NB; all_snr_index++) { if (((all_snr_index - PHY_CARRIER_OFFSET) * 4) % BLK_SIZE == 0) { if (all_snr_index > PHY_CARRIER_OFFSET) { cur_blk = cur_blk->next; data = (u32*) cur_blk->data; } } if (all_snr_index % CP_MSG_VS_GET_SNR_REQ_CARRIER_GR_NB == carrier_gr) { data_to_send.snr[grp_snr_index] = (data[(all_snr_index - PHY_CARRIER_OFFSET) % (BLK_SIZE/4)]) / CE_RX_BL_NSR_SOUND_RESCALE; grp_snr_index++; } } for (; grp_snr_index < CP_MSG_SNR_IN_MSG_NB; grp_snr_index++) { data_to_send.snr[grp_snr_index] = 0; } } } if ((tm_int_i == CP_MSG_VS_GET_SNR_REQ_INT_LIST_ONLY) || (data_to_send.result == CP_MSG_VS_GET_SNR_CNF_RESULT_FAILURE)) { /* Set all snr to 0 */ for (grp_snr_index = 0; grp_snr_index < CP_MSG_SNR_IN_MSG_NB; grp_snr_index++) data_to_send.snr[grp_snr_index] = 0; } cp_msg_vs_get_snr_cnf_send (ctx, &(mme->peer), &data_to_send); if (station) blk_release (station); } } /** * Handle STARTED => VS_GET_SPECTRUM.REQ. * \param ctx control plane context * \param mme received MME handle */ void cp_sta_action_vs__started__vs_get_spectrum_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); uint i; /* Received data */ mac_t mac_addr; cp_msg_vs_get_spectrum_req_carrier_gr_t carrier_gr; /* Sent Data */ cp_msg_vs_get_spectrum_cnf_result_t result; u8 AvgAGC; cp_msg_vs_get_spectrum_cnf_spec_t spectrum; cp_msg_vs_get_spectrum_cnf_spec_t spectrum_null; spectrum_null.Imaginary = 0; spectrum_null.Real = 0; /* Call Receive MME. */ bool ok = cp_msg_vs_get_spectrum_req_receive (ctx, mme, &mac_addr, &carrier_gr); /* fill data for sending */ if(ok) { result = CP_MSG_VS_GET_SPECTRUM_CNF_RESULT_SUCCESS; AvgAGC = 0x64; } else { result = CP_MSG_VS_GET_SPECTRUM_CNF_RESULT_FAILURE; AvgAGC = 0; } /* Call Send MME. */ cp_mme_tx_t *reply = cp_msg_vs_get_spectrum_cnf_send_begin (ctx, &mme->peer, result, AvgAGC); for (i = 0; i < 192 ; i++) { spectrum.Imaginary = i; spectrum.Real = i + 1; cp_msg_vs_get_spectrum_cnf_send_spectrum (ctx, reply, result == CP_MSG_VS_GET_SPECTRUM_CNF_RESULT_SUCCESS ? &spectrum : &spectrum_null); } cp_msg_vs_get_spectrum_cnf_send_end (ctx, reply); } /** * Handle STARTED => VS_GET_LINK_STATS.REQ. * \param ctx control plane context * \param mme received MME handle */ void cp_sta_action_vs__started__vs_get_link_stats_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); /* Received data */ cp_msg_vs_get_link_stats_req_t req_data; if (cp_msg_vs_get_link_stats_req_receive (ctx, mme, &req_data)) { /* Received mme is correct and deserves an answer */ u32* pt_bad_crc = NULL; u32 bad_crc = 0; cp_tei_t tei; cp_msg_vs_get_link_stats_cnf_result_t res_type = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS; cp_net_t* our_avln = cp_sta_mgr_get_our_avln (ctx); /* Check network is known */ if (req_data.nid != our_avln->nid) res_type = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE; /* Get tei from mac */ if (res_type == CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS) { cp_sta_t *sta; sta = cp_sta_mgr_sta_get_from_mac (ctx, req_data.dasa); if (sta) { /* The station exists get the TEI */ tei = cp_sta_get_tei (sta); slab_release (sta); } else res_type = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE; } if (res_type == CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS) { /* Get the pointer to the bad crc number */ switch (req_data.TLFlag) { case CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_TX_LINK: { mfs_tx_t *mfs; mfs = mac_store_mfs_get_tx(ctx->mac_store, false, req_data.Mgmt_Flag, req_data.lid, tei); if (!mfs) res_type = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE; else { pt_bad_crc = &mfs->stats.num_bad_pbs_crc; blk_release (mfs); } break; } case CP_MSG_VS_GET_LINK_STATS_REQ_TLFLAG_RX_LINK: { mfs_rx_t *mfs = NULL; mfs = mac_store_mfs_get_rx(ctx->mac_store, false, req_data.Mgmt_Flag, req_data.lid, tei); if (!mfs) res_type = CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_FAILURE; else { pt_bad_crc = &mfs->stats.num_bad_pbs_crc; blk_release (mfs); } break; } default: dbg_assert_default (); break; } } if (res_type == CP_MSG_VS_GET_LINK_STATS_CNF_RESULT_SUCCESS) { dbg_assert (pt_bad_crc); switch (req_data.ReqType) { case CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_RESET_STAT: bad_crc = *pt_bad_crc; *pt_bad_crc = 0; break; case CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_GET_STAT: bad_crc = *pt_bad_crc; break; case CP_MSG_VS_GET_LINK_STATS_REQ_REQTYPE_RESET_STAT: *pt_bad_crc = 0; bad_crc = *pt_bad_crc; break; default: dbg_assert_default (); break; } } cp_msg_vs_get_link_stats_cnf_send (ctx, &mme->peer, req_data.ReqID, res_type, bad_crc); } } /** * Handle STARTED => VS_GET_AMP_MAP.REQ. * \param ctx control plane context * \param mme received MME handle */ void cp_sta_action_vs__started__vs_get_amp_map_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); uint i = 0; uint j = 0; /* Sent Data */ cp_msg_vs_get_amp_map_cnf_result_t result; u16 amlen; bool ok = true; /* fill data for sending */ if(ok) { result = CP_MSG_VS_GET_AMP_MAP_CNF_RESULT_SUCCESS; amlen = 0x1234; } else { result = CP_MSG_VS_GET_AMP_MAP_CNF_RESULT_FAILURE; amlen = 0; } /* Call Send MME. */ cp_mme_tx_t *reply = cp_msg_vs_get_amp_map_cnf_send_begin (ctx, &mme->peer, result, amlen); for (i = 1; i <= 128 ; i++) for (j = 0; j < 12 ; j++) cp_msg_vs_get_amp_map_cnf_send_ampmap (ctx, reply, result == CP_MSG_VS_GET_AMP_MAP_CNF_RESULT_SUCCESS ? j : 0 ); cp_msg_vs_get_amp_map_cnf_send_end (ctx, reply); } /** * Handle STARTED => VS_GET_STATS.REQ. * \param ctx control plane context * \param mme received MME handle */ void cp_sta_action_vs__started__vs_get_stats_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); u8 page; u8 level; if (cp_msg_vs_get_stats_req_receive (ctx, mme, &page, &level)) { cp_mme_tx_t *mme_tx; u8 nb_pages = 0; cp_msg_vs_get_stats_cnf_result_t result = CP_MSG_VS_GET_STATS_CNF_RESULT_FAILURE; mme_tx = cp_msg_vs_get_stats_cnf_send_begin (ctx, &mme->peer); if (level < LIB_STATS_TOTAL) { nb_pages = lib_stats_get_nb_pages (level); if (page < nb_pages) result = CP_MSG_VS_GET_STATS_CNF_RESULT_SUCCESS; } cp_msg_vs_get_stats_cnf_send (ctx, mme_tx, page, nb_pages,level, result); cp_msg_vs_get_stats_cnf_send_end (ctx, mme_tx); } } void cp_sta_action_vs__started__vs_get_ce_stats_req (cp_t *ctx, cp_mme_rx_t *mme) { mac_t mac = MAC_ZERO; sta_t *sta = NULL; tonemask_info_t *ti = NULL; u8 version = 0, result = CP_MSG_VS_GET_CE_STATS_CNF_RESULT_FAILURE; if (cp_msg_vs_get_ce_stats_req_receive (ctx, mme, &mac)) { cp_sta_t *cp_sta = cp_sta_mgr_sta_get_from_mac (ctx, mac); if (cp_sta) { if (cp_sta_get_authenticated (ctx, cp_sta)) { sta = mac_store_sta_get (ctx->mac_store, cp_sta_get_tei (cp_sta)); if (sta) { result = CP_MSG_VS_GET_CE_STATS_CNF_RESULT_SUCCESS; ti = &ctx->mac_config->tonemask_info; } } slab_release (cp_sta); } cp_msg_vs_get_ce_stats_cnf_send (ctx, &mme->peer, version, result, sta, ti); if (sta) blk_release (sta); } } /** * Handle STARTED => IMAC_GET_DISCOVER_LIST.REQ. * \param ctx control plane context * \param mme received MME handle */ void cp_sta_action_vs__started__imac_get_discover_list_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert (ctx); dbg_assert (mme); cp_mme_tx_t *mme_tx; if (cp_msg_imac_get_discover_list_req_receive (ctx, mme)) { u8 num_stations; num_stations = cp_sta_mgr_get_num_discovered_stas (ctx); mme_tx = cp_msg_imac_get_discover_list_cnf_send_begin (ctx, &mme->peer, CP_MSG_IMAC_GET_DISCOVER_LIST_RESULT_SUCCESS, CP_MSG_GET_DISCOVER_LIST_VERSION, num_stations); /* Get stations informations for each existing network */ cp_net_t *net; for (net = cp_sta_mgr_get_first_avln (ctx); net; net = cp_sta_mgr_get_next_avln (ctx, net)) { /* For all kind of association states we seek stations */ cp_net_sta_status_t assoc; for (assoc = 0; assoc < CP_NET_STA_NB; assoc++) { cp_sta_t *cp_sta; for (cp_sta = cp_net_sta_get_first (ctx, net, assoc); cp_sta; cp_sta = cp_net_sta_get_next (ctx, net, cp_sta)) { cp_msg_imac_discover_list_sta_info_t data; cp_tei_t tei = cp_sta_get_tei (cp_sta); data.mac = cp_sta_get_mac_address (cp_sta); data.ble_tx = cp_sta_action_get_average_ble ( ctx, tei, true, false); data.ble_rx = cp_sta_action_get_average_ble ( ctx, tei, false, false); cp_msg_imac_get_discover_list_cnf_send ( ctx, mme_tx, &data); } } } cp_msg_imac_get_discover_list_cnf_send_end (ctx, mme_tx); } } void cp_sta_action_vs__started__vs_get_pb_stats_req (cp_t *ctx, cp_mme_rx_t *mme) { dbg_assert(ctx); cp_tei_t stei_filter = PB_STATS_FILTER_DISABLE; if (cp_msg_vs_get_pb_stats_req_receive (ctx, mme, &stei_filter)) { cp_mme_tx_t *mme_tx; int nb_measures = 0; int index = 0; sar_read_pb_stats_begin (ctx->sar, &index, &nb_measures, (u8) stei_filter); mme_tx = cp_msg_vs_get_pb_stats_cnf_send_begin (ctx, &mme->peer, nb_measures); cp_msg_vs_get_pb_stats_cnf_send_measure (ctx, mme_tx, index, nb_measures); cp_msg_vs_get_pb_stats_cnf_send_end (ctx, mme_tx); sar_read_pb_stats_end (ctx->sar); } }