Commit e4eea33d authored by Robert Schmidt's avatar Robert Schmidt

FlexRAN: Enable MME adding/removing

parent d47c539d
......@@ -125,6 +125,39 @@ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) {
}
}
void flexran_agent_handle_mme_update(mid_t mod_id,
size_t n_mme,
Protocol__FlexS1apMme **mme) {
if (n_mme == 0 || n_mme > 1) {
LOG_E(FLEXRAN_AGENT, "cannot handle %lu MMEs yet\n", n_mme);
return;
}
if (!mme[0]->s1_ip) {
LOG_E(FLEXRAN_AGENT, "no S1 IP present, cannot handle request\n");
return;
}
if (mme[0]->has_state
&& mme[0]->state == PROTOCOL__FLEX_MME_STATE__FLMMES_DISCONNECTED) {
int rc = flexran_remove_s1ap_mme(mod_id, 1, &mme[0]->s1_ip);
if (rc == 0)
LOG_I(FLEXRAN_AGENT, "remove MME at IP %s\n", mme[0]->s1_ip);
else
LOG_W(FLEXRAN_AGENT,
"could not remove MME: flexran_remove_s1ap_mme() returned %d\n",
rc);
} else {
int rc = flexran_add_s1ap_mme(mod_id, 1, &mme[0]->s1_ip);
if (rc == 0)
LOG_I(FLEXRAN_AGENT, "add MME at IP %s\n", mme[0]->s1_ip);
else
LOG_W(FLEXRAN_AGENT,
"could not add MME: flexran_add_s1ap_mme() returned %d\n",
rc);
}
}
int flexran_agent_register_s1ap_xface(mid_t mod_id) {
if (agent_s1ap_xface[mod_id]) {
LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id);
......
......@@ -60,6 +60,11 @@ int flexran_agent_s1ap_stats_reply(mid_t mod_id,
/* Free allocated S1AP stats message */
void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* Add or remove MME updates */
void flexran_agent_handle_mme_update(mid_t mod_id,
size_t n_mme,
Protocol__FlexS1apMme **mme);
/* Register technology specific interface callbacks */
int flexran_agent_register_s1ap_xface(mid_t mod_id);
......
......@@ -893,24 +893,20 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg;
if (enb_config->n_cell_config == 0) {
LOG_W(FLEXRAN_AGENT,
"received enb_config_reply message does not contain a cell_config\n");
*msg = NULL;
return 0;
}
if (enb_config->n_cell_config > 1)
LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n");
if (enb_config->n_cell_config > 0) {
if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) {
prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config);
} else if (enb_config->cell_config[0]->has_eutra_band
}
if (enb_config->cell_config[0]->has_eutra_band
&& enb_config->cell_config[0]->has_dl_freq
&& enb_config->cell_config[0]->has_ul_freq
&& enb_config->cell_config[0]->has_dl_bandwidth) {
initiate_soft_restart(mod_id, enb_config->cell_config[0]);
} else if (flexran_agent_get_rrc_xface(mod_id)
}
if (flexran_agent_get_rrc_xface(mod_id)
&& enb_config->cell_config[0]->has_x2_ho_net_control) {
LOG_I(FLEXRAN_AGENT,
"setting X2 HO NetControl to %d\n",
......@@ -919,6 +915,13 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
if (rc < 0)
LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network");
}
}
if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) {
flexran_agent_handle_mme_update(mod_id,
enb_config->s1ap->n_mme,
enb_config->s1ap->mme);
}
*msg = NULL;
return 0;
......
......@@ -3634,6 +3634,97 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
return 0;
}
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
if (!rrc_is_present(mod_id)) return -2;
/* Reconstruct S1AP_REGISTER_ENB_REQ */
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ);
RCconfig_S1(m, mod_id);
const int CC_id = 0;
eNB_RRC_INST *rrc = RC.rrc[CC_id];
RrcConfigurationReq *conf = &rrc->configuration;
S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn;
for (int i = 0; i < conf->num_plmn; ++i) {
S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i];
S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i];
S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i];
}
/* reconstruct MME list, it might have been updated since initial
* configuration */
S1AP_REGISTER_ENB_REQ(m).nb_mme = 0;
struct s1ap_eNB_mme_data_s *mme = NULL;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4;
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address);
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6;
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address);
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num;
for (int i = 0; i < mme->broadcast_plmn_num; ++i)
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i];
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
}
if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS)
return -1;
for (int i = 0; i < n_mme; ++i) {
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]);
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1;
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0;
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn;
for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i)
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i;
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
}
itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
return 0;
}
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
struct s1ap_eNB_mme_data_s *mme = NULL;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
if (mme->mme_s1_ip.ipv4
&& strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0)
break;
}
if (!mme)
return -2;
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION);
SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id;
itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
switch (mme->state) {
case S1AP_ENB_STATE_WAITING:
s1ap->s1ap_mme_nb -= 1;
if (s1ap->s1ap_mme_pending_nb > 0)
s1ap->s1ap_mme_pending_nb -= 1;
break;
case S1AP_ENB_STATE_CONNECTED:
case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */
s1ap->s1ap_mme_nb -= 1;
s1ap->s1ap_mme_associated_nb -= 1;
break;
case S1AP_ENB_STATE_DISCONNECTED:
default:
break;
}
RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme);
return 0;
}
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){
if (!rrc_is_present(mod_id)) return -1;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
......
......@@ -832,6 +832,12 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
/* Get the S1AP UE conf */
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf);
/* Add MMEs and re-issue S1AP Registration Request */
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4);
/* Remove MMEs and and cut SCTP to MME */
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4);
/********************* general information *****************/
/* get an ID for this BS (or part of a BS) */
uint64_t flexran_get_bs_id(mid_t mod_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment