Merge remote-tracking branch 'develop'
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -3104,4 +3104,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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "s1ap_eNB_ue_context.h"
|
||||
#include "s1ap_eNB_management_procedures.h"
|
||||
|
||||
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) {
|
||||
return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id];
|
||||
@@ -3002,6 +3004,14 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index) {
|
||||
return ue_context_p->ue_context.e_rab[index].param.gtp_teid;
|
||||
}
|
||||
|
||||
uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti)
|
||||
{
|
||||
if (!rrc_is_present(mod_id)) return 0;
|
||||
struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
|
||||
if (!ue_context_p) return -1;
|
||||
return ue_context_p->ue_context.eNB_ue_s1ap_id;
|
||||
}
|
||||
|
||||
/**************************** SLICING ****************************/
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
@@ -3470,6 +3480,195 @@ int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
|
||||
}
|
||||
|
||||
/************************** S1AP **************************/
|
||||
int flexran_get_s1ap_mme_pending(mid_t mod_id){
|
||||
if (!rrc_is_present(mod_id)) return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
return s1ap->s1ap_mme_pending_nb;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_mme_connected(mid_t mod_id){
|
||||
if (!rrc_is_present(mod_id)) return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
return s1ap->s1ap_mme_associated_nb;
|
||||
}
|
||||
|
||||
char* flexran_get_s1ap_enb_s1_ip(mid_t mod_id){
|
||||
if (!rrc_is_present(mod_id)) return NULL;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return NULL;
|
||||
if (s1ap->eNB_s1_ip.ipv4)
|
||||
return &s1ap->eNB_s1_ip.ipv4_address[0];
|
||||
if (s1ap->eNB_s1_ip.ipv6)
|
||||
return &s1ap->eNB_s1_ip.ipv6_address[0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* flexran_get_s1ap_enb_name(mid_t mod_id){
|
||||
if (!rrc_is_present(mod_id)) return NULL;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return NULL;
|
||||
return s1ap->eNB_name;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_nb_mme(mid_t mod_id) {
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return 0;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
int count = 0;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_nb_ue(mid_t mod_id) {
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return 0;
|
||||
struct s1ap_eNB_ue_context_s *ue = NULL;
|
||||
int count = 0;
|
||||
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apMme * mme_conf){
|
||||
if (!rrc_is_present(mod_id)) return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
|
||||
struct served_gummei_s *gummei_p = NULL;
|
||||
struct plmn_identity_s *served_plmn_p = NULL;
|
||||
struct served_group_id_s *group_id_p = NULL;
|
||||
struct mme_code_s *mme_code_p = NULL;
|
||||
int i = 0;
|
||||
Protocol__FlexGummei **served_gummeis;
|
||||
Protocol__FlexPlmn **requested_plmns;
|
||||
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head){
|
||||
if (mme_index == 0) break;
|
||||
mme_index--;
|
||||
}
|
||||
if (mme_index > 0) return -1;
|
||||
|
||||
if (mme->mme_s1_ip.ipv4) {
|
||||
mme_conf->s1_ip = (char*) &mme->mme_s1_ip.ipv4_address[0];
|
||||
} else if (mme->mme_s1_ip.ipv6) {
|
||||
mme_conf->s1_ip = (char*) &mme->mme_s1_ip.ipv6_address[0];
|
||||
}
|
||||
mme_conf->name = mme->mme_name;
|
||||
mme_conf->has_state = 1;
|
||||
mme_conf->state = mme->state;
|
||||
|
||||
mme_conf->n_served_gummeis = 0;
|
||||
STAILQ_FOREACH(gummei_p, &mme->served_gummei, next) {
|
||||
mme_conf->n_served_gummeis++;
|
||||
}
|
||||
if (mme_conf->n_served_gummeis > 0) {
|
||||
served_gummeis = calloc(mme_conf->n_served_gummeis, sizeof(Protocol__FlexGummei*));
|
||||
if(served_gummeis == NULL) return -1;
|
||||
|
||||
STAILQ_FOREACH(gummei_p, &mme->served_gummei, next) {
|
||||
served_plmn_p = STAILQ_FIRST(&gummei_p->served_plmns);
|
||||
group_id_p = STAILQ_FIRST(&gummei_p->served_group_ids);
|
||||
mme_code_p = STAILQ_FIRST(&gummei_p->mme_codes);
|
||||
|
||||
served_gummeis[i] = malloc(sizeof(Protocol__FlexGummei));
|
||||
if (!served_gummeis[i]) return -1;
|
||||
protocol__flex_gummei__init(served_gummeis[i]);
|
||||
served_gummeis[i]->plmn = malloc(sizeof(Protocol__FlexPlmn));
|
||||
if (!served_gummeis[i]->plmn) return -1;
|
||||
protocol__flex_plmn__init(served_gummeis[i]->plmn);
|
||||
|
||||
if (served_plmn_p) {
|
||||
served_gummeis[i]->plmn->has_mcc = 1;
|
||||
served_gummeis[i]->plmn->mcc = served_plmn_p->mcc;
|
||||
served_gummeis[i]->plmn->has_mnc = 1;
|
||||
served_gummeis[i]->plmn->mnc = served_plmn_p->mnc;
|
||||
served_gummeis[i]->plmn->has_mnc_length = 1;
|
||||
served_gummeis[i]->plmn->mnc_length = served_plmn_p-> mnc_digit_length;
|
||||
STAILQ_NEXT(served_plmn_p, next);
|
||||
}
|
||||
if (group_id_p) {
|
||||
served_gummeis[i]->has_mme_group_id = 1;
|
||||
served_gummeis[i]->mme_group_id = group_id_p->mme_group_id;
|
||||
STAILQ_NEXT(group_id_p, next);
|
||||
}
|
||||
if (mme_code_p){
|
||||
served_gummeis[i]->has_mme_code = 1;
|
||||
served_gummeis[i]->mme_code = mme_code_p->mme_code;
|
||||
STAILQ_NEXT(mme_code_p, next);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
mme_conf->served_gummeis = served_gummeis;
|
||||
}
|
||||
|
||||
// requested PLMNS
|
||||
mme_conf->n_requested_plmns = mme->broadcast_plmn_num;
|
||||
if (mme_conf->n_requested_plmns > 0){
|
||||
requested_plmns = calloc(mme_conf->n_requested_plmns, sizeof(Protocol__FlexPlmn*));
|
||||
if(requested_plmns == NULL) return -1;
|
||||
for(int i = 0; i < mme_conf->n_requested_plmns; i++) {
|
||||
requested_plmns[i] = malloc(sizeof(Protocol__FlexPlmn));
|
||||
if (!requested_plmns[i]) return -1;
|
||||
protocol__flex_plmn__init(requested_plmns[i]);
|
||||
requested_plmns[i]->mcc = s1ap->mcc[mme->broadcast_plmn_index[i]];
|
||||
requested_plmns[i]->has_mcc = 1;
|
||||
requested_plmns[i]->mnc = s1ap->mnc[mme->broadcast_plmn_index[i]];
|
||||
requested_plmns[i]->has_mnc = 1;
|
||||
requested_plmns[i]->mnc_length = s1ap->mnc_digit_length[mme->broadcast_plmn_index[i]];
|
||||
requested_plmns[i]->has_mnc_length = 1;
|
||||
}
|
||||
mme_conf->requested_plmns = requested_plmns;
|
||||
}
|
||||
|
||||
mme_conf->has_rel_capacity = 1;
|
||||
mme_conf->rel_capacity = mme->relative_mme_capacity;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){
|
||||
if (!rrc_is_present(mod_id)) return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
|
||||
uint32_t enb_ue_s1ap_id = flexran_get_rrc_enb_ue_s1ap_id(mod_id, rnti);
|
||||
struct s1ap_eNB_ue_context_s *ue = NULL;
|
||||
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){
|
||||
if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break;
|
||||
}
|
||||
if (ue == NULL) return -1;
|
||||
|
||||
if (ue->mme_ref->mme_s1_ip.ipv4)
|
||||
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0];
|
||||
else if (ue->mme_ref->mme_s1_ip.ipv6)
|
||||
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv6_address[0];
|
||||
|
||||
ue_conf->has_enb_ue_s1ap_id = 1;
|
||||
ue_conf->enb_ue_s1ap_id = ue->eNB_ue_s1ap_id;
|
||||
ue_conf->has_mme_ue_s1ap_id = 1;
|
||||
ue_conf->mme_ue_s1ap_id = ue->mme_ue_s1ap_id;
|
||||
|
||||
ue_conf->selected_plmn = malloc(sizeof(Protocol__FlexPlmn));
|
||||
if (!ue_conf->selected_plmn) return -1;
|
||||
protocol__flex_plmn__init(ue_conf->selected_plmn);
|
||||
|
||||
ue_conf->selected_plmn->has_mcc = 1;
|
||||
ue_conf->selected_plmn->mcc = s1ap->mcc[ue->selected_plmn_identity];
|
||||
ue_conf->selected_plmn->has_mnc = 1;
|
||||
ue_conf->selected_plmn->mnc = s1ap->mnc[ue->selected_plmn_identity];
|
||||
ue_conf->selected_plmn->has_mnc_length = 1;
|
||||
ue_conf->selected_plmn->mnc_length = s1ap->mnc_digit_length[ue->selected_plmn_identity];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************** General BS info ****************************/
|
||||
uint64_t flexran_get_bs_id(mid_t mod_id) {
|
||||
if (!rrc_is_present(mod_id)) return 0;
|
||||
@@ -3488,13 +3687,14 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
|
||||
case ngran_eNB_CU:
|
||||
case ngran_ng_eNB_CU:
|
||||
case ngran_gNB_CU:
|
||||
n_caps = 3;
|
||||
n_caps = 4;
|
||||
*caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
|
||||
AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
|
||||
n_caps * sizeof(Protocol__FlexBsCapability));
|
||||
(*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
|
||||
(*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
|
||||
(*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
|
||||
(*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
|
||||
break;
|
||||
case ngran_eNB_DU:
|
||||
case ngran_gNB_DU:
|
||||
@@ -3511,7 +3711,7 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
|
||||
case ngran_eNB:
|
||||
case ngran_ng_eNB:
|
||||
case ngran_gNB:
|
||||
n_caps = 8;
|
||||
n_caps = 9;
|
||||
*caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
|
||||
AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
|
||||
n_caps * sizeof(Protocol__FlexBsCapability));
|
||||
@@ -3523,26 +3723,27 @@ size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
|
||||
(*caps)[5] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
|
||||
(*caps)[6] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
|
||||
(*caps)[7] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
|
||||
(*caps)[8] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
|
||||
break;
|
||||
case ngran_eNB_MBMS_STA:
|
||||
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return n_caps;
|
||||
}
|
||||
|
||||
uint16_t flexran_get_capabilities_mask(mid_t mod_id) {
|
||||
uint32_t flexran_get_capabilities_mask(mid_t mod_id) {
|
||||
if (!rrc_is_present(mod_id)) return 0;
|
||||
|
||||
uint16_t mask = 0;
|
||||
|
||||
uint32_t mask = 0;
|
||||
switch (RC.rrc[mod_id]->node_type) {
|
||||
case ngran_eNB_CU:
|
||||
case ngran_ng_eNB_CU:
|
||||
case ngran_gNB_CU:
|
||||
mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
|
||||
break;
|
||||
case ngran_eNB_DU:
|
||||
case ngran_gNB_DU:
|
||||
@@ -3562,11 +3763,41 @@ uint16_t flexran_get_capabilities_mask(mid_t mod_id) {
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
|
||||
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
|
||||
break;
|
||||
case ngran_eNB_MBMS_STA:
|
||||
AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 = ×ync[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 = ×ync[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 = ×ync[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 = ×ync[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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
+13
-33
@@ -37,27 +37,19 @@
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
# include "intertask_interface.h"
|
||||
# if defined(ENABLE_USE_MME)
|
||||
# include "s1ap_eNB.h"
|
||||
# include "sctp_eNB_task.h"
|
||||
# include "gtpv1u_eNB_task.h"
|
||||
# endif
|
||||
|
||||
# include "PHY/INIT/phy_init.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "s1ap_eNB.h"
|
||||
#include "sctp_eNB_task.h"
|
||||
#include "gtpv1u_eNB_task.h"
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
|
||||
extern unsigned char NB_gNB_INST;
|
||||
#endif
|
||||
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
#define GNB_REGISTER_RETRY_DELAY 10
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
# if defined(ENABLE_USE_MME)
|
||||
# define GNB_REGISTER_RETRY_DELAY 10
|
||||
# endif
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
@@ -82,7 +74,6 @@ static void configure_nr_rrc(uint32_t gnb_id)
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
# if defined(ENABLE_USE_MME)
|
||||
static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, const Enb_properties_array_t *enb_properties)
|
||||
{
|
||||
uint32_t gnb_id;
|
||||
@@ -113,23 +104,15 @@ static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//,
|
||||
|
||||
return register_gnb_pending;
|
||||
}
|
||||
# endif
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
void *gNB_app_task(void *args_p)
|
||||
{
|
||||
#if defined(ENABLE_ITTI)
|
||||
uint32_t gnb_nb = RC.nb_nr_inst;
|
||||
uint32_t gnb_id_start = 0;
|
||||
uint32_t gnb_id_end = gnb_id_start + gnb_nb;
|
||||
# if defined(ENABLE_USE_MME)
|
||||
//uint32_t register_gnb_pending;
|
||||
//uint32_t registered_gnb;
|
||||
//long gnb_register_retry_timer_id;
|
||||
# endif
|
||||
uint32_t gnb_id;
|
||||
MessageDef *msg_p = NULL;
|
||||
const char *msg_name = NULL;
|
||||
@@ -166,15 +149,15 @@ void *gNB_app_task(void *args_p)
|
||||
configure_nr_rrc(gnb_id);
|
||||
}
|
||||
|
||||
# if defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED) {
|
||||
/* Try to register each gNB */
|
||||
//registered_gnb = 0;
|
||||
//register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end);//, gnb_properties_p);
|
||||
# else
|
||||
} else {
|
||||
/* Start L2L1 task */
|
||||
msg_p = itti_alloc_new_message(TASK_GNB_APP, INITIALIZE_MESSAGE);
|
||||
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
|
||||
# endif
|
||||
msg_p = itti_alloc_new_message(TASK_GNB_APP, INITIALIZE_MESSAGE);
|
||||
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
|
||||
}
|
||||
|
||||
do {
|
||||
// Wait for a message
|
||||
@@ -193,7 +176,7 @@ void *gNB_app_task(void *args_p)
|
||||
LOG_I(GNB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
|
||||
break;
|
||||
|
||||
# if defined(ENABLE_USE_MME)
|
||||
|
||||
/*
|
||||
case S1AP_REGISTER_ENB_CNF:
|
||||
LOG_I(GNB_APP, "[gNB %d] Received %s: associated MME %d\n", instance, msg_name,
|
||||
@@ -254,7 +237,6 @@ void *gNB_app_task(void *args_p)
|
||||
//}
|
||||
|
||||
break;
|
||||
# endif
|
||||
|
||||
default:
|
||||
LOG_E(GNB_APP, "Received unexpected message %s\n", msg_name);
|
||||
@@ -265,8 +247,6 @@ void *gNB_app_task(void *args_p)
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
} while (1);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -36,13 +36,9 @@
|
||||
#include "gnb_config.h"
|
||||
#include "UTIL/OTG/otg.h"
|
||||
#include "UTIL/OTG/otg_externs.h"
|
||||
#if defined(ENABLE_ITTI)
|
||||
# include "intertask_interface.h"
|
||||
# if defined(ENABLE_USE_MME)
|
||||
# include "s1ap_eNB.h"
|
||||
# include "sctp_eNB_task.h"
|
||||
# endif
|
||||
#endif
|
||||
#include "intertask_interface.h"
|
||||
#include "s1ap_eNB.h"
|
||||
#include "sctp_eNB_task.h"
|
||||
#include "sctp_default_values.h"
|
||||
// #include "SystemInformationBlockType2.h"
|
||||
// #include "LAYER2/MAC/extern.h"
|
||||
@@ -225,11 +221,10 @@ void RCconfig_nr_flexran()
|
||||
/* gNB ID from configuration, as read in by RCconfig_RRC() */
|
||||
if (!GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr) {
|
||||
// Calculate a default gNB ID
|
||||
# if defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED)
|
||||
gnb_id = i + (s1ap_generate_eNB_id () & 0xFFFF8);
|
||||
# else
|
||||
else
|
||||
gnb_id = i;
|
||||
# endif
|
||||
} else {
|
||||
gnb_id = *(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr);
|
||||
}
|
||||
@@ -648,7 +643,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
AssertFatal (i<num_gnbs,"Failed to parse config file no %ith element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
/*
|
||||
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED) {
|
||||
if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
|
||||
asn_debug = 0;
|
||||
asn1_xer_print = 0;
|
||||
@@ -662,7 +657,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
asn_debug = 0;
|
||||
asn1_xer_print = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
if (num_gnbs>0) {
|
||||
@@ -671,13 +666,13 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
|
||||
if (GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr == NULL) {
|
||||
// Calculate a default gNB ID
|
||||
# if defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED) {
|
||||
uint32_t hash;
|
||||
hash = s1ap_generate_eNB_id ();
|
||||
gnb_id = i + (hash & 0xFFFF8);
|
||||
# else
|
||||
} else {
|
||||
gnb_id = i;
|
||||
# endif
|
||||
}
|
||||
} else {
|
||||
gnb_id = *(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr);
|
||||
}
|
||||
@@ -2739,7 +2734,7 @@ int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i) {
|
||||
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
|
||||
|
||||
/*
|
||||
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
|
||||
if (EPC_MODE_ENABLED) {
|
||||
if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
|
||||
asn_debug = 0;
|
||||
asn1_xer_print = 0;
|
||||
@@ -2753,7 +2748,7 @@ int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i) {
|
||||
asn_debug = 0;
|
||||
asn1_xer_print = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
AssertFatal (i<GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt,
|
||||
|
||||
@@ -897,10 +897,12 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
} // end for loop on UE_id
|
||||
|
||||
#if (!defined(PRE_SCD_THREAD))
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP);
|
||||
pdcp_run(&ctxt);
|
||||
pdcp_mbms_run(&ctxt);
|
||||
rrc_rx_tx(&ctxt, CC_id);
|
||||
if (!NODE_IS_DU(RC.rrc[module_idP]->node_type)) {
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP);
|
||||
pdcp_run(&ctxt);
|
||||
pdcp_mbms_run(&ctxt);
|
||||
rrc_rx_tx(&ctxt, CC_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
@@ -988,6 +990,8 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
if (flexran_agent_get_mac_xface(module_idP) && subframeP == 9) {
|
||||
flexran_agent_slice_update(module_idP);
|
||||
}
|
||||
if (flexran_agent_get_mac_xface(module_idP))
|
||||
flexran_agent_get_mac_xface(module_idP)->flexran_agent_notify_tick(module_idP);
|
||||
|
||||
stop_meas(&(eNB->eNB_scheduler));
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, VCD_FUNCTION_OUT);
|
||||
|
||||
@@ -48,11 +48,11 @@
|
||||
#include "pdcp.h"
|
||||
#include "assertions.h"
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
#include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
#include "SIMULATION/TOOLS/sim.h" // for taus
|
||||
//#if defined(ENABLE_ITTI)
|
||||
//#include "intertask_interface.h"
|
||||
//#endif
|
||||
//
|
||||
#include "SIMULATION/TOOLS/sim.h" // for taus
|
||||
|
||||
#define ENABLE_MAC_PAYLOAD_DEBUG
|
||||
#define DEBUG_eNB_SCHEDULER 1
|
||||
@@ -60,37 +60,38 @@
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
|
||||
int8_t get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, uint8_t mbsfn_sync_area) {
|
||||
// currently there is one-to-one mapping between sf allocation pattern and sync area
|
||||
if (mbsfn_sync_area >= MAX_MBSFN_AREA) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d] CC_id %d MBSFN synchronization area %d out of range\n ",
|
||||
module_idP, CC_id, mbsfn_sync_area);
|
||||
return -1;
|
||||
} else if (RC.mac[module_idP]->
|
||||
common_channels[CC_id].mbsfn_SubframeConfig[mbsfn_sync_area]
|
||||
!= NULL) {
|
||||
return mbsfn_sync_area;
|
||||
} else {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d] CC_id %d MBSFN Subframe Config pattern %d not found \n ",
|
||||
module_idP, CC_id, mbsfn_sync_area);
|
||||
return -1;
|
||||
}
|
||||
int8_t
|
||||
get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id,
|
||||
uint8_t mbsfn_sync_area)
|
||||
{
|
||||
// currently there is one-to-one mapping between sf allocation pattern and sync area
|
||||
if (mbsfn_sync_area > MAX_MBSFN_AREA) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d] CC_id %d MBSFN synchronization area %d out of range\n ",
|
||||
module_idP, CC_id, mbsfn_sync_area);
|
||||
return -1;
|
||||
} else if (RC.mac[module_idP]->
|
||||
common_channels[CC_id].mbsfn_SubframeConfig[mbsfn_sync_area]
|
||||
!= NULL) {
|
||||
return mbsfn_sync_area;
|
||||
} else {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d] CC_id %d MBSFN Subframe Config pattern %d not found \n ",
|
||||
module_idP, CC_id, mbsfn_sync_area);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t bytes_in_buffer=0;
|
||||
static uint8_t msi_pmch_stop=0;
|
||||
static uint32_t msi_pmch_stop=0;
|
||||
//static uint8_t msi_active=0;
|
||||
//static uint8_t msi_pmch_stop2=0;
|
||||
uint16_t mbms_rab_id = 2047;
|
||||
static uint8_t msi_sfs=0;
|
||||
static uint32_t msi_sfs=0;
|
||||
|
||||
|
||||
//MSI_ELEMENT * ptr =NULL;
|
||||
|
||||
|
||||
int
|
||||
schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
sub_frame_t subframeP)
|
||||
@@ -121,8 +122,9 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
int mcch_mcs = -1;
|
||||
uint16_t TBS, j = -1, padding = 0, post_padding = 0;
|
||||
mac_rlc_status_resp_t rlc_status;
|
||||
//mac_rlc_status_resp_t rlc_status2;
|
||||
int num_mtch;
|
||||
int msi_length, i, k;
|
||||
int msi_length=0, i, k;
|
||||
//uint8_t l =0;
|
||||
unsigned char sdu_lcids[11], num_sdus = 0, offset = 0;
|
||||
uint16_t sdu_lengths[11], sdu_length_total = 0;
|
||||
@@ -511,9 +513,11 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
// 2nd: Create MSI, get MCCH from RRC and MTCHs from RLC
|
||||
|
||||
// there is MSI (MCH Scheduling Info)
|
||||
uint16_t msi_control_element[29], *msi_ptr;
|
||||
char *buffer_pointer=NULL;
|
||||
if (msi_flag == 1) {
|
||||
// Create MSI here
|
||||
uint16_t msi_control_element[29], *msi_ptr;
|
||||
//uint16_t msi_control_element[29], *msi_ptr;
|
||||
|
||||
msi_ptr = &msi_control_element[0];
|
||||
//((MSI_ELEMENT *) msi_ptr)->lcid = MCCH_LCHANID; //MCCH
|
||||
@@ -543,9 +547,11 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
msi_pmch_stop = msi_sfs-1;
|
||||
else
|
||||
msi_pmch_stop = msi_sfs;
|
||||
|
||||
msi_pmch_stop = msi_sfs;
|
||||
|
||||
if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9)
|
||||
LOG_W(MAC,"e-MBMS Buffer Overflow\n");
|
||||
//if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9)
|
||||
//LOG_W(MAC,"e-MBMS Buffer Overflow\n");
|
||||
|
||||
if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/) {
|
||||
((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP of this mtch (only one mtch now) & stop_sf limited to 256
|
||||
@@ -584,6 +590,8 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
memcpy((char *) &mch_buffer[sdu_length_total],
|
||||
msi_control_element, msi_length);
|
||||
|
||||
buffer_pointer = (char *) &mch_buffer[sdu_length_total];
|
||||
|
||||
sdu_lcids[num_sdus] = MCH_SCHDL_INFO;
|
||||
sdu_lengths[num_sdus] = msi_length;
|
||||
sdu_length_total += sdu_lengths[num_sdus];
|
||||
@@ -594,12 +602,26 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
}
|
||||
// there is MCCH
|
||||
if (mcch_flag == 1) {
|
||||
|
||||
//LOG_E(MAC,
|
||||
//"[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE COUNTING (mod %d)\n",module_idP, CC_id, frameP, subframeP,frameP%2==0);
|
||||
if(1/*frameP%2==0*/){
|
||||
LOG_D(MAC,
|
||||
"[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n",
|
||||
module_idP, CC_id, frameP, subframeP, i, j);
|
||||
|
||||
mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0],
|
||||
mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0],
|
||||
i); // this is the mbsfn sync area index
|
||||
}
|
||||
else{
|
||||
LOG_E(MAC,
|
||||
"[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE COUNTING (area %d, sfAlloc %d)\n",
|
||||
module_idP, CC_id, frameP, subframeP, i, j);
|
||||
|
||||
//
|
||||
// mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH_COUNTING, 0xFFFC, 1, &cc->MCCH_pdu.payload[0],
|
||||
// i); // this is the mbsfn sync area index
|
||||
}
|
||||
|
||||
mcch_sdu_length+=1; //RLC ?
|
||||
|
||||
@@ -629,6 +651,15 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
sdu_lcids[num_sdus] = MCCH_LCHANID;
|
||||
sdu_lengths[num_sdus] = mcch_sdu_length;
|
||||
|
||||
// LOG_W(MAC,"MCCH RLC %x:",(unsigned char)mch_buffer[sdu_length_total]);
|
||||
// for (int kk = 7; kk >= 0; kk--)
|
||||
// {
|
||||
// printf("%d",(((unsigned char)mch_buffer[sdu_length_total]) >> kk) & 1 ? '1' : '0');
|
||||
// }
|
||||
// printf("\n");
|
||||
//mch_buffer[sdu_length_total] = (unsigned char)0;
|
||||
|
||||
|
||||
if (sdu_lengths[num_sdus] > 128) {
|
||||
header_len_mcch = 3;
|
||||
}
|
||||
@@ -641,6 +672,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TBS =
|
||||
get_TBS_DL(/*cc->pmch_Config[0]->dataMCS_r9*/cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth));
|
||||
// do not let mcch and mtch multiplexing when relaying is active
|
||||
@@ -686,7 +718,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9;
|
||||
|
||||
rlc_status =
|
||||
mac_rlc_status_ind(module_idP, 0, frameP, subframeP,
|
||||
mac_rlc_status_ind(module_idP, 0/*0xfffd*/, frameP, subframeP,
|
||||
module_idP, ENB_FLAG_YES, MBMS_FLAG_YES,
|
||||
cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9,
|
||||
//MTCH,
|
||||
@@ -697,36 +729,77 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
bytes_in_buffer = rlc_status.bytes_in_buffer;
|
||||
|
||||
|
||||
msi_sfs = rlc_status.bytes_in_buffer/TBS+(rlc_status.bytes_in_buffer%TBS?1:0);
|
||||
if( !(mcch_flag==1 || msi_flag==1) )
|
||||
msi_sfs = rlc_status.bytes_in_buffer/(TBS- header_len_mcch - header_len_msi -sdu_length_total - header_len_mtch)+(rlc_status.bytes_in_buffer%(TBS- header_len_mcch - header_len_msi -sdu_length_total - header_len_mtch)?1:0);
|
||||
//uint16_t msi_control_element[29], *msi_ptr;
|
||||
//
|
||||
//
|
||||
uint16_t TBS_MTCH =
|
||||
get_TBS_DL(cc->pmch_Config[0]->dataMCS_r9, to_prb(cc->mib->message.dl_Bandwidth));
|
||||
if(msi_flag==1 && buffer_pointer!=NULL){
|
||||
msi_ptr = &msi_control_element[0];
|
||||
|
||||
//memcpy(buffer_pointer,
|
||||
// msi_control_element, msi_length);
|
||||
|
||||
// msi_pmch_stop = rlc_status.bytes_in_buffer/TBS+(rlc_status.bytes_in_buffer%TBS?1:0);
|
||||
msi_pmch_stop = (rlc_status.bytes_in_buffer - header_len_mcch - header_len_msi -sdu_length_total - header_len_mtch)/(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)+((rlc_status.bytes_in_buffer-TBS-header_len_mcch - header_len_msi -sdu_length_total)%(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)?0:0);
|
||||
|
||||
if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9)
|
||||
LOG_E(MAC,"e-MBMS Buffer Overflow\n");
|
||||
if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/) {
|
||||
((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP of this mtch (only one mtch now) & stop_sf limited to 256
|
||||
//((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = msi_pmch_stop;
|
||||
((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9);
|
||||
msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9);
|
||||
}else{
|
||||
((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7; // last subframeP of this mtch (only one mtch now)
|
||||
((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xFF;
|
||||
msi_pmch_stop=0;
|
||||
}
|
||||
LOG_I(MAC,"frameP %d, subframeP %d rlc_status.bytes_in_buffer %d stop_sf_LSB %d\n",frameP,subframeP,rlc_status.bytes_in_buffer,((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB);
|
||||
//LOG_W(MAC,"frameP %d, subframeP %d rlc_status.bytes_in_buffer %d stop_sf_LSB %d msi_calc:%d remainder %d\n",frameP,subframeP,rlc_status.bytes_in_buffer,((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB,rlc_status.bytes_in_buffer/(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)+((rlc_status.bytes_in_buffer-TBS-header_len_mcch - header_len_msi -sdu_length_total)%(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)?0:0),((rlc_status.bytes_in_buffer-TBS-header_len_mcch - header_len_msi -sdu_length_total)%(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)?0:0));
|
||||
|
||||
memcpy(buffer_pointer,
|
||||
msi_control_element, msi_length);
|
||||
|
||||
}
|
||||
|
||||
LOG_D(MAC,
|
||||
"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d TBS %d pmch_stop %d msi_sfs %d\n",
|
||||
MTCH, frameP, subframeP, rlc_status.bytes_in_buffer,TBS,msi_pmch_stop,msi_sfs);
|
||||
"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d TBS_MTCH %d pmch_stop %d msi_sfs %d\n",
|
||||
MTCH, frameP, subframeP, rlc_status.bytes_in_buffer,TBS_MTCH,msi_pmch_stop,msi_sfs);
|
||||
|
||||
if (rlc_status.bytes_in_buffer > 0 || msi_pmch_stop > 0 /*msi_pmch_stop>=num_sf_alloc*/ ) {
|
||||
if ((rlc_status.bytes_in_buffer > 0 && msi_pmch_stop > 0) && ((msi_flag!=1 || mcch_flag!=1)) /*|| (rlc_status.bytes_in_buffer > 0 && (msi_flag==1 || mcch_flag==1))*//*|| msi_sfs > cc->pmch_Config[0]->sf_AllocEnd_r9 */ /*msi_pmch_stop>=num_sf_alloc*/ ) {
|
||||
//if(rlc_status.bytes_in_buffer > 0){
|
||||
LOG_I(MAC,
|
||||
LOG_D(MAC,
|
||||
"[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d) rlc_status.bytes_in_buffer %d\n",
|
||||
module_idP, CC_id, frameP,
|
||||
TBS - header_len_mcch - header_len_msi -
|
||||
sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer);
|
||||
|
||||
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used
|
||||
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0/*0xfffd*/, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used
|
||||
(char *)
|
||||
&mch_buffer[sdu_length_total]
|
||||
,0,
|
||||
0
|
||||
);
|
||||
|
||||
// LOG_I(MAC,"RLC %x:",(unsigned char)mch_buffer[sdu_length_total]);
|
||||
// for (int kk = 7; kk >= 0; kk--)
|
||||
// {
|
||||
// printf("%d",(((unsigned char)mch_buffer[sdu_length_total]) >> kk) & 1 ? '1' : '0');
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
//sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(MAX_MOBILES_PER_ENB+1)), (char*)&mch_buffer[sdu_length_total]);
|
||||
LOG_I(MAC,
|
||||
LOG_D(MAC,
|
||||
"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_sfs %d sdu_lengths[num_sdus] %d\n",
|
||||
module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs, sdu_lengths[num_sdus]);
|
||||
cc->mtch_active = 1;
|
||||
sdu_lcids[num_sdus] = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9/*MTCH*/;
|
||||
sdu_length_total += sdu_lengths[num_sdus];
|
||||
|
||||
if (msi_pmch_stop != 0)
|
||||
if (msi_pmch_stop != 0 && msi_flag !=1)
|
||||
msi_pmch_stop--;
|
||||
|
||||
|
||||
@@ -833,14 +906,14 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
}
|
||||
|
||||
/* Tracing of PDU is done on UE side */
|
||||
if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xffff, // M_RNTI = 6 in wirehsark
|
||||
//if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xfffd, // M_RNTI = 6 in wirehsark
|
||||
RC.mac[module_idP]->frame,
|
||||
RC.mac[module_idP]->subframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n",
|
||||
module_idP, CC_id, frameP, TBS);
|
||||
}
|
||||
//}
|
||||
|
||||
eNB_MAC_INST *eNB = RC.mac[module_idP];
|
||||
dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
|
||||
@@ -1370,7 +1443,7 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
header_len_msi = 3;
|
||||
}
|
||||
|
||||
LOG_D(MAC,
|
||||
LOG_W(MAC,
|
||||
"[eNB %d] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes TBS %d, bytes in buffer %d stop_sf_LSB %d msi_sfs %d cc->pmch_Config[0]->sf_AllocEnd_r9 %ld\n",
|
||||
module_idP, CC_id, frameP, msi_length,TBS, bytes_in_buffer,msi_pmch_stop,msi_sfs,cc->pmch_Config[0]->sf_AllocEnd_r9);
|
||||
|
||||
@@ -1485,7 +1558,7 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9;
|
||||
|
||||
rlc_status =
|
||||
mac_rlc_status_ind(module_idP, 0, frameP, subframeP,
|
||||
mac_rlc_status_ind(module_idP, 0/*0xfffd*/, frameP, subframeP,
|
||||
module_idP, ENB_FLAG_YES, MBMS_FLAG_YES,
|
||||
cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9,
|
||||
//MTCH,
|
||||
@@ -1510,7 +1583,7 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
TBS - header_len_mcch - header_len_msi -
|
||||
sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer);
|
||||
|
||||
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used
|
||||
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0/*0xfffd*/, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used
|
||||
(char *)
|
||||
&mch_buffer[sdu_length_total]
|
||||
,0,
|
||||
@@ -1632,14 +1705,14 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
}
|
||||
|
||||
/* Tracing of PDU is done on UE side */
|
||||
if (opt_enabled == 1) {
|
||||
//if (opt_enabled == 1) {
|
||||
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xffff, // M_RNTI = 6 in wirehsark
|
||||
RC.mac[module_idP]->frame,
|
||||
RC.mac[module_idP]->subframe, 0, 0);
|
||||
LOG_D(OPT,
|
||||
"[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n",
|
||||
module_idP, CC_id, frameP, TBS);
|
||||
}
|
||||
//}
|
||||
|
||||
/*
|
||||
for (j=0;j<sdu_length_total;j++)
|
||||
@@ -1669,12 +1742,12 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
MCH_PDU *get_mch_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
|
||||
sub_frame_t subframeP) {
|
||||
// RC.mac[module_idP]->MCH_pdu.mcs=0;
|
||||
//LOG_D(MAC," MCH_pdu.mcs is %d\n", RC.mac[module_idP]->MCH_pdu.mcs);
|
||||
//#warning "MCH pdu should take the CC_id index"
|
||||
return (&RC.mac[module_idP]->common_channels[CC_id].MCH_pdu);
|
||||
sub_frame_t subframeP)
|
||||
{
|
||||
// RC.mac[module_idP]->MCH_pdu.mcs=0;
|
||||
//LOG_D(MAC," MCH_pdu.mcs is %d\n", RC.mac[module_idP]->MCH_pdu.mcs);
|
||||
//#warning "MCH pdu should take the CC_id index"
|
||||
return (&RC.mac[module_idP]->common_channels[CC_id].MCH_pdu);
|
||||
}
|
||||
|
||||
|
||||
@@ -746,6 +746,9 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
|
||||
LOG_D(MAC, "[UE %d] parse_mch_header, found %d sdus\n", module_idP,
|
||||
num_sdu);
|
||||
|
||||
if(sdu[0]==0 && sdu[1]==0)
|
||||
num_sdu=0;
|
||||
|
||||
for (i = 0; i < num_sdu; i++) {
|
||||
if (rx_lcids[i] == MCH_SCHDL_INFO) {
|
||||
if (rx_lengths[i] & 0x01) {
|
||||
|
||||
@@ -2724,8 +2724,9 @@ int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_in
|
||||
LOG_I(RRC,"Setting SIStatus bit 0 to 1\n");
|
||||
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus_MBMS = 1;
|
||||
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag_MBMS = sib1_MBMS->systemInfoValueTag_r14;
|
||||
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
|
||||
|
||||
/*
|
||||
if (EPC_MODE_ENABLED)
|
||||
{
|
||||
int cell_valid = 0;
|
||||
|
||||
@@ -2781,8 +2782,8 @@ int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_in
|
||||
LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT );
|
||||
return 0;
|
||||
}
|
||||
@@ -2922,8 +2923,8 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index,
|
||||
LOG_I(RRC,"Setting SIStatus bit 0 to 1\n");
|
||||
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus = 1;
|
||||
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag;
|
||||
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
|
||||
{
|
||||
|
||||
if (EPC_MODE_ENABLED) {
|
||||
int cell_valid = 0;
|
||||
|
||||
if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) {
|
||||
@@ -2982,7 +2983,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index,
|
||||
LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ int nas_config_mbms(int interface_id, int thirdOctet, int fourthOctet, char *ifn
|
||||
bringInterfaceUp(interfaceName, 1);
|
||||
|
||||
if(!returnValue)
|
||||
LOG_I(OIP,"Interface %s successfuly configured, ip address %s, mask %s broadcast address %s\n",
|
||||
LOG_I(OIP,"Interface %s successfully configured, ip address %s, mask %s broadcast address %s\n",
|
||||
interfaceName, ipAddress, netMask, broadcastAddress);
|
||||
else
|
||||
LOG_E(OIP,"Interface %s couldn't be configured (ip address %s, mask %s broadcast address %s)\n",
|
||||
@@ -301,7 +301,7 @@ int nas_config_mbms_s1(int interface_id, int thirdOctet, int fourthOctet, char *
|
||||
printf("returnValue %d\n",returnValue);
|
||||
|
||||
if(!returnValue)
|
||||
LOG_I(OIP,"Interface %s successfuly configured, ip address %s, mask %s broadcast address %s\n",
|
||||
LOG_I(OIP,"Interface %s successfully configured, ip address %s, mask %s broadcast address %s\n",
|
||||
interfaceName, ipAddress, "255.255.255.0", broadcastAddress);
|
||||
else
|
||||
LOG_E(OIP,"Interface %s couldn't be configured (ip address %s, mask %s broadcast address %s)\n",
|
||||
|
||||
Reference in New Issue
Block a user