From c619f6eff76234d2efd14d29e99d8132dd768946 Mon Sep 17 00:00:00 2001 From: Robert Schmidt <robert.schmidt@eurecom.fr> Date: Tue, 12 Dec 2017 10:03:06 +0100 Subject: [PATCH] Feature: Provide restart for lte-softmodem - {restart,stop}_L1L2() in lte-softmodem.c - add function start_phy_rrc() in enb_app.{c,h}, accessible from outside - will be used to restart PHY and RRC when lte-softmodem is restarted use only one FlexRAN wait function --- openair2/ENB_APP/enb_app.c | 30 ++-- openair2/ENB_APP/enb_app.h | 7 + .../ENB_APP/flexran_agent_common_internal.c | 28 +++- targets/RT/USER/lte-softmodem.c | 129 +++++++++++++++++- targets/RT/USER/lte-softmodem.h | 3 + 5 files changed, 176 insertions(+), 21 deletions(-) diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 89e20889cb..be0b88acff 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -57,14 +57,13 @@ extern unsigned char NB_eNB_INST; #endif extern volatile int node_control_state; -static void enb_app_wait_reconfig_cmd (void) +void ltesm_wait_reconfig_cmd(void) { - LOG_I(ENB_APP, "ENB APP await reconfiguration command\n"); - - while (node_control_state == ENB_WAIT_RECONFIGURATION_CMD) { + LOG_I(ENB_APP, "LTE Softmodem wait reconfiguration command\n"); + + while (node_control_state == ENB_WAIT_RECONFIGURATION_CMD) { usleep(200000); } - sleep(2); // wait for createing other tasks } #if defined(ENABLE_ITTI) @@ -202,6 +201,15 @@ static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_pro itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); } +void enb_app_start_phy_rrc(uint32_t enb_id_start, uint32_t enb_id_end) +{ + Enb_properties_array_t *enb_properties_p = enb_config_get(); + for (uint32_t enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { + configure_phy(enb_id, enb_properties_p); + configure_rrc(enb_id, enb_properties_p); + } +} + /*------------------------------------------------------------------------------*/ # if defined(ENABLE_USE_MME) static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties) @@ -325,8 +333,10 @@ void *eNB_app_task(void *args_p) for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { flexran_agent_start(enb_id, enb_properties_p); } - // wait for config comd from the controller/network app - enb_app_wait_reconfig_cmd(); + // wait for config comd from the controller/network app plus some time so + // that the other Tasks are in place + ltesm_wait_reconfig_cmd(); + sleep(2); // set again the ran api vars for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { @@ -336,11 +346,7 @@ void *eNB_app_task(void *args_p) #endif - for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { - configure_phy(enb_id, enb_properties_p); - configure_rrc(enb_id, enb_properties_p); - } - + enb_app_start_phy_rrc(enb_id_start, enb_id_end); # if defined(ENABLE_USE_MME) /* Try to register each eNB */ diff --git a/openair2/ENB_APP/enb_app.h b/openair2/ENB_APP/enb_app.h index 8e3c28760b..be5adfbb34 100644 --- a/openair2/ENB_APP/enb_app.h +++ b/openair2/ENB_APP/enb_app.h @@ -30,8 +30,15 @@ #ifndef ENB_APP_H_ #define ENB_APP_H_ +#include <stdint.h> void *eNB_app_task(void *args_p); +/* needed for flexran: start PHY and RRC when restarting */ +void enb_app_start_phy_rrc(uint32_t enb_id_start, uint32_t enb_id_end); + +/* wait that FlexRAN left state ENB_WAIT_RECONFIGURATION_CMD */ +void ltesm_wait_reconfig_cmd(void); + #endif /* ENB_APP_H_ */ diff --git a/openair2/ENB_APP/flexran_agent_common_internal.c b/openair2/ENB_APP/flexran_agent_common_internal.c index e2ee656b23..e77557e9ee 100644 --- a/openair2/ENB_APP/flexran_agent_common_internal.c +++ b/openair2/ENB_APP/flexran_agent_common_internal.c @@ -31,8 +31,33 @@ #include "flexran_agent_common_internal.h" #include "flexran_agent_mac_internal.h" + +/* the following is needed to soft-restart the lte-softmodem */ +#include "targets/RT/USER/lte-softmodem.h" +#include "assertions.h" +#include "enb_app.h" extern volatile int node_control_state; +void handle_reconfiguration(mid_t mod_id) +{ + /* NOTE: this function might be extended by using stop_modem() + * to halt the modem so that it can later be resumed */ + + if (ENB_NORMAL_OPERATION != node_control_state) { + node_control_state = ENB_NORMAL_OPERATION; + } else { + if (stop_L1L2(mod_id) < 0 || restart_L1L2(mod_id) < 0) { + LOG_E(ENB_APP, "could not restart, killing lte-softmodem\n"); + /* shutdown the whole lte-softmodem */ + itti_terminate_tasks(TASK_PHY_ENB); + return; + } + + enb_app_start_phy_rrc(mod_id, mod_id+1); + LOG_I(ENB_APP, "lte-softmodem restart succeeded\n"); + } +} + int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) { yaml_parser_t parser; @@ -72,8 +97,7 @@ int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy if (parse_enb_id(mod_id, &parser) == -1) { goto error; } else { // succeful parse and setting - node_control_state= ENB_NORMAL_OPERATION; - LOG_I(ENB_APP, "Successful parsed config for enb system, entering normal state\n"); + handle_reconfiguration(mod_id); } } else if (strcmp((char *) event.data.scalar.value, "mac") == 0) { LOG_D(ENB_APP, "This is intended for the mac system\n"); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index d36907bba7..b89c82aff4 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1487,18 +1487,128 @@ void fill_PHY_vars_eNB_g(uint8_t abstraction_flag, uint8_t beta_ACK, uint8_t bet } } -/* check the state : either continue or wait for a command to start/stop the eNB - * if needed override the current configuration parameters, such as - * frequencies, bands, power, bandwidth +#if defined(ENABLE_ITTI) && defined(FLEXRAN_AGENT_SB_IF) +/* + * helper function to terminate a certain ITTI task */ -static void ltesm_wait_reconfig_cmd(void) +void terminate_task(task_id_t task_id, mid_t mod_id) { - LOG_I(ENB_APP, "LTE Softmodem wait reconfiguration command\n"); + LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id); + MessageDef *msg; + msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE); + itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); +} + +int stop_L1L2(int enb_id) +{ + int CC_id; + + LOG_W(ENB_APP, "stopping lte-softmodem\n"); + + /* stop trx devices */ + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_stop_func) { + LOG_I(ENB_APP, "stopping PHY_vars_eNB_g[0][%d]->rfdevice (via trx_stop_func())\n", CC_id); + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_stop_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + } + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_stop_func) { + LOG_I(ENB_APP, "stopping PHY_vars_eNB_g[0][%d]->ifdevice (via trx_stop_func())\n", CC_id); + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_stop_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } + } + + /* these tasks need to pick up new configuration */ + terminate_task(TASK_RRC_ENB, enb_id); + terminate_task(TASK_L2L1, enb_id); + oai_exit = 1; + LOG_W(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id); + kill_eNB_proc(enb_id); + /* give some time for all threads */ + sleep(1); + return 0; +} + +/* + * Restart the lte-softmodem. + * This function checks whether we are in ENB_NORMAL_OPERATION (defined by + * FlexRAN). If yes, first stop L1/L2/L3, then resume. + */ +int restart_L1L2(int enb_id) +{ + int i, aa, CC_id; + /* needed for fill_PHY_vars_eNB_g(), defined locally in main(); + * abstraction flag is needed too, but defined both globally and in main () */ + uint8_t beta_ACK = 0, beta_RI = 0, beta_CQI = 2; + /* needed for macphy_init() */ + int eMBMS_active = 0; + + LOG_W(ENB_APP, "restarting lte-softmodem\n"); + + /* block threads */ + sync_var = -1; + oai_exit = 0; + + reconfigure_enb_params(enb_id); /* set frame parameters from configuration */ + + /* PHY_vars_eNB_g will be filled by init_lte_eNB(), so free and + * let the data structure be filled again */ + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + free(PHY_vars_eNB_g[0][CC_id]); + fill_PHY_vars_eNB_g(abstraction_flag, beta_ACK, beta_RI, beta_CQI); + } + + dump_frame_parms(frame_parms[0]); + init_openair0(); + + /* give MAC interface current cell information, the rest is the same. + * For more info, check l2_init(). Then, initialize it (cf. line 1904). */ + mac_xface->frame_parms = frame_parms[0]; + mac_xface->macphy_init(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,0,0); + + LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); + if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { + LOG_E(RRC, "Create task for RRC eNB failed\n"); + return -1; + } else { + LOG_I(RRC, "Re-created task for RRC eNB successfully\n"); + } + if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { + LOG_E(PDCP, "Create task for L2L1 failed\n"); + return -1; + } else { + LOG_I(PDCP, "Re-created task for L2L1 successfully\n"); + } + + /* TODO XForms here */ - while (node_control_state == ENB_WAIT_RECONFIGURATION_CMD) { - usleep(200000); + printf("Initializing eNB threads\n"); + init_eNB(node_function, node_timing, 1, eth_params, single_thread_flag, wait_for_sync); + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_eNB_g[0][CC_id]->rf_map.card=0; + PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; } + + mlockall(MCL_CURRENT | MCL_FUTURE); + + printf("Setting eNB buffer to all-RX\n"); + // Set LSBs for antenna switch (ExpressMIMO) + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0; + for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++) + for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++) + PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; + } + + printf("Sending sync to all threads\n"); + + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + + return 0; } +#endif int main( int argc, char **argv ) { int i,aa; @@ -1689,7 +1799,12 @@ int main( int argc, char **argv ) { } create_enb_app_task(UE_flag ? 0 : 1); + +#ifdef FLEXRAN_AGENT_SB_IF + /* wait command for flexran agent: only start when configuration received */ ltesm_wait_reconfig_cmd (); +#endif + // reconfigure_enb: 0 for wait, 1 for skip, and other values to reconfigure for (i=0; (i < NB_eNB_INST && node_control_state == ENB_NORMAL_OPERATION ) ; i++){ reconfigure_enb_params(i); diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 4d9d145c68..a0883c3d59 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -89,4 +89,7 @@ extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *); extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *); +extern int stop_L1L2(int enb_id); +extern int restart_L1L2(int enb_id); + #endif -- 2.26.2