Commit a87220d3 authored by Robert Schmidt's avatar Robert Schmidt

Add S1AP control module for FlexRAN with status monitoring support

parent 44fdb23f
...@@ -923,6 +923,7 @@ include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY") ...@@ -923,6 +923,7 @@ include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY")
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC") include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC")
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC") include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC")
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP") include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP")
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/S1AP")
include_directories("${OPENAIR2_DIR}/UTIL/OSA") include_directories("${OPENAIR2_DIR}/UTIL/OSA")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc") include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc") include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
...@@ -1016,6 +1017,7 @@ add_library(FLEXRAN_AGENT ...@@ -1016,6 +1017,7 @@ add_library(FLEXRAN_AGENT
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP/flexran_agent_pdcp.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP/flexran_agent_pdcp.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_net_comm.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent_net_comm.c
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file flexran_agent_s1ap.c
* \brief FlexRAN agent Control Module S1AP
* \author Navid Nikaein
* \date 2019
* \version 0.1
*/
#include "flexran_agent_s1ap.h"
/*Array containing the Agent-S1AP interfaces*/
AGENT_S1AP_xface *agent_s1ap_xface[NUM_MAX_ENB];
void flexran_agent_fill_s1ap_cell_config(mid_t mod_id,
Protocol__FlexS1apConfig **s1ap_config) {
*s1ap_config = malloc(sizeof(Protocol__FlexS1apConfig));
if (!*s1ap_config) return;
protocol__flex_s1ap_config__init(*s1ap_config);
LOG_D(FLEXRAN_AGENT, "flexran_agent_fill_s1ap_cell_config %d\n", mod_id);
// S1AP status
(*s1ap_config)->has_pending = 1;
(*s1ap_config)->pending = flexran_get_s1ap_mme_pending(mod_id);
(*s1ap_config)->has_connected = 1;
(*s1ap_config)->connected = flexran_get_s1ap_mme_connected(mod_id);
(*s1ap_config)->enb_s1_ip = flexran_get_s1ap_enb_s1_ip(mod_id);
if (!(*s1ap_config)->enb_s1_ip)
(*s1ap_config)->enb_s1_ip = "";
(*s1ap_config)->enb_name = flexran_get_s1ap_enb_name(mod_id);
(*s1ap_config)->mme = NULL;
(*s1ap_config)->n_mme = flexran_get_s1ap_nb_mme(mod_id);
if ((*s1ap_config)->n_mme > 0) {
Protocol__FlexS1apMme **mme_conf = calloc((*s1ap_config)->n_mme,
sizeof(Protocol__FlexS1apMme *));
AssertFatal(mme_conf, "%s(): MME malloc failed\n", __func__);
for(int i = 0; i < (*s1ap_config)->n_mme; i++){
mme_conf[i] = malloc(sizeof(Protocol__FlexS1apMme));
AssertFatal(mme_conf[i], "%s(): MME malloc failed\n", __func__);
protocol__flex_s1ap_mme__init(mme_conf[i]);
if (flexran_get_s1ap_mme_conf(mod_id, i, mme_conf[i]) < 0) {
LOG_E(FLEXRAN_AGENT,
"error in flexran_get_s1ap_mme_conf(): cannot retrieve MME state\n");
(*s1ap_config)->n_mme = 0;
break;
}
}
(*s1ap_config)->mme = mme_conf;
}
}
int flexran_agent_s1ap_stats_reply(mid_t mod_id,
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags) {
if (n_ue <= 0)
return 0;
if (!(ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_S1AP_STATS))
return 0;
for (int i = 0; i < n_ue; i++) {
const rnti_t rnti = ue_report[i]->rnti;
Protocol__FlexS1apUe *ue = malloc(sizeof(Protocol__FlexS1apUe));
AssertFatal(ue, "%s(): MME malloc failed\n", __func__);
protocol__flex_s1ap_ue__init(ue);
if (flexran_get_s1ap_ue(mod_id, rnti, ue) < 0) {
LOG_E(FLEXRAN_AGENT, "error in %s(): cannot retrieve UE conf\n", __func__);
break;
}
ue_report[i]->s1ap_stats = ue;
ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_S1AP_STATS;
}
return 0;
}
void flexran_agent_free_s1ap_cell_config(Protocol__FlexS1apConfig **s1ap) {
for (int i = 0; i < (*s1ap)->n_mme; i++) {
/* following structures allocated in the RAN API */
for(int j = 0; j < (*s1ap)->mme[i]->n_served_gummeis; j++) {
free((*s1ap)->mme[i]->served_gummeis[j]->plmn);
free((*s1ap)->mme[i]->served_gummeis[j]);
}
free((*s1ap)->mme[i]->served_gummeis);
for (int j = 0; j < (*s1ap)->mme[i]->n_requested_plmns; j++)
free((*s1ap)->mme[i]->requested_plmns[j]);
free((*s1ap)->mme[i]->requested_plmns);
free((*s1ap)->mme[i]);
}
free((*s1ap)->mme);
free(*s1ap);
*s1ap = NULL;
}
void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) {
for (int i = 0; i < reply->n_ue_report; ++i) {
if (!reply->ue_report[i]->s1ap_stats)
continue;
free(reply->ue_report[i]->s1ap_stats->selected_plmn);
free(reply->ue_report[i]->s1ap_stats);
reply->ue_report[i]->s1ap_stats = NULL;
}
}
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);
return -1;
}
AGENT_S1AP_xface *xface = malloc(sizeof(AGENT_S1AP_xface));
if (!xface) {
LOG_E(FLEXRAN_AGENT, "could not allocate memory for S1AP agent xface %d\n", mod_id);
return -1;
}
// not implemented yet
xface->flexran_s1ap_notify_release_request=NULL;
agent_s1ap_xface[mod_id] = xface;
return 0;
}
int flexran_agent_unregister_s1ap_xface(mid_t mod_id) {
if (!agent_s1ap_xface[mod_id]) {
LOG_E(FLEXRAN_AGENT, "S1AP agent for eNB %d is not registered\n", mod_id);
return -1;
}
agent_s1ap_xface[mod_id]->flexran_s1ap_notify_release_request=NULL;
free(agent_s1ap_xface[mod_id]);
agent_s1ap_xface[mod_id] = NULL;
return 0;
}
AGENT_S1AP_xface *flexran_agent_get_s1ap_xface(mid_t mod_id) {
return agent_s1ap_xface[mod_id];
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file flexran_agent_s1ap.h
* \brief FlexRAN agent S1AP Control Module
* \author navid nikaein
* \date 2017
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_S1AP_H_
#define FLEXRAN_AGENT_S1AP_H_
#include "header.pb-c.h"
#include "flexran.pb-c.h"
#include "stats_messages.pb-c.h"
#include "stats_common.pb-c.h"
#include "flexran_agent_common.h"
#include "flexran_agent_defs.h"
#include "flexran_agent_s1ap_defs.h"
#include "flexran_agent_ran_api.h"
/***************************************
* FlexRAN agent - technology S1AP API *
***************************************/
/* Send to the controller all the S1AP configs */
void flexran_agent_fill_s1ap_cell_config(mid_t mod_id,
Protocol__FlexS1apConfig **s1ap_config);
/* Free allocated S1AP cell configs */
void flexran_agent_free_s1ap_cell_config(Protocol__FlexS1apConfig **s1ap);
/* Fill the stats message for S1AP */
int flexran_agent_s1ap_stats_reply(mid_t mod_id,
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags);
/* Free allocated S1AP stats message */
void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* Register technology specific interface callbacks */
int flexran_agent_register_s1ap_xface(mid_t mod_id);
/* Unregister technology specific callbacks */
int flexran_agent_unregister_s1ap_xface(mid_t mod_id);
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef __FLEXRAN_AGENT_S1AP_PRIMITIVES_H__
#define __FLEXRAN_AGENT_S1AP_PRIMITIVES_H__
#include "flexran_agent_defs.h"
/* FLEXRAN AGENT-S1AP Interface */
typedef struct {
// S1AP statistics
void (*flexran_s1ap_notify_release_request)(mid_t mod_id);
} AGENT_S1AP_xface;
#endif
...@@ -355,13 +355,6 @@ message flex_s1ap_mme { ...@@ -355,13 +355,6 @@ message flex_s1ap_mme {
optional uint32 rel_capacity = 6; // Relative MME capacity, TS23.401 optional uint32 rel_capacity = 6; // Relative MME capacity, TS23.401
} }
message flex_s1ap_ue {
optional string mme_s1_ip = 1; // IP of MME to which UE is connected
optional uint32 enb_ue_s1ap_id = 2; // S1AP ID on eNodeB side for UE
optional uint32 mme_ue_s1ap_id = 3; // S1AP ID on MME side for UE
optional flex_plmn selected_plmn = 4; // UE-selected PLMN in RRC Conn Setup Cplt
}
enum flex_mme_state { enum flex_mme_state {
FLMMES_DISCONNECTED = 0; FLMMES_DISCONNECTED = 0;
FLMMES_WAITING = 1; FLMMES_WAITING = 1;
......
...@@ -100,7 +100,6 @@ message flex_ue_config { ...@@ -100,7 +100,6 @@ message flex_ue_config {
optional uint32 ul_slice_id = 32; optional uint32 ul_slice_id = 32;
// Configuration about RRC measurements // Configuration about RRC measurements
optional flex_measurement_info info = 33; optional flex_measurement_info info = 33;
optional uint32 enb_ue_s1ap_id = 34; // S1AP ID on eNodeB side
} }
message flex_lc_ue_config { message flex_lc_ue_config {
...@@ -109,10 +108,9 @@ message flex_lc_ue_config { ...@@ -109,10 +108,9 @@ message flex_lc_ue_config {
} }
message flex_s1ap_config { message flex_s1ap_config {
optional uint32 pending = 1; // number of pending (to be connected) MMEs optional uint32 pending = 1; // number of pending (to be connected) MMEs
optional uint32 connected = 2; // number of connected MMEs optional uint32 connected = 2; // number of connected MMEs
optional string enb_s1_ip = 3; // S1-MME IP of eNodeB optional string enb_s1_ip = 3; // S1-MME IP of eNodeB
optional string enb_name = 4; // S1-MME name of eNodeB optional string enb_name = 4; // S1-MME name of eNodeB
repeated flex_s1ap_mme mme = 5; repeated flex_s1ap_mme mme = 5;
repeated flex_s1ap_ue ue = 6;
} }
...@@ -75,6 +75,7 @@ enum flex_bs_capability { ...@@ -75,6 +75,7 @@ enum flex_bs_capability {
PDCP = 5; PDCP = 5;
SDAP = 6; SDAP = 6;
RRC = 7; RRC = 7;
S1AP = 8;
} }
enum flex_bs_split { enum flex_bs_split {
......
...@@ -310,3 +310,15 @@ message flex_gtp_stats { ...@@ -310,3 +310,15 @@ message flex_gtp_stats {
optional uint32 teid_sgw = 4; optional uint32 teid_sgw = 4;
optional string addr_sgw = 5; optional string addr_sgw = 5;
} }
//
// S1AP stats
//
message flex_s1ap_ue {
optional string mme_s1_ip = 1; // IP of MME to which UE is connected
optional uint32 enb_ue_s1ap_id = 2; // S1AP ID on eNodeB side for UE
optional uint32 mme_ue_s1ap_id = 3; // S1AP ID on MME side for UE
optional flex_plmn selected_plmn = 4; // UE-selected PLMN in RRC Conn Setup Cplt
}
...@@ -51,6 +51,7 @@ message flex_ue_stats_report { ...@@ -51,6 +51,7 @@ message flex_ue_stats_report {
optional flex_pdcp_stats pdcp_stats = 11; optional flex_pdcp_stats pdcp_stats = 11;
optional flex_mac_stats mac_stats = 12; optional flex_mac_stats mac_stats = 12;
repeated flex_gtp_stats gtp_stats = 13; repeated flex_gtp_stats gtp_stats = 13;
optional flex_s1ap_ue s1ap_stats = 14;
} }
// //
...@@ -91,6 +92,7 @@ enum flex_ue_stats_type { ...@@ -91,6 +92,7 @@ enum flex_ue_stats_type {
FLUST_PDCP_STATS = 1024; FLUST_PDCP_STATS = 1024;
FLUST_GTP_STATS = 2048; FLUST_GTP_STATS = 2048;
FLUST_S1AP_STATS = 4096;
FLUST_RRC_MEASUREMENTS = 65536; FLUST_RRC_MEASUREMENTS = 65536;
// To be extended with more types of stats // To be extended with more types of stats
......
...@@ -177,8 +177,8 @@ int flexran_agent_start(mid_t mod_id) ...@@ -177,8 +177,8 @@ int flexran_agent_start(mid_t mod_id)
/* Register and initialize the control modules depending on capabilities. /* Register and initialize the control modules depending on capabilities.
* After registering, calling flexran_agent_get_*_xface() tells whether a * After registering, calling flexran_agent_get_*_xface() tells whether a
* control module is operational */ * control module is operational */
uint16_t caps = flexran_get_capabilities_mask(mod_id); uint32_t caps = flexran_get_capabilities_mask(mod_id);
LOG_I(FLEXRAN_AGENT, "Agent handles BS ID %ld, capabilities=0x%x => handling%s%s%s%s%s%s%s%s\n", LOG_I(FLEXRAN_AGENT, "Agent handles BS ID %ld, capabilities=0x%x => handling%s%s%s%s%s%s%s%s%s\n",
flexran_get_bs_id(mod_id), caps, flexran_get_bs_id(mod_id), caps,
FLEXRAN_CAP_LOPHY(caps) ? " LOPHY" : "", FLEXRAN_CAP_LOPHY(caps) ? " LOPHY" : "",
FLEXRAN_CAP_HIPHY(caps) ? " HIPHY" : "", FLEXRAN_CAP_HIPHY(caps) ? " HIPHY" : "",
...@@ -187,7 +187,8 @@ int flexran_agent_start(mid_t mod_id) ...@@ -187,7 +187,8 @@ int flexran_agent_start(mid_t mod_id)
FLEXRAN_CAP_RLC(caps) ? " RLC" : "", FLEXRAN_CAP_RLC(caps) ? " RLC" : "",
FLEXRAN_CAP_PDCP(caps) ? " PDCP" : "", FLEXRAN_CAP_PDCP(caps) ? " PDCP" : "",
FLEXRAN_CAP_SDAP(caps) ? " SDAP" : "", FLEXRAN_CAP_SDAP(caps) ? " SDAP" : "",
FLEXRAN_CAP_RRC(caps) ? " RRC" : ""); FLEXRAN_CAP_RRC(caps) ? " RRC" : "",
FLEXRAN_CAP_S1AP(caps) ? " S1AP" : "");
if (FLEXRAN_CAP_LOPHY(caps) || FLEXRAN_CAP_HIPHY(caps)) { if (FLEXRAN_CAP_LOPHY(caps) || FLEXRAN_CAP_HIPHY(caps)) {
flexran_agent_register_phy_xface(mod_id); flexran_agent_register_phy_xface(mod_id);
...@@ -210,6 +211,11 @@ int flexran_agent_start(mid_t mod_id) ...@@ -210,6 +211,11 @@ int flexran_agent_start(mid_t mod_id)
LOG_I(FLEXRAN_AGENT, "registered PDCP interface/CM for eNB %d\n", mod_id); LOG_I(FLEXRAN_AGENT, "registered PDCP interface/CM for eNB %d\n", mod_id);
} }
if (FLEXRAN_CAP_S1AP(caps)) {
flexran_agent_register_s1ap_xface(mod_id);
LOG_I(FLEXRAN_AGENT, "registered S1AP interface/CM for eNB %d\n", mod_id);
}
/* /*
* initilize a timer * initilize a timer
*/ */
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "flexran_agent_mac.h" #include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h" #include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h" #include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "assertions.h" #include "assertions.h"
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
/*! \file flexran_agent_common.c /*! \file flexran_agent_common.c
* \brief common primitives for all agents * \brief common primitives for all agents
* \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein, shahab SHARIAT BAGHERI * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
* \date 2017 * \date 2017
* \version 0.1 * \version 0.1
*/ */
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "flexran_agent_phy.h" #include "flexran_agent_phy.h"
#include "flexran_agent_mac.h" #include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h" #include "flexran_agent_rrc.h"
#include "flexran_agent_s1ap.h"
//#include "PHY/extern.h" //#include "PHY/extern.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_internal.h"
...@@ -339,6 +340,9 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { ...@@ -339,6 +340,9 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
free(reply->cell_config[i]); free(reply->cell_config[i]);
} }
if (reply->s1ap)
flexran_agent_free_s1ap_cell_config(&reply->s1ap);
free(reply->cell_config); free(reply->cell_config);
free(reply); free(reply);
...@@ -757,9 +761,12 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F ...@@ -757,9 +761,12 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F
cell_conf[i]->carrier_index = i; cell_conf[i]->carrier_index = i;
cell_conf[i]->has_carrier_index = 1; cell_conf[i]->has_carrier_index = 1;
} }
enb_config_reply_msg->cell_config=cell_conf; enb_config_reply_msg->cell_config=cell_conf;
} }
if (flexran_agent_get_s1ap_xface(mod_id))
flexran_agent_fill_s1ap_cell_config(mod_id, &enb_config_reply_msg->s1ap);
*msg = malloc(sizeof(Protocol__FlexranMessage)); *msg = malloc(sizeof(Protocol__FlexranMessage));
......
...@@ -116,6 +116,7 @@ typedef int32_t err_code_t; ...@@ -116,6 +116,7 @@ typedef int32_t err_code_t;
#define FLEXRAN_CAP_PDCP(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)) > 0) #define FLEXRAN_CAP_PDCP(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)) > 0)
#define FLEXRAN_CAP_SDAP(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)) > 0) #define FLEXRAN_CAP_SDAP(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)) > 0)
#define FLEXRAN_CAP_RRC(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)) > 0) #define FLEXRAN_CAP_RRC(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)) > 0)
#define FLEXRAN_CAP_S1AP(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP)) > 0)
typedef enum { typedef enum {
ENB_NORMAL_OPERATION = 0x0, ENB_NORMAL_OPERATION = 0x0,
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "flexran_agent_mac_defs.h" #include "flexran_agent_mac_defs.h"
#include "flexran_agent_rrc_defs.h" #include "flexran_agent_rrc_defs.h"
#include "flexran_agent_pdcp_defs.h" #include "flexran_agent_pdcp_defs.h"
#include "flexran_agent_s1ap_defs.h"
/* Control module interface for the communication of the PHY control module with the agent */ /* Control module interface for the communication of the PHY control module with the agent */
AGENT_PHY_xface *flexran_agent_get_phy_xface(mid_t mod_id); AGENT_PHY_xface *flexran_agent_get_phy_xface(mid_t mod_id);
...@@ -48,6 +49,9 @@ AGENT_RRC_xface *flexran_agent_get_rrc_xface(mid_t mod_id); ...@@ -48,6 +49,9 @@ AGENT_RRC_xface *flexran_agent_get_rrc_xface(mid_t mod_id);
/* Control module interface for the communication of the RRC Control Module with the agent */ /* Control module interface for the communication of the RRC Control Module with the agent */
AGENT_PDCP_xface *flexran_agent_get_pdcp_xface(mid_t mod_id); AGENT_PDCP_xface *flexran_agent_get_pdcp_xface(mid_t mod_id);
/* Control module interface for the communication of the S1AP Control Module with the agent */
AGENT_S1AP_xface *flexran_agent_get_s1ap_xface(mid_t mod_id);
/* Requried to know which UEs had a harq updated over some subframe */ /* Requried to know which UEs had a harq updated over some subframe */
extern int harq_pid_updated[NUM_MAX_UE][8]; extern int harq_pid_updated[NUM_MAX_UE][8];
extern int harq_pid_round[NUM_MAX_UE][8]; extern int harq_pid_round[NUM_MAX_UE][8];
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "flexran_agent_mac.h" #include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h" #include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h" #include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "flexran_agent_timer.h" #include "flexran_agent_timer.h"
#include "flexran_agent_ran_api.h" #include "flexran_agent_ran_api.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
...@@ -324,6 +325,14 @@ int flexran_agent_stats_reply(mid_t enb_id, ...@@ -324,6 +325,14 @@ int flexran_agent_stats_reply(mid_t enb_id,
goto error; goto error;
} }
/* S1AP statistics, depends on RRC to find S1AP ID */
if (flexran_agent_get_rrc_xface(enb_id)
&& flexran_agent_get_s1ap_xface(enb_id)
&& flexran_agent_s1ap_stats_reply(enb_id, ue_report, n_ue, ue_flags) < 0) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
goto error;
}
if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0) { if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0) {
goto error; goto error;
} }
...@@ -523,6 +532,8 @@ int flexran_agent_destroy_stats_reply(Protocol__FlexranMessage *msg) ...@@ -523,6 +532,8 @@ int flexran_agent_destroy_stats_reply(Protocol__FlexranMessage *msg)
flexran_agent_mac_destroy_stats_reply(msg->stats_reply_msg); flexran_agent_mac_destroy_stats_reply(msg->stats_reply_msg);
flexran_agent_rrc_destroy_stats_reply(msg->stats_reply_msg); flexran_agent_rrc_destroy_stats_reply(msg->stats_reply_msg);
flexran_agent_pdcp_destroy_stats_reply(msg->stats_reply_msg); flexran_agent_pdcp_destroy_stats_reply(msg->stats_reply_msg);
flexran_agent_rrc_gtp_destroy_stats_reply(msg->stats_reply_msg);
flexran_agent_s1ap_destroy_stats_reply(msg->stats_reply_msg);
for (int i = 0; i < msg->stats_reply_msg->n_cell_report; ++i) for (int i = 0; i < msg->stats_reply_msg->n_cell_report; ++i)
free(msg->stats_reply_msg->cell_report[i]); free(msg->stats_reply_msg->cell_report[i]);
for (int i = 0; i < msg->stats_reply_msg->n_ue_report; ++i) for (int i = 0; i < msg->stats_reply_msg->n_ue_report; ++i)
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <dlfcn.h> #include <dlfcn.h>
#include "flexran_agent_ran_api.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) { 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]; 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) { ...@@ -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; 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 ****************************/ /**************************** SLICING ****************************/
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
if (!mac_is_present(mod_id)) return -1; 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) { ...@@ -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; 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 ****************************/ /**************************** General BS info ****************************/
uint64_t flexran_get_bs_id(mid_t mod_id) { uint64_t flexran_get_bs_id(mid_t mod_id) {
if (!rrc_is_present(mod_id)) return 0; if (!rrc_is_present(mod_id)) return 0;
...@@ -3488,13 +3687,14 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps) ...@@ -3488,13 +3687,14 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
case ngran_eNB_CU: case ngran_eNB_CU:
case ngran_ng_eNB_CU: case ngran_ng_eNB_CU:
case ngran_gNB_CU: case ngran_gNB_CU:
n_caps = 3; n_caps = 4;
*caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability)); *caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n", AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
n_caps * sizeof(Protocol__FlexBsCapability)); n_caps * sizeof(Protocol__FlexBsCapability));
(*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP; (*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
(*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP; (*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
(*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__RRC; (*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
(*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
break; break;
case ngran_eNB_DU: case ngran_eNB_DU:
case ngran_gNB_DU: case ngran_gNB_DU:
...@@ -3511,7 +3711,7 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps) ...@@ -3511,7 +3711,7 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
case ngran_eNB: case ngran_eNB:
case ngran_ng_eNB: case ngran_ng_eNB:
case ngran_gNB: case ngran_gNB:
n_caps = 8; n_caps = 9;
*caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability)); *caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n", AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
n_caps * sizeof(Protocol__FlexBsCapability)); n_caps * sizeof(Protocol__FlexBsCapability));
...@@ -3523,26 +3723,27 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps) ...@@ -3523,26 +3723,27 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
(*caps)[5] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP; (*caps)[5] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
(*caps)[6] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP; (*caps)[6] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
(*caps)[7] = PROTOCOL__FLEX_BS_CAPABILITY__RRC; (*caps)[7] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
(*caps)[8] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
break; break;
case ngran_eNB_MBMS_STA: case ngran_eNB_MBMS_STA:
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
break; break;
} }
return n_caps; 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; if (!rrc_is_present(mod_id)) return 0;
uint32_t mask = 0;
uint16_t mask = 0;
switch (RC.rrc[mod_id]->node_type) { switch (RC.rrc[mod_id]->node_type) {
case ngran_eNB_CU: case ngran_eNB_CU:
case ngran_ng_eNB_CU: case ngran_ng_eNB_CU:
case ngran_gNB_CU: case ngran_gNB_CU:
mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP) mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP) | (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; break;
case ngran_eNB_DU: case ngran_eNB_DU:
case ngran_gNB_DU: case ngran_gNB_DU:
...@@ -3562,9 +3763,11 @@ uint16_t flexran_get_capabilities_mask(mid_t mod_id) { ...@@ -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__RLC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP) | (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP) | (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; break;
case ngran_eNB_MBMS_STA: case ngran_eNB_MBMS_STA:
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
break; break;
} }
......
...@@ -652,6 +652,9 @@ int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index); ...@@ -652,6 +652,9 @@ int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index);
/* Get the TEID at the SGW for UE */ /* Get the TEID at the SGW for UE */
int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index); int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index);
/* gets the UEs S1AP ID at eNodeB, stored in RRC */
uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti);
/************************** Slice configuration **************************/ /************************** Slice configuration **************************/
/* Get the DL slice ID for a UE */ /* Get the DL slice ID for a UE */
...@@ -804,6 +807,31 @@ char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx); ...@@ -804,6 +807,31 @@ char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx);
/* Set the scheduler name for a slice in UL */ /* Set the scheduler name for a slice in UL */
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name); int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name);
/************************** S1AP **************************/
/* Get the number of MMEs to be connected */
int flexran_get_s1ap_mme_pending(mid_t mod_id);
/* Get the number of connected MMEs */
int flexran_get_s1ap_mme_connected(mid_t mod_id);
/* Get the eNB S1AP IP address */
char* flexran_get_s1ap_enb_s1_ip(mid_t mod_id);
/* Get the name of the eNB */
char* flexran_get_s1ap_enb_name(mid_t mod_id);
/* Get the number of connected MMEs to this eNB */
int flexran_get_s1ap_nb_mme(mid_t mod_id);
/* Get the number of connected UEs to this eNB */
int flexran_get_s1ap_nb_ue(mid_t mod_id);
/* Get the S1AP MME conf */
int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apMme * mme_conf);
/* Get the S1AP UE conf */
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf);
/********************* general information *****************/ /********************* general information *****************/
/* get an ID for this BS (or part of a BS) */ /* get an ID for this BS (or part of a BS) */
uint64_t flexran_get_bs_id(mid_t mod_id); uint64_t flexran_get_bs_id(mid_t mod_id);
...@@ -815,7 +843,7 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps) ...@@ -815,7 +843,7 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
/* get the capabilities supported by the underlying network function as a bit /* get the capabilities supported by the underlying network function as a bit
* mask. */ * mask. */
uint16_t flexran_get_capabilities_mask(mid_t mod_id); uint32_t flexran_get_capabilities_mask(mid_t mod_id);
/* get the splits used by the underlying network function, /* get the splits used by the underlying network function,
* return the number and stores list of this length in splits. If there are * return the number and stores list of this length in splits. If there are
......
...@@ -124,7 +124,9 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, ...@@ -124,7 +124,9 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
s1ap_mme_data_p->assoc_id = -1; s1ap_mme_data_p->assoc_id = -1;
s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num;
memcpy(&s1ap_mme_data_p->mme_s1_ip,
mme_ip_address,
sizeof(*mme_ip_address));
for (int i = 0; i < broadcast_plmn_num; ++i) for (int i = 0; i < broadcast_plmn_num; ++i)
s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];
...@@ -193,6 +195,10 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * ...@@ -193,6 +195,10 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
new_instance->eNB_id = s1ap_register_eNB->eNB_id; new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type; new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac; new_instance->tac = s1ap_register_eNB->tac;
memcpy(&new_instance->eNB_s1_ip,
&s1ap_register_eNB->enb_ip_address,
sizeof(s1ap_register_eNB->enb_ip_address));
for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) { for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) {
new_instance->mcc[i] = s1ap_register_eNB->mcc[i]; new_instance->mcc[i] = s1ap_register_eNB->mcc[i];
......
...@@ -124,6 +124,9 @@ typedef struct s1ap_eNB_mme_data_s { ...@@ -124,6 +124,9 @@ typedef struct s1ap_eNB_mme_data_s {
/* This is the optional name provided by the MME */ /* This is the optional name provided by the MME */
char *mme_name; char *mme_name;
/* MME S1AP IP address */
net_ip_address_t mme_s1_ip;
/* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max /* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max
* number of 8 RATs but in our case only one is used. The LTE related pool * number of 8 RATs but in our case only one is used. The LTE related pool
* configuration is included on the first place in the list. * configuration is included on the first place in the list.
...@@ -200,6 +203,9 @@ typedef struct s1ap_eNB_instance_s { ...@@ -200,6 +203,9 @@ typedef struct s1ap_eNB_instance_s {
/* Tracking area code */ /* Tracking area code */
uint16_t tac; uint16_t tac;
/* eNB S1AP IP address */
net_ip_address_t eNB_s1_ip;
/* Mobile Country Code /* Mobile Country Code
* Mobile Network Code * Mobile Network Code
*/ */
......
...@@ -1468,7 +1468,7 @@ int s1ap_eNB_path_switch_req(instance_t instance, ...@@ -1468,7 +1468,7 @@ int s1ap_eNB_path_switch_req(instance_t instance,
break; break;
} }
} while(1); } while(1);
ue_context_p->mme_ue_s1ap_id = path_switch_req_p->mme_ue_s1ap_id; ue_context_p->mme_ue_s1ap_id = path_switch_req_p->mme_ue_s1ap_id;
/* Prepare the S1AP message to encode */ /* Prepare the S1AP message to encode */
......
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