Add S1AP control module for FlexRAN with status monitoring support

This commit is contained in:
Robert Schmidt
2020-01-20 14:05:05 +01:00
parent 44fdb23f15
commit a87220d376
20 changed files with 573 additions and 30 deletions
+211 -8
View File
@@ -28,6 +28,8 @@
#include <dlfcn.h>
#include "flexran_agent_ran_api.h"
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_management_procedures.h"
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) {
return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id];
@@ -3002,6 +3004,14 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index) {
return ue_context_p->ue_context.e_rab[index].param.gtp_teid;
}
uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti)
{
if (!rrc_is_present(mod_id)) return 0;
struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
if (!ue_context_p) return -1;
return ue_context_p->ue_context.eNB_ue_s1ap_id;
}
/**************************** SLICING ****************************/
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
if (!mac_is_present(mod_id)) return -1;
@@ -3470,6 +3480,195 @@ int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
}
/************************** S1AP **************************/
int flexran_get_s1ap_mme_pending(mid_t mod_id){
if (!rrc_is_present(mod_id)) return -1;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
return s1ap->s1ap_mme_pending_nb;
}
int flexran_get_s1ap_mme_connected(mid_t mod_id){
if (!rrc_is_present(mod_id)) return -1;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
return s1ap->s1ap_mme_associated_nb;
}
char* flexran_get_s1ap_enb_s1_ip(mid_t mod_id){
if (!rrc_is_present(mod_id)) return NULL;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return NULL;
if (s1ap->eNB_s1_ip.ipv4)
return &s1ap->eNB_s1_ip.ipv4_address[0];
if (s1ap->eNB_s1_ip.ipv6)
return &s1ap->eNB_s1_ip.ipv6_address[0];
return NULL;
}
char* flexran_get_s1ap_enb_name(mid_t mod_id){
if (!rrc_is_present(mod_id)) return NULL;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return NULL;
return s1ap->eNB_name;
}
int flexran_get_s1ap_nb_mme(mid_t mod_id) {
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return 0;
struct s1ap_eNB_mme_data_s *mme = NULL;
int count = 0;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
count++;
}
return count;
}
int flexran_get_s1ap_nb_ue(mid_t mod_id) {
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return 0;
struct s1ap_eNB_ue_context_s *ue = NULL;
int count = 0;
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head) {
count++;
}
return count;
}
int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apMme * mme_conf){
if (!rrc_is_present(mod_id)) return -1;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
struct served_gummei_s *gummei_p = NULL;
struct plmn_identity_s *served_plmn_p = NULL;
struct served_group_id_s *group_id_p = NULL;
struct mme_code_s *mme_code_p = NULL;
int i = 0;
Protocol__FlexGummei **served_gummeis;
Protocol__FlexPlmn **requested_plmns;
struct s1ap_eNB_mme_data_s *mme = NULL;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head){
if (mme_index == 0) break;
mme_index--;
}
if (mme_index > 0) return -1;
if (mme->mme_s1_ip.ipv4) {
mme_conf->s1_ip = (char*) &mme->mme_s1_ip.ipv4_address[0];
} else if (mme->mme_s1_ip.ipv6) {
mme_conf->s1_ip = (char*) &mme->mme_s1_ip.ipv6_address[0];
}
mme_conf->name = mme->mme_name;
mme_conf->has_state = 1;
mme_conf->state = mme->state;
mme_conf->n_served_gummeis = 0;
STAILQ_FOREACH(gummei_p, &mme->served_gummei, next) {
mme_conf->n_served_gummeis++;
}
if (mme_conf->n_served_gummeis > 0) {
served_gummeis = calloc(mme_conf->n_served_gummeis, sizeof(Protocol__FlexGummei*));
if(served_gummeis == NULL) return -1;
STAILQ_FOREACH(gummei_p, &mme->served_gummei, next) {
served_plmn_p = STAILQ_FIRST(&gummei_p->served_plmns);
group_id_p = STAILQ_FIRST(&gummei_p->served_group_ids);
mme_code_p = STAILQ_FIRST(&gummei_p->mme_codes);
served_gummeis[i] = malloc(sizeof(Protocol__FlexGummei));
if (!served_gummeis[i]) return -1;
protocol__flex_gummei__init(served_gummeis[i]);
served_gummeis[i]->plmn = malloc(sizeof(Protocol__FlexPlmn));
if (!served_gummeis[i]->plmn) return -1;
protocol__flex_plmn__init(served_gummeis[i]->plmn);
if (served_plmn_p) {
served_gummeis[i]->plmn->has_mcc = 1;
served_gummeis[i]->plmn->mcc = served_plmn_p->mcc;
served_gummeis[i]->plmn->has_mnc = 1;
served_gummeis[i]->plmn->mnc = served_plmn_p->mnc;
served_gummeis[i]->plmn->has_mnc_length = 1;
served_gummeis[i]->plmn->mnc_length = served_plmn_p-> mnc_digit_length;
STAILQ_NEXT(served_plmn_p, next);
}
if (group_id_p) {
served_gummeis[i]->has_mme_group_id = 1;
served_gummeis[i]->mme_group_id = group_id_p->mme_group_id;
STAILQ_NEXT(group_id_p, next);
}
if (mme_code_p){
served_gummeis[i]->has_mme_code = 1;
served_gummeis[i]->mme_code = mme_code_p->mme_code;
STAILQ_NEXT(mme_code_p, next);
}
i++;
}
mme_conf->served_gummeis = served_gummeis;
}
// requested PLMNS
mme_conf->n_requested_plmns = mme->broadcast_plmn_num;
if (mme_conf->n_requested_plmns > 0){
requested_plmns = calloc(mme_conf->n_requested_plmns, sizeof(Protocol__FlexPlmn*));
if(requested_plmns == NULL) return -1;
for(int i = 0; i < mme_conf->n_requested_plmns; i++) {
requested_plmns[i] = malloc(sizeof(Protocol__FlexPlmn));
if (!requested_plmns[i]) return -1;
protocol__flex_plmn__init(requested_plmns[i]);
requested_plmns[i]->mcc = s1ap->mcc[mme->broadcast_plmn_index[i]];
requested_plmns[i]->has_mcc = 1;
requested_plmns[i]->mnc = s1ap->mnc[mme->broadcast_plmn_index[i]];
requested_plmns[i]->has_mnc = 1;
requested_plmns[i]->mnc_length = s1ap->mnc_digit_length[mme->broadcast_plmn_index[i]];
requested_plmns[i]->has_mnc_length = 1;
}
mme_conf->requested_plmns = requested_plmns;
}
mme_conf->has_rel_capacity = 1;
mme_conf->rel_capacity = mme->relative_mme_capacity;
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);
if (!s1ap) return -1;
uint32_t enb_ue_s1ap_id = flexran_get_rrc_enb_ue_s1ap_id(mod_id, rnti);
struct s1ap_eNB_ue_context_s *ue = NULL;
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){
if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break;
}
if (ue == NULL) return -1;
if (ue->mme_ref->mme_s1_ip.ipv4)
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0];
else if (ue->mme_ref->mme_s1_ip.ipv6)
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv6_address[0];
ue_conf->has_enb_ue_s1ap_id = 1;
ue_conf->enb_ue_s1ap_id = ue->eNB_ue_s1ap_id;
ue_conf->has_mme_ue_s1ap_id = 1;
ue_conf->mme_ue_s1ap_id = ue->mme_ue_s1ap_id;
ue_conf->selected_plmn = malloc(sizeof(Protocol__FlexPlmn));
if (!ue_conf->selected_plmn) return -1;
protocol__flex_plmn__init(ue_conf->selected_plmn);
ue_conf->selected_plmn->has_mcc = 1;
ue_conf->selected_plmn->mcc = s1ap->mcc[ue->selected_plmn_identity];
ue_conf->selected_plmn->has_mnc = 1;
ue_conf->selected_plmn->mnc = s1ap->mnc[ue->selected_plmn_identity];
ue_conf->selected_plmn->has_mnc_length = 1;
ue_conf->selected_plmn->mnc_length = s1ap->mnc_digit_length[ue->selected_plmn_identity];
return 0;
}
/**************************** General BS info ****************************/
uint64_t flexran_get_bs_id(mid_t mod_id) {
if (!rrc_is_present(mod_id)) return 0;
@@ -3488,13 +3687,14 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
case ngran_eNB_CU:
case ngran_ng_eNB_CU:
case ngran_gNB_CU:
n_caps = 3;
n_caps = 4;
*caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
n_caps * sizeof(Protocol__FlexBsCapability));
(*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
(*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
(*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
(*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
break;
case ngran_eNB_DU:
case ngran_gNB_DU:
@@ -3511,7 +3711,7 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
case ngran_eNB:
case ngran_ng_eNB:
case ngran_gNB:
n_caps = 8;
n_caps = 9;
*caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
n_caps * sizeof(Protocol__FlexBsCapability));
@@ -3523,26 +3723,27 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
(*caps)[5] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
(*caps)[6] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
(*caps)[7] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
(*caps)[8] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
break;
case ngran_eNB_MBMS_STA:
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
break;
}
return n_caps;
}
uint16_t flexran_get_capabilities_mask(mid_t mod_id) {
uint32_t flexran_get_capabilities_mask(mid_t mod_id) {
if (!rrc_is_present(mod_id)) return 0;
uint16_t mask = 0;
uint32_t mask = 0;
switch (RC.rrc[mod_id]->node_type) {
case ngran_eNB_CU:
case ngran_ng_eNB_CU:
case ngran_gNB_CU:
mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
break;
case ngran_eNB_DU:
case ngran_gNB_DU:
@@ -3562,9 +3763,11 @@ uint16_t flexran_get_capabilities_mask(mid_t mod_id) {
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
break;
case ngran_eNB_MBMS_STA:
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
break;
}