Merge branch 'fhg-ta' into fhg-ra

This commit is contained in:
cig
2020-02-03 10:45:29 +01:00
359 changed files with 41429 additions and 5532 deletions
File diff suppressed because it is too large Load Diff
@@ -51,8 +51,15 @@ int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg);
int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg);
/* Statistics reply protocol message constructor and destructor */
int flexran_agent_mac_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report);
/* Statistics reply protocol message constructors (for UE and cell stats) and destructor */
int flexran_agent_mac_stats_reply_ue(mid_t mod_id,
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags);
int flexran_agent_mac_stats_reply_cell(mid_t mod_id,
Protocol__FlexCellStatsReport **cell_report,
int n_cc,
uint32_t cc_flags);
int flexran_agent_mac_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* DL MAC scheduling decision protocol message constructor (empty command) and destructor */
@@ -54,10 +54,9 @@ typedef struct {
void (*flexran_agent_get_pending_dl_mac_config)(mid_t mod_id,
Protocol__FlexranMessage **msg);
/// Notify the controller for a state change of a particular UE, by sending the proper
/// UE state change message (ACTIVATION, DEACTIVATION, HANDOVER)
// int (*flexran_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti,
// uint8_t state_change);
/// Notify the controller of another (RU) tick, i.e. new subframe. Used to
/// synchronize the eNB and the agent.
void (*flexran_agent_notify_tick)(mid_t mod_id);
void *dl_scheduler_loaded_lib;
@@ -61,12 +61,6 @@ err_code_t flexran_agent_init_cont_mac_stats_update(mid_t mod_id);
err_code_t flexran_agent_destroy_cont_mac_stats_update(mid_t mod_id);
/*Enable/Disable the continuous stats update service for the MAC*/
err_code_t flexran_agent_enable_cont_mac_stats_update(mid_t mod_id, xid_t xid,
stats_request_config_t *stats_req);
err_code_t flexran_agent_disable_cont_mac_stats_update(mid_t mod_id);
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_report,
Protocol__FlexranMessage *old_report);
@@ -65,25 +65,17 @@ void flexran_agent_pdcp_aggregate_stats(const mid_t mod_id,
int flexran_agent_pdcp_stats_reply(mid_t mod_id,
const report_config_t *report_config,
Protocol__FlexUeStatsReport **ue_report,
Protocol__FlexCellStatsReport **cell_report) {
// Protocol__FlexHeader *header;
int i;
// int cc_id = 0;
/* Allocate memory for list of UE reports */
if (report_config->nr_ue > 0) {
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags) {
if (n_ue > 0) {
for (i = 0; i < report_config->nr_ue; i++) {
const rnti_t rnti = report_config->ue_report_type[i].ue_rnti;
for (int i = 0; i < n_ue; i++) {
const rnti_t rnti = ue_report[i]->rnti;
const uint16_t uid = flexran_get_pdcp_uid_from_rnti(mod_id, rnti);
/* Check flag for creation of buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PDCP_STATS) {
if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PDCP_STATS) {
Protocol__FlexPdcpStats *pdcp_aggr_stats;
pdcp_aggr_stats = malloc(sizeof(Protocol__FlexPdcpStats));
@@ -129,12 +121,6 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
error:
LOG_W(FLEXRAN_AGENT, "Can't allocate PDCP stats\n");
/* if (cell_report != NULL)
free(cell_report);
if (ue_report != NULL)
free(ue_report);
*/
return -1;
}
@@ -48,9 +48,9 @@
/* Send to the controller all the pdcp stat updates that occured during this subframe*/
int flexran_agent_pdcp_stats_reply(mid_t mod_id,
const report_config_t *report_config,
Protocol__FlexUeStatsReport **ue_report,
Protocol__FlexCellStatsReport **cell_report);
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags);
int flexran_agent_pdcp_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* Get the stats from RAN API and aggregate them per USER*/
@@ -380,18 +380,15 @@ void flexran_trigger_rrc_measurements (mid_t mod_id, LTE_MeasResults_t* measRes
int flexran_agent_rrc_stats_reply(mid_t mod_id,
const report_config_t *report_config,
Protocol__FlexUeStatsReport **ue_report,
Protocol__FlexCellStatsReport **cell_report) {
if (report_config->nr_ue > 0) {
rnti_t rntis[report_config->nr_ue];
flexran_get_rrc_rnti_list(mod_id, rntis, report_config->nr_ue);
for (int i = 0; i < report_config->nr_ue; i++) {
const rnti_t rnti = rntis[i];
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags) {
if (n_ue > 0) {
for (int i = 0; i < n_ue; i++) {
const rnti_t rnti = ue_report[i]->rnti;
/* Check flag for creation of buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS) {
if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS) {
/*Source cell EUTRA Measurements*/
Protocol__FlexRrcMeasurements *rrc_measurements;
@@ -531,7 +528,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
}
return 0;
error:
for (int i = 0; i < report_config->nr_ue; i++) {
for (int i = 0; i < n_ue; i++) {
if (ue_report[i]->rrc_measurements && ue_report[i]->rrc_measurements->neigh_meas != NULL) {
for (int j = 0; j < ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) {
free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]);
@@ -540,8 +537,6 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
}
}
if (cell_report != NULL)
free(cell_report);
if (ue_report != NULL)
free(ue_report);
return -1;
@@ -575,20 +570,18 @@ int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply)
}
int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id,
const report_config_t *report_config,
Protocol__FlexUeStatsReport **ue_report,
Protocol__FlexCellStatsReport **cell_report) {
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags) {
/* This function fills the GTP part of the statistics. The necessary
* information is, for our purposes, completely maintained in the RRC layer.
* It would be possible to add a GTP module that handles this, though. */
if (report_config->nr_ue > 0) {
rnti_t rntis[report_config->nr_ue];
flexran_get_rrc_rnti_list(mod_id, rntis, report_config->nr_ue);
for (int i = 0; i < report_config->nr_ue; i++) {
const rnti_t rnti = rntis[i];
if (n_ue > 0) {
for (int i = 0; i < n_ue; i++) {
const rnti_t rnti = ue_report[i]->rnti;
/* Check flag for creation of buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_GTP_STATS) {
if (ue_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_GTP_STATS) {
/* get number of rabs for this UE */
const int num_e_rab = flexran_agent_rrc_gtp_num_e_rab(mod_id, rnti);
@@ -618,7 +611,7 @@ int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id,
}
return 0;
error:
for (int i = 0; i < report_config->nr_ue; i++) {
for (int i = 0; i < n_ue; i++) {
if (!ue_report[i]->gtp_stats) continue;
for (int r = 0; r < ue_report[i]->n_gtp_stats; ++r) {
if (ue_report[i]->gtp_stats[r]) {
@@ -57,12 +57,18 @@ int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg);
void flexran_trigger_rrc_measurements (mid_t mod_id, LTE_MeasResults_t *);
/* Statistics reply protocol message constructor and destructor */
int flexran_agent_rrc_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report);
int flexran_agent_rrc_stats_reply(mid_t mod_id,
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags);
int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* Statistic reply for GTP statistics which OAI stores also in the RRC layer.
* This might be moved to a separate GTP module in the future */
int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report);
int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id,
Protocol__FlexUeStatsReport **ue_report,
int n_ue,
uint32_t ue_flags);
int flexran_agent_rrc_gtp_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* Fill the RRC part of a ue_config message */
@@ -0,0 +1,161 @@
/*
* 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];
}
@@ -0,0 +1,69 @@
/*
* 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
@@ -0,0 +1,32 @@
/*
* 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
@@ -336,3 +336,28 @@ message flex_a5_event {
optional int64 time_to_trigger = 4;
optional int64 max_report_cells = 5;
}
//
// S1AP cell configuration
//
message flex_gummei {
optional flex_plmn plmn = 1;
optional uint32 mme_group_id = 2;
optional uint32 mme_code = 3;
}
message flex_s1ap_mme {
optional string s1_ip = 1; // S1-MME IP of MME
optional string name = 2; // S1-MME name of MME
optional flex_mme_state state = 3; // State of the MME
repeated flex_gummei served_gummeis = 4; // GUMMEIs served by the MME
repeated flex_plmn requested_plmns = 5; // PLMNs communicated to MME
optional uint32 rel_capacity = 6; // Relative MME capacity, TS23.401
}
enum flex_mme_state {
FLMMES_DISCONNECTED = 0;
FLMMES_WAITING = 1;
FLMMES_CONNECTED = 2;
FLMMES_OVERLOAD = 3;
}
@@ -107,6 +107,10 @@ message flex_lc_ue_config {
repeated flex_lc_config lc_config = 2; // A list of LC configurations for the given UE
}
message flex_s1ap_config {
optional uint32 pending = 1; // number of pending (to be connected) MMEs
optional uint32 connected = 2; // number of connected MMEs
optional string enb_s1_ip = 3; // S1-MME IP of eNodeB
optional string enb_name = 4; // S1-MME name of eNodeB
repeated flex_s1ap_mme mme = 5;
}
+11 -1
View File
@@ -6,7 +6,6 @@ import "header.proto";
import "time_common.proto";
import "config_messages.proto";
import "controller_commands.proto";
import "control_delegation.proto";
import "config_common.proto";
message flexran_message {
@@ -75,12 +74,22 @@ enum flex_bs_capability {
PDCP = 5;
SDAP = 6;
RRC = 7;
S1AP = 8;
}
enum flex_bs_split {
F1 = 0;
nFAPI = 1;
IF4 = 2;
IF4p5 = 3;
IF5 = 4;
}
message flex_hello {
optional flex_header header = 1;
optional uint64 bs_id = 2; // Unique id to distinguish the eNB
repeated flex_bs_capability capabilities = 3;
repeated flex_bs_split splits = 4;
}
message flex_echo_request {
@@ -147,6 +156,7 @@ message flex_enb_config_reply {
optional flex_header header = 1;
repeated flex_cell_config cell_config = 3;
optional uint32 device_spec = 4;
optional flex_s1ap_config s1ap = 5;
}
message flex_ue_config_request {
+16 -11
View File
@@ -1,6 +1,8 @@
syntax = "proto2";
package protocol;
import "config_common.proto"; // for flex_plmn
//
// UE related statistics
//
@@ -218,25 +220,16 @@ message flex_eutra_cgi_measurements {
// Tracking area code of the neighbor cell.
optional uint32 tracking_area_code = 2;
// Public land mobile network identifiers of neighbor cell.
repeated flex_plmn_identity plmn_id = 3;
repeated flex_plmn plmn = 3;
}
message flex_cell_global_eutra_id {
// Public land mobile network identifier of neighbor cell.
optional flex_plmn_identity plmn_id = 1;
optional flex_plmn plmn = 1;
// Cell identifier of neighbor cell.
optional uint32 cell_id = 2;
}
message flex_plmn_identity {
// Mobile Network Code (MNC).
repeated uint32 mnc = 1;
// Mobile Country Code (MCC).
repeated uint32 mcc = 2;
// tracking area code
repeated uint32 tac = 3;
}
message flex_eutra_ref_signal_meas {
// Neighboring Cell RSRP
optional int32 rsrp = 1;
@@ -317,3 +310,15 @@ message flex_gtp_stats {
optional uint32 teid_sgw = 4;
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 {
optional flex_pdcp_stats pdcp_stats = 11;
optional flex_mac_stats mac_stats = 12;
repeated flex_gtp_stats gtp_stats = 13;
optional flex_s1ap_ue s1ap_stats = 14;
}
//
@@ -91,6 +92,7 @@ enum flex_ue_stats_type {
FLUST_PDCP_STATS = 1024;
FLUST_GTP_STATS = 2048;
FLUST_S1AP_STATS = 4096;
FLUST_RRC_MEASUREMENTS = 65536;
// To be extended with more types of stats
+228
View File
@@ -46,6 +46,8 @@
# include "x2ap_eNB.h"
# include "x2ap_messages_types.h"
# include "m2ap_eNB.h"
# include "m2ap_messages_types.h"
# define X2AP_ENB_REGISTER_RETRY_DELAY 10
#include "openair1/PHY/INIT/phy_init.h"
@@ -56,6 +58,90 @@ extern RAN_CONTEXT_t RC;
# define ENB_REGISTER_RETRY_DELAY 10
#include "targets/RT/USER/lte-softmodem.h"
/*************************** ENB M2AP **************************/
//static uint32_t eNB_app_register_MBMS_STA(ngran_node_t node_type,uint32_t enb_id_start, uint32_t enb_id_end) {
// uint32_t enb_id;
// //MessageDef *msg_p;
// uint32_t register_enb_pending = 0;
//
// for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
// {
//
// //msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
// //RCconfig_S1(msg_p, enb_id);
//
// if (enb_id == 0) RCconfig_gtpu();
//
// //LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx));
//
// //LOG_I(ENB_APP,"[eNB %d] eNB_app_register via S1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
// //itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
//
// register_enb_pending++;
// }
// }
//
// return register_enb_pending;
//}
//*****end M2AP ****/
static uint32_t eNB_app_register_m2(uint32_t enb_id_start, uint32_t enb_id_end) {
uint32_t enb_id;
MessageDef *msg_p;
uint32_t register_enb_m2_pending = 0;
// msg_p = itti_alloc_new_message (TASK_ENB_APP,MESSAGE_TEST );
// itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
LOG_D(ENB_APP,"Register ...\n");
for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
{
msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_REGISTER_ENB_REQ);
RCconfig_M2(msg_p, enb_id);
itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
register_enb_m2_pending++;
}
}
return register_enb_m2_pending;
}
/*************************** M2AP ENB handle **********************************/
static uint32_t eNB_app_handle_m2ap_mbms_scheduling_information(instance_t instance){
//uint32_t mce_id=0;
MessageDef *msg_p;
msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SCHEDULING_INFORMATION_RESP);
itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
return 0;
}
static uint32_t eNB_app_handle_m2ap_mbms_session_start_req(instance_t instance){
//uint32_t mce_id=0;
MessageDef *msg_p;
msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_START_RESP);
itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
return 0;
}
static uint32_t eNB_app_handle_m2ap_mbms_session_stop_req(instance_t instance){
//uint32_t mce_id=0;
MessageDef *msg_p;
msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_STOP_RESP);
itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
return 0;
}
static uint32_t eNB_app_handle_m2ap_mbms_session_update_req(instance_t instance){
//uint32_t mce_id=0;
MessageDef *msg_p;
msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_UPDATE_RESP);
itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
return 0;
}
//// end M2AP ENB handle **********************************/
/*------------------------------------------------------------------------------*/
@@ -126,6 +212,9 @@ void *eNB_app_task(void *args_p) {
uint32_t x2_register_enb_pending = 0;
uint32_t x2_registered_enb = 0;
long x2_enb_register_retry_timer_id;
uint32_t m2_register_enb_pending = 0;
uint32_t m2_registered_enb = 0;
long m2_enb_register_retry_timer_id;
MessageDef *msg_p = NULL;
instance_t instance;
int result;
@@ -144,6 +233,22 @@ void *eNB_app_task(void *args_p) {
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
}
/* Try to register each eNB with MCE each other */
if (is_m2ap_eNB_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
//eNB_app_register_MBMS_STA(RC.rrc[0]->node_type, enb_id_start, enb_id_end);
//m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
if (timer_setup (5, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
NULL, &m2_enb_register_retry_timer_id) < 0) {
//LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
//sleep(ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
//registered_enb = 0;
//register_enb_pending = eNB_app_register (RC.rrc[0]->node_type,enb_id_start, enb_id_end);
}
}
do {
// Wait for a message
itti_receive_msg (TASK_ENB_APP, &msg_p);
@@ -272,6 +377,12 @@ void *eNB_app_task(void *args_p) {
}
} /* if (EPC_MODE_ENABLED) */
if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) {
LOG_I(ENB_APP, " Received %s: timer_id %ld M2 register\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end);
}
break;
case X2AP_DEREGISTERED_ENB_IND:
@@ -316,6 +427,123 @@ void *eNB_app_task(void *args_p) {
break;
case M2AP_DEREGISTERED_ENB_IND:
LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2);
/* TODO handle recovering of registration */
break;
case M2AP_REGISTER_ENB_CNF:
LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
M2AP_REGISTER_ENB_CNF(msg_p).nb_m2);
DevAssert(m2_register_enb_pending > 0);
m2_register_enb_pending--;
/* Check if at least eNB is registered with one target eNB */
if (M2AP_REGISTER_ENB_CNF(msg_p).nb_m2 > 0) {
m2_registered_enb++;
}
/* Check if all register eNB requests have been processed */
if (m2_register_enb_pending == 0) {
if (m2_registered_enb == enb_nb) {
/* If all eNB are registered, start RRC HO task */
} else {
uint32_t m2_not_associated = enb_nb - m2_registered_enb;
LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
m2_not_associated, m2_not_associated > 1 ? "are" : "is");
// timer to retry
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
//if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
// INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
// &x2_enb_register_retry_timer_id) < 0) {
// LOG_E(ENB_APP, " Can not start eNB X2AP register: retry timer, use \"sleep\" instead!\n");
// sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
// /* Restart the registration process */
// x2_registered_enb = 0;
// x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
//}
}
}
break;
case M2AP_SETUP_RESP:
LOG_I(ENB_APP,"M2AP_SETUP_RESP RESPONSE received\n");
// AssertFatal(NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received F1AP_REGISTER_ENB_CNF in CU/eNB\n");
// LOG_I(ENB_APP, "Received %s: associated ngran_eNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
// F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate);
//
// handle_f1ap_setup_resp(&F1AP_SETUP_RESP(msg_p));
// DevAssert(register_enb_pending > 0);
// register_enb_pending--;
// /* Check if at least eNB is registered with one MME */
// if (F1AP_SETUP_RESP(msg_p).num_cells_to_activate > 0) {
// registered_enb++;
// }
// /* Check if all register eNB requests have been processed */
// if (register_enb_pending == 0) {
// if (registered_enb == enb_nb) {
// /* If all eNB cells are registered, start L2L1 task */
// MessageDef *msg_init_p;
// msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
// itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
// } else {
// LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n",
// enb_nb - registered_enb, ENB_REGISTER_RETRY_DELAY);
// /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
// if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
// NULL, &enb_register_retry_timer_id) < 0) {
// LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
// sleep(ENB_REGISTER_RETRY_DELAY);
// /* Restart the registration process */
// registered_enb = 0;
// register_enb_pending = eNB_app_register (RC.rrc[0]->node_type,enb_id_start, enb_id_end);//, enb_properties_p);
// }
// }
// }
break;
case M2AP_MBMS_SCHEDULING_INFORMATION:
LOG_I(ENB_APP,"M2AP_SCHEDULING_INFORMATION received\n");
eNB_app_handle_m2ap_mbms_scheduling_information(ITTI_MESSAGE_GET_INSTANCE(msg_p));
break;
case M2AP_MBMS_SESSION_START_REQ:
LOG_I(ENB_APP,"M2AP_MBMS_SESSION_START_REQ received\n");
eNB_app_handle_m2ap_mbms_session_start_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
break;
case M2AP_MBMS_SESSION_STOP_REQ:
LOG_I(ENB_APP,"M2AP_MBMS_SESSION_STOP_REQ received\n");
eNB_app_handle_m2ap_mbms_session_stop_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
break;
case M2AP_RESET:
LOG_I(ENB_APP,"M2AP_RESET received\n");
break;
case M2AP_ENB_CONFIGURATION_UPDATE_ACK:
LOG_I(ENB_APP,"M2AP_ENB_CONFIGURATION_UPDATE_ACK received\n");
break;
case M2AP_ENB_CONFIGURATION_UPDATE_FAILURE:
LOG_I(ENB_APP,"M2AP_ENB_CONFIGURATION_UPDATE_FAILURE received\n");
break;
case M2AP_ERROR_INDICATION:
LOG_I(ENB_APP,"M2AP_MBMS_SESSION_UPDATE_REQ\n");
eNB_app_handle_m2ap_mbms_session_update_req(ITTI_MESSAGE_GET_INSTANCE(msg_p));
break;
case M2AP_MBMS_SERVICE_COUNTING_REQ:
LOG_I(ENB_APP,"M2AP_MBMS_SERVICE_COUNTING_REQ\n");
break;
case M2AP_MCE_CONFIGURATION_UPDATE:
LOG_I(ENB_APP,"M2AP_MCE_CONFIGURATION_UPDATE\n");
break;
default:
LOG_E(ENB_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
break;
+270 -1
View File
@@ -380,7 +380,6 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) {
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
//RRC_CONFIGURATION_REQ (msg_p).rrc_inactivity_timer_thres = RRC_INACTIVITY_THRESH; // set to 0 to deactivate
// In the configuration file it is in seconds. For RRC it has to be in milliseconds
RRC_CONFIGURATION_REQ (msg_p).rrc_inactivity_timer_thres = (*ENBParamList.paramarray[i][ENB_RRC_INACTIVITY_THRES_IDX].uptr) * 1000;
RRC_CONFIGURATION_REQ (msg_p).cell_identity = enb_id;
@@ -428,6 +427,14 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) {
else
RRC_CONFIGURATION_REQ (msg_p).enable_x2 = 0;
/* m2 enabled */
if (ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr != NULL &&
*(ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr) != NULL &&
!strcmp(*(ENBParamList.paramarray[i][ENB_ENABLE_ENB_M2].strptr), "yes"))
RRC_CONFIGURATION_REQ (msg_p).eMBMS_M2_configured = 1;
else
RRC_CONFIGURATION_REQ (msg_p).eMBMS_M2_configured = 0;
// Parse optional physical parameters
config_getlist( &CCsParamList,NULL,0,enbpath);
LOG_I(RRC,"num component carriers %d \n",CCsParamList.numelt);
@@ -2044,6 +2051,266 @@ int RCconfig_gtpu(void ) {
return 0;
}
int RCconfig_M2(MessageDef *msg_p, uint32_t i) {
int I, J, j, k, l;
int enb_id;
char *address = NULL;
char *cidr = NULL;
ccparams_lte_t ccparams_lte;
memset((void *)&ccparams_lte,0,sizeof(ccparams_lte_t));
paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
paramdef_t ENBParams[] = ENBPARAMS_DESC;
paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
/* get global parameters, defined outside any section in the config file */
config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
paramdef_t CCsParams[] = CCPARAMS_DESC(ccparams_lte);
paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0};
// ccparams_MCE_t MCEconfig;
// memset((void *)&MCEconfig,0,sizeof(ccparams_MCE_t));
// paramdef_t MCEParams[] = MCEPARAMS_DESC((&MCEconfig));
// checkedparam_t config_check_MCEparams[] = MCEPARAMS_CHECK;
/* map parameter checking array instances to parameter definition array instances */
for (I = 0; I < (sizeof(CCsParams) / sizeof(paramdef_t)); I++) {
CCsParams[I].chkPptr = &(config_check_CCparams[I]);
}
AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
"Failed to parse config file %s, %uth attribute %s \n",
RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);
if (ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt > 0) {
// Output a list of all eNBs.
config_getlist( &ENBParamList,ENBParams,sizeof(ENBParams)/sizeof(paramdef_t),NULL);
if (ENBParamList.numelt > 0) {
for (k = 0; k < ENBParamList.numelt; k++) {
if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) {
// Calculate a default eNB ID
if (EPC_MODE_ENABLED) {
uint32_t hash;
hash = s1ap_generate_eNB_id ();
enb_id = k + (hash & 0xFFFF8);
} else {
enb_id = k;
}
} else {
enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr);
}
// search if in active list
for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) {
if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) {
paramdef_t PLMNParams[] = PLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0};
/* map parameter checking array instances to parameter definition array instances */
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
paramdef_t M2Params[] = M2PARAMS_DESC;
paramlist_def_t M2ParamList = {ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS,NULL,0};
paramdef_t SCTPParams[] = SCTPPARAMS_DESC;
paramdef_t NETParams[] = NETPARAMS_DESC;
paramdef_t MBMSConfigParams[] = MBMS_CONFIG_PARAMS_DESC;
paramdef_t MBMSParams[] = MBMSPARAMS_DESC;
paramlist_def_t MBMSConfigParamList = {ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST,NULL,0};
paramlist_def_t MBMSParamList = {ENB_CONFIG_STRING_MBMS_SERVICE_AREA_LIST,NULL,0};
/* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */
/* this is most probably a problem with the config module */
char aprefix[MAX_OPTNAME_SIZE*80 + 8];
sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
/* Some default/random parameters */
M2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;
if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB;
} else if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB;
} else {
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr));
}
M2AP_REGISTER_ENB_REQ (msg_p).eNB_name = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr));
M2AP_REGISTER_ENB_REQ (msg_p).tac = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr;
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
// char aprefix2[MAX_OPTNAME_SIZE*80 + 8];
// sprintf(aprefix2,"%s.[%i].%s.[0]",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST);
// config_getlist(&MBMSParamList, MBMSParams, sizeof(MBMSParams)/sizeof(paramdef_t), aprefix2);
// if (MBMSParamList.numelt < 1 || MBMSParamList.numelt > 8)
// AssertFatal(0, "The number of MBMS Areas must be in [1,8], but is %d\n",
// MBMSParamList.numelt);
// M2AP_REGISTER_ENB_REQ (msg_p).num_mbms_service_area_list = MBMSParamList.numelt;
// for(J=0; J<MBMSParamList.numelt;J++){
// M2AP_REGISTER_ENB_REQ (msg_p).mbms_service_area_list[J] = *MBMSParamList.paramarray[J][ENB_MBMS_SERVICE_AREA_IDX].uptr;
// }
//
char aprefix2[MAX_OPTNAME_SIZE*80 + 8];
sprintf(aprefix2,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
config_getlist(&MBMSConfigParamList, MBMSConfigParams, sizeof(MBMSConfigParams)/sizeof(paramdef_t), aprefix2);
if (MBMSConfigParamList.numelt < 1 || MBMSConfigParamList.numelt > 8)
AssertFatal(0, "The number of MBMS Config Data must be in [1,8], but is %d\n",
MBMSConfigParamList.numelt);
M2AP_REGISTER_ENB_REQ (msg_p).num_mbms_configuration_data_list = MBMSConfigParamList.numelt;
for(int I=0; I < MBMSConfigParamList.numelt; I++){
sprintf(aprefix2,"%s.[%i].%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST,I);
config_getlist(&MBMSParamList, MBMSParams, sizeof(MBMSParams)/sizeof(paramdef_t), aprefix2);
if (MBMSParamList.numelt < 1 || MBMSParamList.numelt > 8)
AssertFatal(0, "The number of MBMS Areas must be in [1,8], but is %d\n",
MBMSParamList.numelt);
M2AP_REGISTER_ENB_REQ (msg_p).mbms_configuration_data_list[I].num_mbms_service_area_list = MBMSParamList.numelt;
for(J=0; J<MBMSParamList.numelt;J++){
M2AP_REGISTER_ENB_REQ (msg_p).mbms_configuration_data_list[I].mbms_service_area_list[J] = *MBMSParamList.paramarray[J][ENB_MBMS_SERVICE_AREA_IDX].uptr;
}
}
if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
PLMNParamList.numelt);
if (PLMNParamList.numelt > 1)
LOG_W(M2AP, "M2AP currently handles only one PLMN, ignoring the others!\n");
M2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][ENB_MOBILE_COUNTRY_CODE_IDX].uptr;
M2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][ENB_MOBILE_NETWORK_CODE_IDX].uptr;
M2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][ENB_MNC_DIGIT_LENGTH].u8ptr;
AssertFatal(M2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3
|| M2AP_REGISTER_ENB_REQ(msg_p).mnc < 100,
"MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
M2AP_REGISTER_ENB_REQ(msg_p).mnc);
/* CC params */
config_getlist(&CCsParamList, NULL, 0, aprefix);
M2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt;
if (CCsParamList.numelt > 0) {
//char ccspath[MAX_OPTNAME_SIZE*2 + 16];
for (J = 0; J < CCsParamList.numelt ; J++) {
sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J);
config_get(CCsParams, sizeof(CCsParams)/sizeof(paramdef_t), aprefix);
M2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = ccparams_lte.eutra_band;
M2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) ccparams_lte.downlink_frequency;
M2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) ccparams_lte.uplink_frequency_offset;
M2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= ccparams_lte.Nid_cell;
if (ccparams_lte.Nid_cell>503) {
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n",
RC.config_file_name, k, ccparams_lte.Nid_cell);
}
M2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= ccparams_lte.N_RB_DL;
if ((ccparams_lte.N_RB_DL!=6) && (ccparams_lte.N_RB_DL!=15) && (ccparams_lte.N_RB_DL!=25) && (ccparams_lte.N_RB_DL!=50) && (ccparams_lte.N_RB_DL!=75) && (ccparams_lte.N_RB_DL!=100)) {
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n",
RC.config_file_name, k, ccparams_lte.N_RB_DL);
}
if (strcmp(ccparams_lte.frame_type, "FDD") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD;
} else if (strcmp(ccparams_lte.frame_type, "TDD") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
} else {
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
RC.config_file_name, k, ccparams_lte.frame_type);
}
M2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL);
M2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL);
}
}
sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
config_getlist( &M2ParamList,M2Params,sizeof(M2Params)/sizeof(paramdef_t),aprefix);
AssertFatal(M2ParamList.numelt <= M2AP_MAX_NB_ENB_IP_ADDRESS,
"value of M2ParamList.numelt %d must be lower than M2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase M2AP_MAX_NB_ENB_IP_ADDRESS\n",
M2ParamList.numelt,M2AP_MAX_NB_ENB_IP_ADDRESS);
M2AP_REGISTER_ENB_REQ (msg_p).nb_m2 = 0;
for (l = 0; l < M2ParamList.numelt; l++) {
M2AP_REGISTER_ENB_REQ (msg_p).nb_m2 += 1;
strcpy(M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4_address,*(M2ParamList.paramarray[l][ENB_M2_IPV4_ADDRESS_IDX].strptr));
strcpy(M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6_address,*(M2ParamList.paramarray[l][ENB_M2_IPV6_ADDRESS_IDX].strptr));
if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 1;
M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 0;
} else if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 0;
M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 1;
} else if (strcmp(*(M2ParamList.paramarray[l][ENB_M2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv4 = 1;
M2AP_REGISTER_ENB_REQ (msg_p).target_mce_m2_ip_address[l].ipv6 = 1;
}
}
// timers
//{
// int t_reloc_prep = 0;
// int tx2_reloc_overall = 0;
// paramdef_t p[] = {
// { "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 },
// { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 }
// };
// config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix);
// if (t_reloc_prep <= 0 || t_reloc_prep > 10000 ||
// tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) {
// LOG_E(M2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n");
// exit(1);
// }
// M2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep;
// M2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall;
//}
// SCTP SETTING
M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS;
if (EPC_MODE_ENABLED) {
sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG);
config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr);
M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr);
}
sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
// NETWORK_INTERFACES
config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix);
M2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_M2C = (uint32_t)*(NETParams[ENB_PORT_FOR_M2C_IDX].uptr);
if ((NETParams[ENB_IPV4_ADDR_FOR_M2C_IDX].strptr == NULL) || (M2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_M2C == 0)) {
LOG_E(RRC,"Add eNB IPv4 address and/or port for M2C in the CONF file!\n");
exit(1);
}
cidr = *(NETParams[ENB_IPV4_ADDR_FOR_M2C_IDX].strptr);
address = strtok(cidr, "/");
M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv6 = 0;
M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv4 = 1;
strcpy(M2AP_REGISTER_ENB_REQ (msg_p).enb_m2_ip_address.ipv4_address, address);
}
}
}
}
}
return 0;
}
//-----------------------------------------------------------------------------
/*
* Configure the s1ap_register_enb_req in itti message for future
@@ -2842,4 +3109,6 @@ void read_config_and_init(void) {
memset((void *)RC.rrc[enb_id], 0, sizeof(eNB_RRC_INST));
RCconfig_RRC(enb_id, RC.rrc[enb_id],macrlc_has_f1[enb_id]);
}
RCconfig_flexran();
}
+1
View File
@@ -116,6 +116,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i);
void read_config_and_init(void);
int RCconfig_X2(MessageDef *msg_p, uint32_t i);
int RCconfig_M2(MessageDef *msg_p, uint32_t i);
void fill_SL_configuration(MessageDef *msg_p, ccparams_sidelink_t *SLconfig,int cell_idx,int cc_idx,char *config_fname);
void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, int cell_idx,int cc_idx,char *config_fname,char *brparamspath);
+85 -3
View File
@@ -205,6 +205,8 @@ typedef enum {
#define ENB_CONFIG_STRING_RRC_INACTIVITY_THRESHOLD "rrc_inactivity_threshold"
#define ENB_CONFIG_STRING_MEASUREMENT_REPORTS "enable_measurement_reports"
#define ENB_CONFIG_STRING_X2 "enable_x2"
#define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2"
#define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2"
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* cell configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
@@ -228,7 +230,10 @@ typedef enum {
{ENB_CONFIG_STRING_RRC_INACTIVITY_THRESHOLD, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_MEASUREMENT_REPORTS, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
}
#define ENB_ENB_ID_IDX 0
#define ENB_CELL_TYPE_IDX 1
#define ENB_ENB_NAME_IDX 2
@@ -247,6 +252,8 @@ typedef enum {
#define ENB_RRC_INACTIVITY_THRES_IDX 15
#define ENB_ENABLE_MEASUREMENT_REPORTS 16
#define ENB_ENABLE_X2 17
#define ENB_ENABLE_ENB_M2 18
#define ENB_ENABLE_MCE_M2 19
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define ENBPARAMS_CHECK { \
@@ -266,6 +273,8 @@ typedef enum {
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -300,6 +309,32 @@ typedef enum {
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
#define ENB_CONFIG_STRING_MBMS_CONFIGURATION_DATA_LIST "mbms_configuration_data_list"
#define ENB_CONFIG_STRING_MBMS_SYNC_AREA "mbms_sync_area"
#define ENB_MBMS_SYNC_AREA_IDX 0
#define MBMS_CONFIG_PARAMS_DESC { \
/* optname helpstr paramflags XXXptr def val type numelt */ \
{ENB_CONFIG_STRING_MBMS_SYNC_AREA , NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
#define ENB_CONFIG_STRING_MBMS_SERVICE_AREA_LIST "mbms_service_area_list"
#define ENB_CONFIG_STRING_MBMS_SERVICE_AREA "mbms_service_area"
#define ENB_MBMS_SERVICE_AREA_IDX 0
#define MBMSPARAMS_DESC { \
/* optname helpstr paramflags XXXptr def val type numelt */ \
{ENB_CONFIG_STRING_MBMS_SERVICE_AREA, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
/* component carries configuration parameters name */
#define ENB_CONFIG_STRING_NB_ANT_PORTS "nb_antenna_ports"
@@ -912,6 +947,39 @@ typedef struct srb1_params_s {
#define ENB_X2_IPV4_ADDRESS_IDX 0
#define ENB_X2_IPV6_ADDRESS_IDX 1
#define ENB_X2_IP_ADDRESS_PREFERENCE_IDX 2
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* M2 configuration parameters section name */
#define ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS "target_mce_m2_ip_address"
/* M2 configuration parameters names */
#define ENB_CONFIG_STRING_TARGET_MCE_M2_IPV4_ADDRESS "ipv4"
#define ENB_CONFIG_STRING_TARGET_MCE_M2_IPV6_ADDRESS "ipv6"
#define ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS_PREFERENCE "preference"
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------------------------------------*/
/* M2 configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------*/
#define M2PARAMS_DESC { \
{ENB_CONFIG_STRING_TARGET_MCE_M2_IPV4_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TARGET_MCE_M2_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TARGET_MCE_M2_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
}
#define ENB_M2_IPV4_ADDRESS_IDX 0
#define ENB_M2_IPV6_ADDRESS_IDX 1
#define ENB_M2_IP_ADDRESS_PREFERENCE_IDX 2
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* SCTP configuration parameters section name */
#define ENB_CONFIG_STRING_SCTP_CONFIG "SCTP"
@@ -945,7 +1013,10 @@ typedef struct srb1_params_s {
#define ENB_PORT_FOR_S1U_IDX 4
#define ENB_IPV4_ADDR_FOR_X2C_IDX 5
#define ENB_PORT_FOR_X2C_IDX 6
#define ENB_IPV4_ADDR_FOR_M2C_IDX 7
#define ENB_PORT_FOR_M2C_IDX 8
#define MCE_IPV4_ADDR_FOR_M2C_IDX 9
#define MCE_PORT_FOR_M2C_IDX 10
/* S1 interface configuration parameters names */
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME"
@@ -958,6 +1029,13 @@ typedef struct srb1_params_s {
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C "ENB_IPV4_ADDRESS_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2C "ENB_PORT_FOR_X2C"
/* M2 interface configuration parameters names */
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_M2C "ENB_IPV4_ADDRESS_FOR_M2C"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_M2C "ENB_PORT_FOR_M2C"
#define ENB_CONFIG_STRING_MCE_IPV4_ADDR_FOR_M2C "MCE_IPV4_ADDRESS_FOR_M2C"
#define ENB_CONFIG_STRING_MCE_PORT_FOR_M2C "MCE_PORT_FOR_M2C"
/*--------------------------------------------------------------------------------------------------------------------------------------------------*/
/* S1/X2 interface configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
@@ -970,6 +1048,10 @@ typedef struct srb1_params_s {
{ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_PORT_FOR_X2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_M2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_PORT_FOR_M2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_MCE_IPV4_ADDR_FOR_M2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MCE_PORT_FOR_M2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0}, \
}
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -988,8 +1070,6 @@ typedef struct srb1_params_s {
#define CONFIG_STRING_L1_LIST "L1s"
#define CONFIG_STRING_L1_CONFIG "l1_config"
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -1145,4 +1225,6 @@ typedef struct srb1_params_s {
#include "enb_paramdef_emtc.h"
#include "enb_paramdef_sidelink.h"
#include "enb_paramdef_mce.h"
#include "enb_paramdef_mme.h"
#endif
+239
View File
@@ -0,0 +1,239 @@
/*
* 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 openair2/ENB_APP/enb_paramdef_mce.h
* \brief definition of configuration parameters for MCE modules
* \author Javier MORGADE
* \date 2019
* \version 0.1
* \company VICOMTECH Spain
* \email: javier.morgade@ieee.org
* \note
* \warning
*/
#include "common/config/config_paramdesc.h"
#include "RRC_paramsvalues.h"
/* mce configuration parameters names */
#define MCE_CONFIG_STRING_MCE_ID "MCE_ID"
#define MCE_CONFIG_STRING_MCE_NAME "MCE_name"
#define MCE_CONFIG_STRING_MCE_M2 "enable_mce_m2"
#define MCE_CONFIG_STRING_MCE_M3 "enable_mce_m3"
#define MCE_PARAMS_DESC {\
{MCE_CONFIG_STRING_MCE_ID, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCE_NAME, NULL, 0, strptr:NULL, defstrval:"OAIMCE", TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_MCE_M3, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
}
#define MCE_MCE_ID_IDX 0
#define MCE_MCE_NAME_IDX 1
#define MCE_ENABLE_MCE_M2_IDX 2
#define MCE_ENABLE_MCE_M3_IDX 3
#define MCE_PARAMS_CHECK { \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
#define MCE_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES"
#define MCE2_INTERFACE_NAME_FOR_M2_ENB_IDX 0
#define MCE2_IPV4_ADDR_FOR_M2C_IDX 1
#define MCE2_PORT_FOR_M2C_IDX 2
#define MCE2_INTERFACE_NAME_FOR_M3_MME_IDX 3
#define MCE2_IPV4_ADDR_FOR_M3C_IDX 4
#define MCE2_PORT_FOR_M3C_IDX 5
/* interface configuration parameters names */
/* M2 interface configuration parameters names */
#define MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M2_ENB "ENB_INTERFACE_NAME_FOR_M2_ENB"
#define MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M2C "MCE_IPV4_ADDRESS_FOR_M2C"
#define MCE_CONFIG_STRING_MCE_PORT_FOR_M2C "MCE_PORT_FOR_M2C"
/* M3 interface configuration parameters names */
#define MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M3_MME "MCE_INTERFACE_NAME_FOR_M3_MME"
#define MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M3C "MCE_IPV4_ADDRESS_FOR_M3C"
#define MCE_CONFIG_STRING_MCE_PORT_FOR_M3C "MCE_PORT_FOR_M3C"
#define MCE_NETPARAMS_DESC { \
{MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M2_ENB, NULL, 0, strptr:&mce_interface_name_for_m2_enb, defstrval:"lo", TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M2C, NULL, 0, strptr:&mce_ipv4_address_for_m2c, defstrval:NULL, TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_MCE_PORT_FOR_M2C, NULL, 0, uptr:&mce_port_for_m2c, defintval:36443L, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCE_INTERFACE_NAME_FOR_M3_MME, NULL, 0, strptr:&mce_interface_name_for_m3_mme, defstrval:NULL, TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_MCE_IPV4_ADDRESS_FOR_M3C, NULL, 0, strptr:&mce_ipv4_address_for_m3c, defstrval:NULL, TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_MCE_PORT_FOR_M3C, NULL, 0, uptr:&mce_port_for_m3c, defintval:36444L, TYPE_UINT, 0}, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------*/
/* M3 configuration parameters */
/* M3 configuration parameters section name */
#define MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS "target_mme_m3_ip_address"
/* M3 configuration parameters names */
#define MCE_CONFIG_STRING_TARGET_MME_M3_IPV4_ADDRESS "ipv4"
#define MCE_CONFIG_STRING_TARGET_MME_M3_IPV6_ADDRESS "ipv6"
#define MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS_PREFERENCE "preference"
/* optname helpstr paramflags XXXptr defXXXval type numelt */
#define M3PARAMS_DESC { \
{MCE_CONFIG_STRING_TARGET_MME_M3_IPV4_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_TARGET_MME_M3_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_TARGET_MME_M3_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
}
#define MCE2_M3_IPV4_ADDRESS_IDX 0
#define MCE2_M3_IPV6_ADDRESS_IDX 1
#define MCE2_M3_IP_ADDRESS_PREFERENCE_IDX 2
/*-----------------------------------------------------------------------------------------------------------------------------------*/
/* MCCH related BCCH Configuration per MBSFN area configuration parameters */
/* MCCH configuration parameters section */
#define MCE_CONFIG_STRING_MCCH_CONFIG_PER_MBSFN_AREA "mcch_config_per_mbsfn_area"
/* M3 configuration parameters names */
#define MCE_CONFIG_STRING_MCCH_MBSFN_AREA "mbsfn_area"
#define MCE_CONFIG_STRING_MCCH_PDCCH_LENGTH "pdcch_length"
#define MCE_CONFIG_STRING_MCCH_REPETITION_PERIOD "repetition_period"
#define MCE_CONFIG_STRING_MCCH_OFFSET "offset"
#define MCE_CONFIG_STRING_MCCH_MODIFICATION_PERIOD "modification_period"
#define MCE_CONFIG_STRING_MCCH_SF_ALLOCATION_INFO "subframe_allocation_info"
#define MCE_CONFIG_STRING_MCCH_MCS "mcs"
/* optname helpstr paramflags XXXptr defXXXval type numelt */
#define MCCH_PARAMS_DESC { \
{MCE_CONFIG_STRING_MCCH_MBSFN_AREA, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCCH_PDCCH_LENGTH, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCCH_REPETITION_PERIOD, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCCH_OFFSET, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCCH_MODIFICATION_PERIOD,NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCCH_SF_ALLOCATION_INFO, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCCH_MCS, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCCH_MBSFN_AREA_IDX 0
#define MCCH_PDCCH_LENGTH_IDX 1
#define MCCH_REPETITION_PERIOD_IDX 2
#define MCCH_OFFSET_IDX 3
#define MCCH_MODIFICATION_PERIOD_IDX 4
#define MCCH_SF_ALLOCATION_INFO_IDX 5
#define MCCH_MCS_IDX 6
/*-------------------------------------------------------------------------------------------------------------------------------------*/
/* M3 configuration parameters section name */
#define MCE_CONFIG_STRING_PLMN "plnm"
/* M3 configuration parameters names */
#define MCE_CONFIG_STRING_MCC "mcc"
#define MCE_CONFIG_STRING_MNC "mnc"
#define MCE_CONFIG_STRING_MNC_LENGTH "mnc_length"
/* optname helpstr paramflags XXXptr defXXXval type numelt */
#define MCE_PLMN_PARAMS_DESC { \
{MCE_CONFIG_STRING_MCC, NULL, 0, uptr:NULL, defuintval:1000, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MNC, NULL, 0, uptr:NULL, defuintval:1000, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MNC_LENGTH, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCE_CONFIG_STRING_MCC_IDX 0
#define MCE_CONFIG_STRING_MNC_IDX 1
#define MCE_CONFIG_STRING_MNC_LENGTH_IDX 2
/*-------------------------------------------------------------------------------------------------------------------------------------*/
#define MCE_CONFIG_STRING_MBMS_SCHEDULING_INFO "mbms_sched_info"
#define MCE_CONFIG_STRING_MCCH_UPDATE_TIME "mcch_update_time"
#define MCE_MBMS_SCHEDULING_INFO_PARAMS_DESC { \
{MCE_CONFIG_STRING_MCCH_UPDATE_TIME, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCE_CONFIG_STRING_MCCH_UPDATE_TIME_IDX 0
///*-------------------------------------------------------------------------------------------------------------------------------------*/
#define MCE_CONFIG_STRING_MBMS_AREA_CONFIGURATION_LIST "mbms_area_config_list"
#define MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD "common_sf_allocation_period"
#define MCE_CONFIG_STRING_MBMS_AREA_ID "mbms_area_id"
#define MCE_MBMS_AREA_CONFIGURATION_LIST_PARAMS_DESC { \
{MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MBMS_AREA_ID, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCE_CONFIG_STRING_COMMON_SF_ALLOCATION_PERIOD_IDX 0
#define MCE_CONFIG_STRING_MBMS_AREA_ID_IDX 1
//
///*-------------------------------------------------------------------------------------------------------------------------------------*/
#define MCE_CONFIG_STRING_PMCH_CONFIGURATION_LIST "pmch_config_list"
#define MCE_CONFIG_STRING_ALLOCATED_SF_END "allocated_sf_end"
#define MCE_CONFIG_STRING_DATA_MCS "data_mcs"
#define MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD "mch_scheduling_period"
#define MCE_MBMS_PMCH_CONFIGURATION_LIST_PARAMS_DESC { \
{MCE_CONFIG_STRING_ALLOCATED_SF_END, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_DATA_MCS, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCE_CONFIG_STRING_ALLOCATED_SF_END_IDX 0
#define MCE_CONFIG_STRING_DATA_MCS_IDX 1
#define MCE_CONFIG_STRING_MCH_SCHEDULING_PERIOD_IDX 2
/*-------------------------------------------------------------------------------------------------------------------------------------*/
#define MCE_CONFIG_STRING_MBMS_SESSION_LIST "mbms_session_list"
#define MCE_CONFIG_STRING_MBMS_SERVICE_ID "service_id"
#define MCE_CONFIG_STRING_MBMS_LCID_ID "lcid_id"
#define MCE_CONFIG_STRING_MBMS_LCID "lcid"
#define MCE_MBMS_MBMS_SESSION_LIST_DESC { \
{MCE_CONFIG_STRING_MBMS_SERVICE_ID, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT32, 0}, \
{MCE_CONFIG_STRING_MBMS_LCID_ID, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_MBMS_LCID, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCE_CONFIG_STRING_MBMS_SERVICE_ID_IDX 0
#define MCE_CONFIG_STRING_MBMS_LCID_ID_IDX 1
#define MCE_CONFIG_STRING_MBMS_LCID_IDX 2
/*-------------------------------------------------------------------------------------------------------------------------------------*/
#define MCE_CONFIG_STRING_MBMS_SF_CONFIGURATION_LIST "mbms_sf_config_list"
#define MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD "radioframe_allocation_period"
#define MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET "radioframe_alloocation_offset"
#define MCE_CONFIG_STRING_NUM_FRAME "num_frame"
#define MCE_CONFIG_STRING_SUBFRAME_ALLOCATION "subframe_allocation"
#define MCE_MBMS_MBMS_SF_CONFIGURATION_LIST_PARAMS_DESC { \
{MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{MCE_CONFIG_STRING_NUM_FRAME, NULL, 0, strptr:NULL, defstrval:"oneFrame", TYPE_STRING, 0}, \
{MCE_CONFIG_STRING_SUBFRAME_ALLOCATION, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
}
#define MCE_CONFIG_STRING_RADIOFRAME_ALLOCATION_PERIOD_IDX 0
#define MCE_CONFIG_STRING_RADIOFRAME_ALLOOCATION_OFFSET_IDX 1
#define MCE_CONFIG_STRING_NUM_FRAME_IDX 2
#define MCE_CONFIG_STRING_SUBFRAME_ALLOCATION_IDX 3
+82
View File
@@ -0,0 +1,82 @@
/*
* 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 openair2/ENB_APP/enb_paramdef_mme.h
* \brief definition of configuration parameters for MME modules
* \author Javier MORGADE
* \date 2019
* \version 0.1
* \company VICOMTECH Spain
* \email: javier.morgade@ieee.org
* \note
* \warning
*/
#include "common/config/config_paramdesc.h"
#include "RRC_paramsvalues.h"
/* mme configuration parameters names */
#define MME_CONFIG_STRING_MME_ID "MME_ID"
#define MME_CONFIG_STRING_MME_NAME "MME_name"
#define MME_CONFIG_STRING_MME_M3 "enable_mme_m3"
#define MMEPARAMS_DESC {\
{MME_CONFIG_STRING_MME_ID, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{MME_CONFIG_STRING_MME_NAME, NULL, 0, strptr:NULL, defstrval:"OAIMME", TYPE_STRING, 0}, \
{MME_CONFIG_STRING_MME_M3, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
}
#define MME_MME_ID_IDX 0
#define MME_MME_NAME_IDX 1
#define MME_ENABLE_MME_M3_IDX 2
#define MMEPARAMS_CHECK { \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
#define MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES"
#define MME_INTERFACE_NAME_FOR_M3_MME_IDX 0
#define MME_IPV4_ADDRESS_FOR_M3C_IDX 1
#define MME_PORT_FOR_M3C_IDX 2
/* interface configuration parameters names */
/* M3 interface configuration parameters names */
#define MME_CONFIG_STRING_MME_INTERFACE_NAME_FOR_M3_MCE "MME_INTERFACE_NAME_FOR_M3_MCE"
#define MME_CONFIG_STRING_MME_IPV4_ADDRESS_FOR_M3C "MME_IPV4_ADDRESS_FOR_M3C"
#define MME_CONFIG_STRING_MME_PORT_FOR_M3C "MME_PORT_FOR_M3C"
#define MME_NETPARAMS_DESC { \
{MME_CONFIG_STRING_MME_INTERFACE_NAME_FOR_M3_MCE, NULL, 0, strptr:&mme_interface_name_for_m3_mce, defstrval:"lo", TYPE_STRING, 0}, \
{MME_CONFIG_STRING_MME_IPV4_ADDRESS_FOR_M3C, NULL, 0, strptr:&mme_ipv4_address_for_m3c, defstrval:"127.0.0.18/24", TYPE_STRING, 0}, \
{MME_CONFIG_STRING_MME_PORT_FOR_M3C, NULL, 0, uptr:&mme_port_for_m3c, defintval:36444L, TYPE_UINT, 0}, \
}
+12 -52
View File
@@ -33,27 +33,14 @@
#include <pthread.h>
#include <arpa/inet.h>
void *receive_thread(void *args);
Protocol__FlexranMessage *flexran_agent_timeout(void* args);
int agent_task_created = 0;
/*
* enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
* and can interact with other itti tasks
*/
void *flexran_agent_task(void *args){
//flexran_agent_info_t *d = (flexran_agent_info_t *) args;
Protocol__FlexranMessage *msg;
void *data;
int size;
err_code_t err_code=0;
int priority = 0;
MessageDef *msg_p = NULL;
int result;
struct flexran_agent_timer_element_s * elem = NULL;
MessageDef *msg_p = NULL;
int result;
itti_mark_task_ready(TASK_FLEXRAN_AGENT);
@@ -71,20 +58,6 @@ void *flexran_agent_task(void *args){
case MESSAGE_TEST:
LOG_I(FLEXRAN_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
break;
case TIMER_HAS_EXPIRED:
msg = flexran_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, msg_p->ittiMsg.timer_has_expired.arg);
if (msg != NULL){
data=flexran_agent_pack_message(msg,&size);
elem = get_timer_entry(msg_p->ittiMsg.timer_has_expired.timer_id);
if (flexran_agent_msg_send(elem->agent_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
goto error;
}
LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
}
break;
default:
LOG_E(FLEXRAN_AGENT, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
@@ -93,10 +66,6 @@ void *flexran_agent_task(void *args){
result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
continue;
error:
if (err_code != 0)
LOG_E(FLEXRAN_AGENT,"flexran_agent_task: error %d occured\n",err_code);
} while (1);
return NULL;
@@ -202,16 +171,14 @@ int flexran_agent_start(mid_t mod_id)
*flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAC);
*/
/*Initialize the continuous stats update mechanism*/
flexran_agent_init_cont_stats_update(mod_id);
pthread_t t;
threadCreate(&t, receive_thread, flexran, "flexran", -1, OAI_PRIORITY_RT);
/* Register and initialize the control modules depending on capabilities.
* After registering, calling flexran_agent_get_*_xface() tells whether a
* control module is operational */
uint16_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",
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%s\n",
flexran_get_bs_id(mod_id), caps,
FLEXRAN_CAP_LOPHY(caps) ? " LOPHY" : "",
FLEXRAN_CAP_HIPHY(caps) ? " HIPHY" : "",
@@ -220,7 +187,8 @@ int flexran_agent_start(mid_t mod_id)
FLEXRAN_CAP_RLC(caps) ? " RLC" : "",
FLEXRAN_CAP_PDCP(caps) ? " PDCP" : "",
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)) {
flexran_agent_register_phy_xface(mod_id);
@@ -243,11 +211,16 @@ int flexran_agent_start(mid_t 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
*/
flexran_agent_init_timer();
flexran_agent_timer_init(mod_id);
/*
* start the enb agent task for tx and interaction with the underlying network function
@@ -288,16 +261,3 @@ error:
return 1;
}
Protocol__FlexranMessage *flexran_agent_timeout(void* args){
// flexran_agent_timer_args_t *timer_args = calloc(1, sizeof(*timer_args));
//memcpy (timer_args, args, sizeof(*timer_args));
flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
LOG_UI(FLEXRAN_AGENT, "flexran_agent %d timeout\n", timer_args->mod_id);
//LOG_I(FLEXRAN_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags);
//LOG_I(FLEXRAN_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags);
return NULL;
}
+1
View File
@@ -40,6 +40,7 @@
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "common/utils/LOG/log.h"
#include "assertions.h"
+45 -24
View File
@@ -21,7 +21,7 @@
/*! \file flexran_agent_common.c
* \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
* \version 0.1
*/
@@ -38,6 +38,7 @@
#include "flexran_agent_phy.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_s1ap.h"
//#include "PHY/extern.h"
#include "common/utils/LOG/log.h"
#include "flexran_agent_mac_internal.h"
@@ -128,6 +129,7 @@ int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessa
hello_msg->bs_id = flexran_get_bs_id(mod_id);
hello_msg->has_bs_id = 1;
hello_msg->n_capabilities = flexran_get_capabilities(mod_id, &hello_msg->capabilities);
hello_msg->n_splits = flexran_get_splits(mod_id, &hello_msg->splits);
*msg = malloc(sizeof(Protocol__FlexranMessage));
if(*msg == NULL)
@@ -161,6 +163,7 @@ int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg) {
free(msg->hello_msg->header);
free(msg->hello_msg->capabilities);
free(msg->hello_msg->splits);
free(msg->hello_msg);
free(msg);
return 0;
@@ -337,6 +340,9 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
free(reply->cell_config[i]);
}
if (reply->s1ap)
flexran_agent_free_s1ap_cell_config(&reply->s1ap);
free(reply->cell_config);
free(reply);
@@ -598,21 +604,7 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
goto error;
ue_config_reply_msg->header = header;
ue_config_reply_msg->n_ue_config = 0;
if (flexran_agent_get_rrc_xface(mod_id))
ue_config_reply_msg->n_ue_config = flexran_get_rrc_num_ues(mod_id);
else if (flexran_agent_get_mac_xface(mod_id))
ue_config_reply_msg->n_ue_config = flexran_get_mac_num_ues(mod_id);
if (flexran_agent_get_rrc_xface(mod_id) && flexran_agent_get_mac_xface(mod_id)
&& flexran_get_rrc_num_ues(mod_id) != flexran_get_mac_num_ues(mod_id)) {
const int nrrc = flexran_get_rrc_num_ues(mod_id);
const int nmac = flexran_get_mac_num_ues(mod_id);
ue_config_reply_msg->n_ue_config = nrrc < nmac ? nrrc : nmac;
LOG_E(FLEXRAN_AGENT, "%s(): different numbers of UEs in RRC (%d) and MAC (%d), reporting for %lu UEs\n",
__func__, nrrc, nmac, ue_config_reply_msg->n_ue_config);
}
ue_config_reply_msg->n_ue_config = flexran_agent_get_num_ues(mod_id);
Protocol__FlexUeConfig **ue_config;
@@ -769,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]->has_carrier_index = 1;
}
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));
@@ -910,14 +905,19 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
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 {
// initiate_soft_restart(mod_id, enb_config->cell_config[0]);
}
if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->has_x2_ho_net_control) {
if (flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control) < 0) {
} else 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)
&& enb_config->cell_config[0]->has_x2_ho_net_control) {
LOG_I(FLEXRAN_AGENT,
"setting X2 HO NetControl to %d\n",
enb_config->cell_config[0]->x2_ho_net_control);
const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control);
if (rc < 0)
LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network");
}
}
*msg = NULL;
@@ -935,3 +935,24 @@ int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Proto
*msg = NULL;
return 0;
}
int flexran_agent_get_num_ues(mid_t mod_id) {
const int has_rrc = flexran_agent_get_rrc_xface(mod_id) != NULL;
const int has_mac = flexran_agent_get_mac_xface(mod_id) != NULL;
DevAssert(has_rrc || has_mac);
if (has_rrc && !has_mac)
return flexran_get_rrc_num_ues(mod_id);
if (!has_rrc && has_mac)
return flexran_get_mac_num_ues(mod_id);
/* has both */
const int nrrc = flexran_get_rrc_num_ues(mod_id);
const int nmac = flexran_get_mac_num_ues(mod_id);
if (nrrc != nmac) {
const int n_ue = nrrc < nmac ? nrrc : nmac;
LOG_E(FLEXRAN_AGENT, "%s(): different numbers of UEs in RRC (%d) and MAC (%d), reporting for %d UEs\n",
__func__, nrrc, nmac, n_ue);
return n_ue;
}
return nrrc;
}
+13 -8
View File
@@ -150,24 +150,25 @@ Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
uint32_t size);
/* Function to be used to send a message to a dispatcher once the appropriate event is triggered. */
Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args);
Protocol__FlexranMessage *flexran_agent_handle_timed_task(
mid_t mod_id,
Protocol__FlexranMessage *msg);
/*Top level Statistics hanlder*/
Protocol__FlexranMessage *flexran_agent_send_stats_reply(
mid_t mod_id,
const Protocol__FlexranMessage *msg);
int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
/* Function to be used to handle reply message . */
int flexran_agent_stats_reply(mid_t enb_id, xid_t xid, const report_config_t *report_config, Protocol__FlexranMessage **msg);
int flexran_agent_stats_reply(mid_t enb_id, xid_t xid, const Protocol__FlexStatsRequest *stats_req, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_stats_reply(Protocol__FlexranMessage *msg);
/* Top level Statistics request protocol message constructor and destructor */
int flexran_agent_stats_request(mid_t mod_id, xid_t xid, const stats_request_config_t *report_config, Protocol__FlexranMessage **msg);
//int flexran_agent_stats_request(mid_t mod_id, xid_t xid, const stats_request_config_t *report_config, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_stats_request(Protocol__FlexranMessage *msg);
err_code_t flexran_agent_init_cont_stats_update(mid_t mod_id);
err_code_t flexran_agent_enable_cont_stats_update(mid_t mod_id, xid_t xid, stats_request_config_t *stats_req) ;
err_code_t flexran_agent_disable_cont_stats_update(mid_t mod_id);
/* Handle a received eNB config reply message as an "order" to reconfigure. It
* does not come as a reconfiguration message as this is a "structured"
* ProtoBuf message (as opposed to "unstructured" YAML). There is no destructor
@@ -183,4 +184,8 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void* params, Prot
* request message. */
int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
/* Return the number of UEs in the BS of this agent across RRC/MAC. If they
* disagree, prints an error and returns the minimum of both. */
int flexran_agent_get_num_ues(mid_t mod_id);
#endif
+1 -64
View File
@@ -107,36 +107,6 @@ typedef uint8_t lcid_t;
typedef int32_t err_code_t;
/*---------Timer Enums --------- */
typedef enum {
/* oneshot timer: */
FLEXRAN_AGENT_TIMER_TYPE_ONESHOT = 0,
/* periodic timer */
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC = 1,
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_TYPE_EVENT_DRIVEN = 2,
/* Max number of states available */
FLEXRAN_AGENT_TIMER_TYPE_MAX,
} flexran_agent_timer_type_t;
typedef enum {
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_STATE_INACTIVE = 0x0,
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_STATE_ACTIVE = 0x1,
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_STATE_STOPPED = 0x2,
/* Max number of states available */
FLEXRAN_AGENT_TIMER_STATE_MAX,
} flexran_agent_timer_state_t;
#define FLEXRAN_CAP_LOPHY(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)) > 0)
#define FLEXRAN_CAP_HIPHY(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)) > 0)
@@ -146,6 +116,7 @@ typedef enum {
#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_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 {
ENB_NORMAL_OPERATION = 0x0,
@@ -193,38 +164,4 @@ typedef struct {
} agent_reconf_rrc;
/* These structs will be used to give
instructions for the type of stats reports
we need to create */
typedef struct {
uint16_t ue_rnti;
uint32_t ue_report_flags; /* Indicates the report elements
required for this UE id. See
FlexRAN specification 1.2.4.2 */
} ue_report_type_t;
typedef struct {
uint16_t cc_id;
uint32_t cc_report_flags; /* Indicates the report elements
required for this CC index. See
FlexRAN specification 1.2.4.3 */
} cc_report_type_t;
typedef struct {
int nr_ue;
ue_report_type_t *ue_report_type;
int nr_cc;
cc_report_type_t *cc_report_type;
} report_config_t;
typedef struct stats_request_config_s{
uint8_t report_type;
uint8_t report_frequency;
uint16_t period; /*In number of subframes*/
report_config_t *config;
} stats_request_config_t;
#endif
+4
View File
@@ -35,6 +35,7 @@
#include "flexran_agent_mac_defs.h"
#include "flexran_agent_rrc_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 */
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);
/* 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);
/* 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 */
extern int harq_pid_updated[NUM_MAX_UE][8];
extern int harq_pid_round[NUM_MAX_UE][8];
+126 -385
View File
@@ -31,6 +31,7 @@
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "flexran_agent_timer.h"
#include "flexran_agent_ran_api.h"
#include "common/utils/LOG/log.h"
@@ -154,39 +155,20 @@ void * flexran_agent_pack_message(Protocol__FlexranMessage *msg,
return NULL;
}
Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args) {
Protocol__FlexranMessage *flexran_agent_handle_timed_task(
mid_t mod_id,
Protocol__FlexranMessage *msg) {
err_code_t err_code;
flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
Protocol__FlexranMessage *timed_task, *reply_message;
timed_task = timer_args->msg;
err_code = ((*agent_messages_callback[timed_task->msg_case-1][timed_task->msg_dir-1])(timer_args->mod_id, (void *) timed_task, &reply_message));
if ( err_code < 0 ){
goto error;
Protocol__FlexranMessage *reply_message;
err_code = ((*agent_messages_callback[msg->msg_case-1][msg->msg_dir-1])(
mod_id, msg, &reply_message));
if (err_code < 0) {
LOG_E(FLEXRAN_AGENT, "could not handle message: errno %d occured\n", err_code);
return NULL;
}
return reply_message;
error:
LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
return NULL;
}
Protocol__FlexranMessage* flexran_agent_process_timeout(long timer_id, void* timer_args){
struct flexran_agent_timer_element_s *found = get_timer_entry(timer_id);
if (found == NULL ) goto error;
LOG_D(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx 0x%lx\n", found, timer_id, found->timer_id);
if (timer_args == NULL)
LOG_W(FLEXRAN_AGENT,"null timer args\n");
return found->cb(timer_args);
error:
LOG_E(FLEXRAN_AGENT, "can't get the timer element\n");
return NULL;
}
err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg) {
@@ -196,335 +178,175 @@ err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg)
/*
Top Level Statistics Report
*/
*/
int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg){
// TODO: Must deal with sanitization of input
// TODO: Must check if RNTIs and cell ids of the request actually exist
// TODO: Must resolve conflicts among stats requests
int i;
err_code_t err_code = 0;
xid_t xid;
uint32_t usec_interval, sec_interval;
//TODO: We do not deal with multiple CCs at the moment and eNB id is 0
int enb_id = mod_id;
//eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
//UE_list_t *eNB_UE_list= &eNB->UE_list;
report_config_t report_config;
uint32_t ue_flags = 0;
uint32_t c_flags = 0;
int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
*msg = NULL;
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexStatsRequest *stats_req = input->stats_request_msg;
xid = (stats_req->header)->xid;
const xid_t xid = stats_req->header->xid;
// Check the type of request that is made
switch(stats_req->body_case) {
case PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST: ;
Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF) {
/*Disable both periodic and continuous updates*/
// flexran_agent_disable_cont_stats_update(mod_id);
flexran_agent_destroy_timer_by_task_id(xid);
*msg = NULL;
return 0;
} else { //One-off, periodical or continuous reporting
//Set the proper flags
ue_flags = comp_req->ue_report_flags;
c_flags = comp_req->cell_report_flags;
//Create a list of all eNB RNTIs and cells
if (stats_req->body_case != PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST) {
LOG_E(FLEXRAN_AGENT, "only complete stats are supported at the moment\n");
return -1;
}
Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
//Set the number of UEs and create list with their RNTIs stats configs
report_config.nr_ue = 0;
if (flexran_agent_get_rrc_xface(mod_id))
report_config.nr_ue = flexran_get_rrc_num_ues(mod_id);
else if (flexran_agent_get_mac_xface(mod_id))
report_config.nr_ue = flexran_get_mac_num_ues(mod_id);
if (flexran_agent_get_rrc_xface(mod_id) && flexran_agent_get_mac_xface(mod_id)
&& flexran_get_rrc_num_ues(mod_id) != flexran_get_mac_num_ues(mod_id)) {
const int nrrc = flexran_get_rrc_num_ues(mod_id);
const int nmac = flexran_get_mac_num_ues(mod_id);
report_config.nr_ue = nrrc < nmac ? nrrc : nmac;
LOG_E(FLEXRAN_AGENT, "%s(): different numbers of UEs in RRC (%d) and MAC (%d), reporting for %d UEs\n",
__func__, nrrc, nmac, report_config.nr_ue);
}
report_config.ue_report_type = malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
if (report_config.ue_report_type == NULL) {
// TODO: Add appropriate error code
err_code = -100;
goto error;
}
if (flexran_agent_get_rrc_xface(mod_id)) {
rnti_t rntis[report_config.nr_ue];
flexran_get_rrc_rnti_list(mod_id, rntis, report_config.nr_ue);
for (i = 0; i < report_config.nr_ue; i++) {
report_config.ue_report_type[i].ue_rnti = rntis[i];
report_config.ue_report_type[i].ue_report_flags = ue_flags;
}
}
if (flexran_agent_get_mac_xface(mod_id) && !flexran_agent_get_rrc_xface(mod_id)) {
for (i = 0; i < report_config.nr_ue; i++) {
const int UE_id = flexran_get_mac_ue_id(mod_id, i);
report_config.ue_report_type[i].ue_rnti = flexran_get_mac_ue_crnti(enb_id, UE_id);
report_config.ue_report_type[i].ue_report_flags = ue_flags;
}
}
//Set the number of CCs and create a list with the cell stats configs
report_config.nr_cc = MAX_NUM_CCs;
report_config.cc_report_type = malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
if (report_config.cc_report_type == NULL) {
// TODO: Add appropriate error code
err_code = -100;
goto error;
}
for (i = 0; i < report_config.nr_cc; i++) {
//TODO: Must fill in the proper cell ids
report_config.cc_report_type[i].cc_id = i;
report_config.cc_report_type[i].cc_report_flags = c_flags;
}
/* Check if request was periodical */
if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL) {
/* Create a one off flexran message as an argument for the periodical task */
Protocol__FlexranMessage *timer_msg = NULL;
stats_request_config_t request_config;
request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
request_config.period = 0;
/* Need to make sure that the ue flags are saved (Bug) */
if (report_config.nr_ue == 0) {
report_config.nr_ue = 1;
report_config.ue_report_type = malloc(sizeof(ue_report_type_t));
if (report_config.ue_report_type == NULL) {
// TODO: Add appropriate error code
err_code = -100;
goto error;
}
report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
report_config.ue_report_type[0].ue_report_flags = ue_flags;
}
request_config.config = &report_config;
if (flexran_agent_stats_request(enb_id, xid, &request_config, &timer_msg) == -1) {
err_code = -100;
goto error;
}
/* Create a timer */
long timer_id = 0;
flexran_agent_timer_args_t *timer_args = malloc(sizeof(flexran_agent_timer_args_t));
memset (timer_args, 0, sizeof(flexran_agent_timer_args_t));
timer_args->mod_id = enb_id;
timer_args->msg = timer_msg;
/*Convert subframes to usec time*/
usec_interval = 1000*comp_req->sf;
sec_interval = 0;
/*add seconds if required*/
if (usec_interval >= 1000*1000) {
sec_interval = usec_interval/(1000*1000);
usec_interval = usec_interval%(1000*1000);
}
flexran_agent_create_timer(sec_interval, usec_interval, FLEXRAN_AGENT_DEFAULT,
enb_id, FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid,
flexran_agent_handle_timed_task,(void*) timer_args, &timer_id);
} else if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS) {
/*If request was for continuous updates, disable the previous configuration and
set up a new one*/
flexran_agent_disable_cont_stats_update(mod_id);
stats_request_config_t request_config;
request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
request_config.period = 0;
/* Need to make sure that the ue flags are saved (Bug) */
if (report_config.nr_ue == 0) {
report_config.nr_ue = 1;
report_config.ue_report_type = malloc(sizeof(ue_report_type_t));
if (report_config.ue_report_type == NULL) {
// TODO: Add appropriate error code
err_code = -100;
goto error;
}
report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
report_config.ue_report_type[0].ue_report_flags = ue_flags;
}
request_config.config = &report_config;
flexran_agent_enable_cont_stats_update(enb_id, xid, &request_config);
}
}
break;
case PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST:;
Protocol__FlexCellStatsRequest *cell_req = stats_req->cell_stats_request;
// UE report config will be blank
report_config.nr_ue = 0;
report_config.ue_report_type = NULL;
report_config.nr_cc = cell_req->n_cell;
report_config.cc_report_type = malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
if (report_config.cc_report_type == NULL) {
// TODO: Add appropriate error code
err_code = -100;
goto error;
}
for (i = 0; i < report_config.nr_cc; i++) {
//TODO: Must fill in the proper cell ids
report_config.cc_report_type[i].cc_id = cell_req->cell[i];
report_config.cc_report_type[i].cc_report_flags = cell_req->flags;
}
break;
case PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST:;
Protocol__FlexUeStatsRequest *ue_req = stats_req->ue_stats_request;
// Cell report config will be blank
report_config.nr_cc = 0;
report_config.cc_report_type = NULL;
report_config.nr_ue = ue_req->n_rnti;
report_config.ue_report_type = malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
if (report_config.ue_report_type == NULL) {
// TODO: Add appropriate error code
err_code = -100;
goto error;
}
for (i = 0; i < report_config.nr_ue; i++) {
const int UE_id = flexran_get_mac_ue_id(mod_id, i);
report_config.ue_report_type[i].ue_rnti = ue_req->rnti[UE_id];
report_config.ue_report_type[i].ue_report_flags = ue_req->flags;
}
break;
switch (comp_req->report_frequency) {
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF:
flexran_agent_destroy_timer(mod_id, xid);
return 0;
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE:
LOG_E(FLEXRAN_AGENT, "one-shot timer not implemented yet\n");
return -1;
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL:
/* Create a one off flexran message as an argument for the periodical task */
LOG_I(FLEXRAN_AGENT, "periodical timer xid %d cell_flags %d ue_flags %d\n",
xid, comp_req->cell_report_flags, comp_req->ue_report_flags);
flexran_agent_create_timer(mod_id, comp_req->sf,
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid,
flexran_agent_send_stats_reply, input);
/* return 1: do not dispose comp_req message we received, we still need it */
return 1;
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS:
LOG_E(FLEXRAN_AGENT, "unsupported report frequency continuous\n");
return -1;
default:
//TODO: Add appropriate error code
err_code = -100;
goto error;
LOG_E(FLEXRAN_AGENT, "unknown report frequency\n");
return -1;
}
if (flexran_agent_stats_reply(enb_id, xid, &report_config, msg )) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
goto error;
}
if (report_config.ue_report_type)
free(report_config.ue_report_type);
if (report_config.cc_report_type)
free(report_config.cc_report_type);
return 0;
error :
LOG_E(FLEXRAN_AGENT, "%s(): errno %d occured\n", __func__, err_code);
return err_code;
}
/*
Top level reply
*/
Protocol__FlexranMessage *flexran_agent_send_stats_reply(
mid_t mod_id,
const Protocol__FlexranMessage *msg) {
const Protocol__FlexStatsRequest *stats_req = msg->stats_request_msg;
const xid_t xid = stats_req->header->xid;
int flexran_agent_stats_reply(mid_t enb_id, xid_t xid, const report_config_t *report_config, Protocol__FlexranMessage **msg){
Protocol__FlexranMessage *reply = NULL;
err_code_t rc = flexran_agent_stats_reply(mod_id, xid, stats_req, &reply);
if (rc < 0) {
LOG_E(FLEXRAN_AGENT, "%s(): errno %d occured, cannot send stats_reply\n",
__func__, rc);
return NULL;
}
return reply;
}
int flexran_agent_stats_reply(mid_t enb_id,
xid_t xid,
const Protocol__FlexStatsRequest *stats_req,
Protocol__FlexranMessage **msg) {
Protocol__FlexHeader *header = NULL;
Protocol__FlexUeStatsReport **ue_report = NULL;
Protocol__FlexCellStatsReport **cell_report = NULL;
Protocol__FlexStatsReply *stats_reply_msg = NULL;
err_code_t err_code = PROTOCOL__FLEXRAN_ERR__UNEXPECTED;
int i,j;
AssertFatal(stats_req->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST,
"%s() handles only complete stats requests\n",
__func__);
const uint32_t cell_flags = stats_req->complete_stats_request->cell_report_flags;
const uint32_t ue_flags = stats_req->complete_stats_request->ue_report_flags;
if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0) {
goto error;
int n_ue = flexran_agent_get_num_ues(enb_id);
rnti_t rntis[n_ue];
if (flexran_agent_get_rrc_xface(enb_id))
flexran_get_rrc_rnti_list(enb_id, rntis, n_ue);
if (flexran_agent_get_mac_xface(enb_id) && !flexran_agent_get_rrc_xface(enb_id)) {
for (int i = 0; i < n_ue; i++) {
const int UE_id = flexran_get_mac_ue_id(enb_id, i);
rntis[i] = flexran_get_mac_ue_crnti(enb_id, UE_id);
}
}
stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
if (stats_reply_msg == NULL) {
goto error;
}
protocol__flex_stats_reply__init(stats_reply_msg);
stats_reply_msg->header = header;
stats_reply_msg->n_ue_report = report_config->nr_ue;
stats_reply_msg->n_cell_report = report_config->nr_cc;
// UE report
ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *) * report_config->nr_ue);
int n_cc = MAX_NUM_CCs;
ue_report = calloc(n_ue, sizeof(Protocol__FlexUeStatsReport *));
if (ue_report == NULL) {
goto error;
}
for (i = 0; i < report_config->nr_ue; i++) {
ue_report[i] = malloc(sizeof(Protocol__FlexUeStatsReport));
if (ue_report[i] == NULL) {
goto error;
}
protocol__flex_ue_stats_report__init(ue_report[i]);
ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
ue_report[i]->has_rnti = 1;
ue_report[i]->has_flags = 1; /* actual flags are filled in the CMs below */
for (int i = 0; i < n_ue; i++) {
ue_report[i] = malloc(sizeof(Protocol__FlexUeStatsReport));
if (ue_report[i] == NULL) {
goto error;
}
protocol__flex_ue_stats_report__init(ue_report[i]);
ue_report[i]->rnti = rntis[i];
ue_report[i]->has_rnti = 1;
ue_report[i]->has_flags = 1; /* actual flags are filled in the CMs below */
}
// cell rpoert
cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *) * report_config->nr_cc);
cell_report = calloc(n_cc, sizeof(Protocol__FlexCellStatsReport *));
if (cell_report == NULL) {
goto error;
}
for (i = 0; i < report_config->nr_cc; i++) {
cell_report[i] = malloc(sizeof(Protocol__FlexCellStatsReport));
if(cell_report[i] == NULL) {
goto error;
}
protocol__flex_cell_stats_report__init(cell_report[i]);
cell_report[i]->carrier_index = report_config->cc_report_type[i].cc_id;
cell_report[i]->has_carrier_index = 1;
cell_report[i]->has_flags = 1; /* actual flags are filled in the CMs below */
for (int i = 0; i < n_cc; i++) {
cell_report[i] = malloc(sizeof(Protocol__FlexCellStatsReport));
if(cell_report[i] == NULL) {
goto error;
}
protocol__flex_cell_stats_report__init(cell_report[i]);
cell_report[i]->carrier_index = i;
cell_report[i]->has_carrier_index = 1;
cell_report[i]->has_flags = 1; /* actual flags are filled in the CMs below */
}
/* MAC reply split */
if (flexran_agent_get_mac_xface(enb_id)
&& flexran_agent_mac_stats_reply(enb_id, report_config, ue_report, cell_report) < 0) {
&& (flexran_agent_mac_stats_reply_ue(enb_id, ue_report, n_ue, ue_flags) < 0
|| flexran_agent_mac_stats_reply_cell(enb_id, cell_report, n_cc, cell_flags) < 0)) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
goto error;
}
/* RRC reply split */
if (flexran_agent_get_rrc_xface(enb_id)
&& flexran_agent_rrc_stats_reply(enb_id, report_config, ue_report, cell_report) < 0) {
&& flexran_agent_rrc_stats_reply(enb_id, ue_report, n_ue, ue_flags) < 0) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
goto error;
}
/* PDCP reply split */
if (flexran_agent_get_pdcp_xface(enb_id)
&& flexran_agent_pdcp_stats_reply(enb_id, report_config, ue_report, cell_report) < 0) {
&& flexran_agent_pdcp_stats_reply(enb_id, ue_report, n_ue, ue_flags) < 0) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
goto error;
}
/* GTP reply split, currently performed through RRC module */
if (flexran_agent_get_rrc_xface(enb_id)
&& flexran_agent_rrc_gtp_stats_reply(enb_id, report_config, ue_report, cell_report) < 0) {
&& flexran_agent_rrc_gtp_stats_reply(enb_id, ue_report, n_ue, ue_flags) < 0) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
goto error;
}
stats_reply_msg->cell_report = cell_report;
stats_reply_msg->ue_report = ue_report;
*msg = malloc(sizeof(Protocol__FlexranMessage));
if(*msg == NULL) {
/* 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) {
goto error;
}
stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
AssertFatal(stats_reply_msg, "no memory for stats_reply_msg\n");
protocol__flex_stats_reply__init(stats_reply_msg);
stats_reply_msg->header = header;
stats_reply_msg->n_ue_report = n_ue;
stats_reply_msg->ue_report = ue_report;
stats_reply_msg->n_cell_report = n_cc;
stats_reply_msg->cell_report = cell_report;
*msg = malloc(sizeof(Protocol__FlexranMessage));
AssertFatal(*msg, "no memory for stats_reply container msg\n");
protocol__flexran_message__init(*msg);
(*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
(*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
@@ -546,7 +368,7 @@ error :
}
if (ue_report != NULL) {
for (j = 0; j < report_config->nr_ue; j++) {
for (int j = 0; j < n_ue; j++) {
if (ue_report[j] != NULL) {
free(ue_report[j]);
}
@@ -556,7 +378,7 @@ error :
}
if (cell_report != NULL) {
for (j = 0; j < report_config->nr_cc; j++) {
for (int j = 0; j < n_cc; j++) {
if (cell_report[j] != NULL) {
free(cell_report[j]);
}
@@ -572,6 +394,7 @@ error :
Top Level Request
*/
/*
int flexran_agent_stats_request(mid_t mod_id,
xid_t xid,
const stats_request_config_t *report_config,
@@ -678,6 +501,7 @@ int flexran_agent_stats_request(mid_t mod_id,
//LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
return -1;
}
*/
int flexran_agent_destroy_stats_request(Protocol__FlexranMessage *msg) {
if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG)
@@ -708,6 +532,8 @@ int flexran_agent_destroy_stats_reply(Protocol__FlexranMessage *msg)
flexran_agent_mac_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_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)
free(msg->stats_reply_msg->cell_report[i]);
for (int i = 0; i < msg->stats_reply_msg->n_ue_report; ++i)
@@ -719,88 +545,3 @@ int flexran_agent_destroy_stats_reply(Protocol__FlexranMessage *msg)
free(msg);
return 0;
}
err_code_t flexran_agent_disable_cont_stats_update(mid_t mod_id) {
/*Disable the continuous updates for the MAC*/
if (pthread_mutex_lock(stats_context[mod_id].mutex)) {
goto error;
}
stats_context[mod_id].cont_update = 0;
stats_context[mod_id].xid = 0;
if (stats_context[mod_id].stats_req != NULL) {
flexran_agent_destroy_flexran_message(stats_context[mod_id].stats_req);
}
if (stats_context[mod_id].prev_stats_reply != NULL) {
flexran_agent_destroy_flexran_message(stats_context[mod_id].prev_stats_reply);
}
if (pthread_mutex_unlock(stats_context[mod_id].mutex)) {
goto error;
}
return 0;
error:
LOG_E(FLEXRAN_AGENT, "stats_context for eNB %d is not initialized\n", mod_id);
return -1;
}
err_code_t flexran_agent_enable_cont_stats_update(mid_t mod_id,
xid_t xid, stats_request_config_t *stats_req) {
if (pthread_mutex_lock(stats_context[mod_id].mutex)) {
goto error;
}
Protocol__FlexranMessage *req_msg = NULL;
flexran_agent_stats_request(mod_id, xid, stats_req, &req_msg);
if (req_msg != NULL) {
stats_context[mod_id].stats_req = req_msg;
stats_context[mod_id].prev_stats_reply = NULL;
stats_context[mod_id].cont_update = 1;
stats_context[mod_id].xid = xid;
}
if (pthread_mutex_unlock(stats_context[mod_id].mutex)) {
goto error;
}
return 0;
error:
LOG_E(FLEXRAN_AGENT, "stats_context for eNB %d is not initialized\n", mod_id);
return -1;
}
err_code_t flexran_agent_init_cont_stats_update(mid_t mod_id) {
/*Initially the continuous update is set to false*/
stats_context[mod_id].cont_update = 0;
stats_context[mod_id].is_initialized = 1;
stats_context[mod_id].stats_req = NULL;
stats_context[mod_id].prev_stats_reply = NULL;
stats_context[mod_id].mutex = calloc(1, sizeof(pthread_mutex_t));
if (stats_context[mod_id].mutex == NULL)
goto error;
if (pthread_mutex_init(stats_context[mod_id].mutex, NULL) != 0)
goto error;
return 0;
error:
return -1;
}
err_code_t flexran_agent_destroy_cont_stats_update(mid_t mod_id) {
stats_context[mod_id].cont_update = 0;
stats_context[mod_id].is_initialized = 0;
flexran_agent_destroy_flexran_message(stats_context[mod_id].stats_req);
flexran_agent_destroy_flexran_message(stats_context[mod_id].prev_stats_reply);
free(stats_context[mod_id].mutex);
return 1;
}
+254 -23
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,15 +3687,15 @@ 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:
n_caps = 5;
@@ -3509,11 +3708,10 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
(*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__HIMAC;
(*caps)[4] = PROTOCOL__FLEX_BS_CAPABILITY__RLC;
break;
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));
@@ -3525,48 +3723,81 @@ 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__SDAP)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
break;
case ngran_eNB_DU:
case ngran_gNB_DU:
mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC);
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC);
break;
case ngran_eNB:
case ngran_ng_eNB:
case ngran_gNB:
mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
| (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__HIPHY)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
| (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__S1AP);
break;
case ngran_eNB_MBMS_STA:
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
break;
}
return mask;
}
size_t flexran_get_splits(mid_t mod_id, Protocol__FlexBsSplit **splits) {
size_t n_splits = 0;
*splits = NULL;
if (rrc_is_present(mod_id) && !NODE_IS_MONOLITHIC(RC.rrc[mod_id]->node_type))
n_splits++;
if (NFAPI_MODE != NFAPI_MONOLITHIC)
n_splits++;
if (RC.ru && RC.ru[mod_id] && RC.ru[mod_id]->if_south != LOCAL_RF)
n_splits++;
if (n_splits == 0)
return 0;
AssertFatal(n_splits < 3, "illegal number of splits (%lu)\n", n_splits);
*splits = calloc(n_splits, sizeof(Protocol__FlexBsSplit));
AssertFatal(*splits, "could not allocate Protocol__FlexBsSplit array\n");
int n = 0;
if (rrc_is_present(mod_id) && !NODE_IS_MONOLITHIC(RC.rrc[mod_id]->node_type))
(*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__F1;
if (NFAPI_MODE != NFAPI_MONOLITHIC)
(*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__nFAPI;
if (RC.ru && RC.ru[mod_id] && RC.ru[mod_id]->if_south == REMOTE_IF4p5)
(*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__IF4p5;
if (RC.ru && RC.ru[mod_id] && RC.ru[mod_id]->if_south == REMOTE_IF5)
(*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__IF5;
DevAssert(n == n_splits);
return n_splits;
}
+35 -1
View File
@@ -44,6 +44,7 @@
#include "RRC/LTE/rrc_eNB_UE_context.h"
#include "PHY/phy_extern.h"
#include "common/utils/LOG/log.h"
#include "nfapi/oai_integration/vendor_ext.h"
/****************************
* get generic info from RAN
@@ -651,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 */
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 **************************/
/* Get the DL slice ID for a UE */
@@ -803,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 */
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 *****************/
/* get an ID for this BS (or part of a BS) */
uint64_t flexran_get_bs_id(mid_t mod_id);
@@ -814,4 +843,9 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
/* get the capabilities supported by the underlying network function as a bit
* 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,
* return the number and stores list of this length in splits. If there are
* zero capabilities, splits will be NULL */
size_t flexran_get_splits(mid_t mod_id, Protocol__FlexBsSplit **splits);
@@ -33,7 +33,7 @@
#include <stdio.h>
#include "flexran_agent_task_manager.h"
#include "flexran_agent_common.c"
#include "flexran_agent_common.h"
/* Util macros */
+232 -153
View File
@@ -21,187 +21,266 @@
/*! \file flexran_agent_timer.c
* \brief FlexRAN Timer
* \author shahab SHARIAT BAGHERI
* \date 2017
* \version 0.1
*/
/*
* timer primitives
* \author Robert Schmidt
* \date 2019
* \version 0.2
*/
#include "flexran_agent_timer.h"
#include "flexran_agent_extern.h"
#include <pthread.h>
#include <sys/timerfd.h>
//struct flexran_agent_map agent_map;
flexran_agent_timer_instance_t timer_instance;
int agent_timer_init = 0;
err_code_t flexran_agent_init_timer(void) {
LOG_I(FLEXRAN_AGENT, "init RB tree\n");
#define MAX_NUM_TIMERS 10
if (!agent_timer_init) {
RB_INIT(&timer_instance.flexran_agent_head);
agent_timer_init = 1;
typedef struct flexran_agent_timer_element_s {
mid_t mod_id;
xid_t xid; /* The id of the task as received by the controller message*/
uint32_t sf;
uint64_t next;
flexran_agent_timer_callback_t cb;
Protocol__FlexranMessage *msg;
} flexran_agent_timer_element_t;
typedef struct flexran_agent_timer_extern_source_s {
pthread_mutex_t mutex_sync;
pthread_cond_t cond;
int wait;
} flexran_agent_timer_extern_source_t;
struct timesync {
void *param_sync;
void (*fsync)(void *);
pthread_t thread;
uint64_t current;
uint64_t next;
int timer_num;
flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS];
pthread_mutex_t mutex_timer;
int exit;
};
struct timesync timesync[NUM_MAX_ENB];
int flexran_agent_timer_signal_init(struct timesync *sync);
int flexran_agent_timer_source_setup(struct timesync *sync);
void *flexran_agent_timer_thread(void *args);
void flexran_agent_timer_remove_internal(struct timesync *sync, int index);
void flexran_agent_timer_process(flexran_agent_timer_element_t *t);
err_code_t flexran_agent_timer_init(mid_t mod_id) {
struct timesync *sync = &timesync[mod_id];
sync->current = 0;
sync->next = 0;
sync->timer_num = 0;
for (int i = 0; i < MAX_NUM_TIMERS; ++i)
sync->timer[i] = NULL;
pthread_mutex_init(&sync->mutex_timer, NULL);
sync->exit = 0;
/* if there is a MAC, we assume we can have a tick from the MAC interface
* (external tick source). Otherwise, generate a tick internally via the
* timerfd linux library. The init functions set everything up and the thread
* will use whatever is available. */
int (*init)(struct timesync *) = flexran_agent_get_mac_xface(mod_id) ?
flexran_agent_timer_signal_init : flexran_agent_timer_source_setup;
if (init(timesync) < 0
|| pthread_create(&sync->thread, NULL, flexran_agent_timer_thread, sync) != 0) {
sync->thread = 0;
if (sync->param_sync)
free(sync->param_sync);
LOG_E(FLEXRAN_AGENT, "could not start timer thread\n");
return TIMER_SETUP_FAILED;
}
return PROTOCOL__FLEXRAN_ERR__NO_ERR;
}
RB_GENERATE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
void flexran_agent_timer_exit(mid_t mod_id) {
timesync[mod_id].exit = 1;
}
/* The timer_id might not be the best choice for the comparison */
int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b) {
if (a->timer_id < b->timer_id) return -1;
void flexran_agent_timer_source_sync(void *sync) {
int fd = *(int *)sync;
uint64_t occ;
int rc __attribute__((unused)) = read(fd, &occ, sizeof(occ));
}
if (a->timer_id > b->timer_id) return 1;
int flexran_agent_timer_source_setup(struct timesync *sync) {
sync->param_sync = malloc(sizeof(int));
if (!sync->param_sync)
return -1;
int fd = timerfd_create(CLOCK_MONOTONIC, 0);
if (fd < 0)
return fd;
// equal timers
const uint64_t period_ns = 1000000; // 1ms
struct itimerspec t;
t.it_interval.tv_sec = period_ns / 1000000000;
t.it_interval.tv_nsec = period_ns % 1000000000;
t.it_value.tv_sec = period_ns / 1000000000;
t.it_value.tv_nsec = period_ns % 1000000000;
int rc = timerfd_settime(fd, 0, &t, NULL);
if (rc != 0)
return -1;
*(int *)sync->param_sync = fd;
sync->fsync = flexran_agent_timer_source_sync;
return 0;
}
err_code_t flexran_agent_create_timer(uint32_t interval_sec,
uint32_t interval_usec,
agent_id_t agent_id,
instance_t instance,
uint32_t timer_type,
xid_t xid,
void flexran_agent_timer_signal_sync(void *param_sync) {
flexran_agent_timer_extern_source_t *sync = param_sync;
pthread_mutex_lock(&sync->mutex_sync);
while (sync->wait) {
pthread_cond_wait(&sync->cond, &sync->mutex_sync);
}
sync->wait = 1;
pthread_mutex_unlock(&sync->mutex_sync);
}
int flexran_agent_timer_signal_init(struct timesync *sync) {
flexran_agent_timer_extern_source_t *s = malloc(sizeof(flexran_agent_timer_extern_source_t));
if (!s)
return TIMER_SETUP_FAILED;
if (pthread_mutex_init(&s->mutex_sync, NULL) < 0)
return TIMER_SETUP_FAILED;
if (pthread_cond_init(&s->cond, NULL) < 0)
return TIMER_SETUP_FAILED;
s->wait = 1;
sync->param_sync = s;
sync->fsync = flexran_agent_timer_signal_sync;
return 0;
}
void flexran_agent_timer_signal(mid_t mod_id) {
flexran_agent_timer_extern_source_t *sync = timesync[mod_id].param_sync;
pthread_mutex_lock(&sync->mutex_sync);
sync->wait = 0;
pthread_mutex_unlock(&sync->mutex_sync);
pthread_cond_signal(&sync->cond);
}
void *flexran_agent_timer_thread(void *args) {
struct timesync *sync = args;
while (1) {
sync->fsync(sync->param_sync);
if (sync->exit)
break;
pthread_mutex_lock(&sync->mutex_timer);
sync->current++;
if (sync->current < sync->next) {
pthread_mutex_unlock(&sync->mutex_timer);
continue;
}
for (int i = 0; i < sync->timer_num; ++i) {
flexran_agent_timer_element_t *t = sync->timer[i];
if (sync->current == t->next) {
flexran_agent_timer_process(t);
t->next += t->sf;
}
if (sync->next == sync->current || t->next < sync->next)
sync->next = t->next;
}
pthread_mutex_unlock(&sync->mutex_timer);
}
LOG_W(FLEXRAN_AGENT, "terminated timer thread\n");
return NULL;
}
void flexran_agent_timer_process(flexran_agent_timer_element_t *t) {
Protocol__FlexranMessage *msg = t->cb(t->mod_id, t->msg);
if (!msg)
return;
int size = 0;
void *data = flexran_agent_pack_message(msg, &size);
if (flexran_agent_msg_send(t->mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0)
LOG_E(FLEXRAN_AGENT, "error while sending message for timer xid %d\n", t->xid);
}
err_code_t flexran_agent_create_timer(mid_t mod_id,
uint32_t sf,
flexran_agent_timer_type_t timer_type,
xid_t xid,
flexran_agent_timer_callback_t cb,
void *timer_args,
long *timer_id) {
struct flexran_agent_timer_element_s *e = calloc(1, sizeof(*e));
DevAssert(e != NULL);
//uint32_t timer_id;
int ret=-1;
if ((interval_sec == 0) && (interval_usec == 0 )) {
free(e);
Protocol__FlexranMessage *msg) {
if (sf == 0)
return TIMER_NULL;
}
if (cb == NULL)
return TIMER_SETUP_FAILED;
AssertFatal(timer_type != FLEXRAN_AGENT_TIMER_TYPE_ONESHOT,
"one shot timer not yet implemented\n");
if (timer_type >= FLEXRAN_AGENT_TIMER_TYPE_MAX) {
free(e);
return TIMER_TYPE_INVALIDE;
}
if (timer_type == FLEXRAN_AGENT_TIMER_TYPE_ONESHOT) {
ret = timer_setup(interval_sec,
interval_usec,
TASK_FLEXRAN_AGENT,
instance,
TIMER_ONE_SHOT,
timer_args,
timer_id);
e->type = TIMER_ONE_SHOT;
} else if (timer_type == FLEXRAN_AGENT_TIMER_TYPE_PERIODIC ) {
ret = timer_setup(interval_sec,
interval_usec,
TASK_FLEXRAN_AGENT,
instance,
TIMER_PERIODIC,
timer_args,
timer_id);
e->type = TIMER_PERIODIC;
}
if (ret < 0 ) {
free(e);
flexran_agent_timer_element_t *t = malloc(sizeof(flexran_agent_timer_element_t));
if (!t) {
LOG_E(FLEXRAN_AGENT, "no memory for new timer %d\n", xid);
return TIMER_SETUP_FAILED;
}
t->mod_id = mod_id;
t->xid = xid;
t->sf = sf;
t->cb = cb;
t->msg = msg;
e->agent_id = agent_id;
e->instance = instance;
e->state = FLEXRAN_AGENT_TIMER_STATE_ACTIVE;
e->timer_id = *timer_id;
e->xid = xid;
e->timer_args = timer_args;
e->cb = cb;
/*element should be a real pointer*/
RB_INSERT(flexran_agent_map, &timer_instance.flexran_agent_head, e);
LOG_I(FLEXRAN_AGENT,"Created a new timer with id 0x%lx for agent %d, instance %d \n",
e->timer_id, e->agent_id, e->instance);
return 0;
}
err_code_t flexran_agent_destroy_timer(long timer_id) {
struct flexran_agent_timer_element_s *e = get_timer_entry(timer_id);
if (e != NULL ) {
RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
flexran_agent_destroy_flexran_message(e->timer_args->msg);
free(e);
struct timesync *sync = &timesync[mod_id];
pthread_mutex_lock(&sync->mutex_timer);
if (sync->timer_num >= MAX_NUM_TIMERS) {
pthread_mutex_unlock(&sync->mutex_timer);
LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n",
sync->timer_num, xid);
free(t);
return TIMER_SETUP_FAILED;
}
if (timer_remove(timer_id) < 0 )
goto error;
/* TODO check that xid does not exist? */
t->next = sync->current + 1;
if (sync->next <= sync->current || t->next < sync->next)
sync->next = t->next;
sync->timer[sync->timer_num] = t;
sync->timer_num++;
pthread_mutex_unlock(&sync->mutex_timer);
LOG_D(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
return 0;
error:
LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
return TIMER_REMOVED_FAILED ;
}
err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid) {
struct flexran_agent_timer_element_s *e = NULL;
long timer_id;
RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
if (e->xid == xid) {
timer_id = e->timer_id;
RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
flexran_agent_destroy_flexran_message(e->timer_args->msg);
free(e);
err_code_t flexran_agent_destroy_timers(mid_t mod_id) {
struct timesync *sync = &timesync[mod_id];
pthread_mutex_lock(&sync->mutex_timer);
for (int i = sync->timer_num - 1; i < 0; --i) {
flexran_agent_timer_remove_internal(sync, i);
}
pthread_mutex_unlock(&sync->mutex_timer);
return 0;
}
if (timer_remove(timer_id) < 0 ) {
goto error;
}
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
struct timesync *sync = &timesync[mod_id];
pthread_mutex_lock(&sync->mutex_timer);
for (int i = 0; i < sync->timer_num; ++i) {
if (sync->timer[i]->xid == xid) {
flexran_agent_timer_remove_internal(sync, i);
pthread_mutex_unlock(&sync->mutex_timer);
return 0;
}
}
return 0;
error:
LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
return TIMER_REMOVED_FAILED ;
pthread_mutex_unlock(&sync->mutex_timer);
LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid);
return TIMER_ELEMENT_NOT_FOUND;
}
err_code_t flexran_agent_destroy_timers(void) {
struct flexran_agent_timer_element_s *e = NULL;
RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
timer_remove(e->timer_id);
flexran_agent_destroy_flexran_message(e->timer_args->msg);
free(e);
}
return 0;
}
void flexran_agent_sleep_until(struct timespec *ts, int delay) {
ts->tv_nsec += delay;
if(ts->tv_nsec >= 1000*1000*1000) {
ts->tv_nsec -= 1000*1000*1000;
ts->tv_sec++;
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL);
}
err_code_t flexran_agent_stop_timer(long timer_id) {
struct flexran_agent_timer_element_s *e=NULL;
struct flexran_agent_timer_element_s search;
memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
search.timer_id = timer_id;
e = RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
if (e != NULL ) {
e->state = FLEXRAN_AGENT_TIMER_STATE_STOPPED;
}
timer_remove(timer_id);
return 0;
}
struct flexran_agent_timer_element_s *get_timer_entry(long timer_id) {
struct flexran_agent_timer_element_s search;
memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
search.timer_id = timer_id;
return RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
/* this function assumes that the timer lock is held */
void flexran_agent_timer_remove_internal(struct timesync *sync, int index) {
LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n",
sync->timer[index]->xid, index, sync->timer[index]->mod_id);
flexran_agent_destroy_flexran_message(sync->timer[index]->msg);
free(sync->timer[index]);
for (int i = index + 1; i < sync->timer_num; ++i)
sync->timer[i - 1] = sync->timer[i];
sync->timer_num--;
sync->timer[sync->timer_num] = NULL;
}
+22 -84
View File
@@ -26,107 +26,45 @@
* \version 0.1
*/
#include <stdio.h>
#include <time.h>
#ifndef _FLEXRAN_AGENT_TIMER_
#define _FLEXRAN_AGENT_TIMER_
#include "flexran_agent_common.h"
#include "flexran_agent_common_internal.h"
#include "flexran_agent_extern.h"
#include "flexran_agent_defs.h"
# include "tree.h"
# include "intertask_interface.h"
/*******************
* timer primitves
*******************/
#define TIMER_NULL -1
#define TIMER_TYPE_INVALIDE -2
#define TIMER_SETUP_FAILED -3
#define TIMER_REMOVED_FAILED -4
#define TIMER_ELEMENT_NOT_FOUND -5
typedef enum {
FLEXRAN_AGENT_TIMER_TYPE_ONESHOT,
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
} flexran_agent_timer_type_t;
/* Type of the callback executed when the timer expired */
typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(void*);
typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(
mid_t mod_id, const Protocol__FlexranMessage *msg);
err_code_t flexran_agent_timer_init(mid_t mod_id);
void flexran_agent_timer_exit(mid_t mod_id);
typedef struct flexran_agent_timer_args_s{
mid_t mod_id;
Protocol__FlexranMessage *msg;
} flexran_agent_timer_args_t;
/* Signals next subframe for FlexRAN timers */
void flexran_agent_timer_signal(mid_t mod_id);
typedef struct flexran_agent_timer_element_s{
RB_ENTRY(flexran_agent_timer_element_s) entry;
agent_id_t agent_id;
instance_t instance;
flexran_agent_timer_type_t type;
flexran_agent_timer_state_t state;
uint32_t interval_sec;
uint32_t interval_usec;
long timer_id; /* Timer id returned by the timer API*/
xid_t xid; /*The id of the task as received by the controller
message*/
flexran_agent_timer_callback_t cb;
flexran_agent_timer_args_t *timer_args;
} flexran_agent_timer_element_t;
typedef struct flexran_agent_timer_instance_s{
RB_HEAD(flexran_agent_map, flexran_agent_timer_element_s) flexran_agent_head;
}flexran_agent_timer_instance_t;
err_code_t flexran_agent_init_timer(void);
/* Create a timer for some agent related event with id xid. Will store the id
of the generated timer in timer_id */
err_code_t flexran_agent_create_timer(uint32_t interval_sec,
uint32_t interval_usec,
agent_id_t agent_id,
instance_t instance,
uint32_t timer_type,
xid_t xid,
flexran_agent_timer_callback_t cb,
void* timer_args,
long *timer_id);
/* Create a timer for some agent related event with id xid. */
err_code_t flexran_agent_create_timer(mid_t mod_id,
uint32_t sf,
flexran_agent_timer_type_t timer_type,
xid_t xid,
flexran_agent_timer_callback_t cb,
Protocol__FlexranMessage *msg);
/* Destroy all existing timers */
err_code_t flexran_agent_destroy_timers(void);
/* Destroy the timer with the given timer_id */
err_code_t flexran_agent_destroy_timer(long timer_id);
err_code_t flexran_agent_destroy_timers(mid_t mod_id);
/* Destroy the timer for task with id xid */
err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid);
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid);
/* Stop a timer */
err_code_t flexran_agent_stop_timer(long timer_id);
/* Restart the given timer */
err_code_t flexran_agent_restart_timer(long *timer_id);
/* Find the timer with the given timer_id */
struct flexran_agent_timer_element_s * get_timer_entry(long timer_id);
/* Obtain the protocol message stored in the given expired timer */
Protocol__FlexranMessage * flexran_agent_process_timeout(long timer_id, void* timer_args);
/* Comparator function comparing two timers. Decides the ordering of the timers */
int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b);
/*Specify a delay in nanoseconds to timespec and sleep until then*/
void flexran_agent_sleep_until(struct timespec *ts, int delay);
/* RB_PROTOTYPE is for .h files */
RB_PROTOTYPE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
#endif /* _FLEXRAN_AGENT_TIMER_ */